aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/elementary/src/lib
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-04-22 09:20:32 +1000
committerDavid Walter Seikel2012-04-22 09:20:32 +1000
commit3ad3455551be0d7859ecb02290376206d5e66498 (patch)
tree497917e12b4d7f458dff9765d9b53f64c4e03fc3 /libraries/elementary/src/lib
parentUpdate EFL to latest beta. (diff)
downloadSledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.zip
SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.gz
SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.bz2
SledjHamr-3ad3455551be0d7859ecb02290376206d5e66498.tar.xz
And actually include new files, plus elementary libraries.
Diffstat (limited to 'libraries/elementary/src/lib')
-rw-r--r--libraries/elementary/src/lib/Elementary.h258
-rw-r--r--libraries/elementary/src/lib/Elementary.h.in258
-rw-r--r--libraries/elementary/src/lib/Elementary_Cursor.h87
-rw-r--r--libraries/elementary/src/lib/Makefile.am253
-rw-r--r--libraries/elementary/src/lib/Makefile.in1731
-rw-r--r--libraries/elementary/src/lib/elc_ctxpopup.c1433
-rw-r--r--libraries/elementary/src/lib/elc_ctxpopup.h211
-rw-r--r--libraries/elementary/src/lib/elc_dayselector.c669
-rw-r--r--libraries/elementary/src/lib/elc_dayselector.h207
-rw-r--r--libraries/elementary/src/lib/elc_fileselector.c1249
-rw-r--r--libraries/elementary/src/lib/elc_fileselector.h313
-rw-r--r--libraries/elementary/src/lib/elc_fileselector_button.c520
-rw-r--r--libraries/elementary/src/lib/elc_fileselector_button.h306
-rw-r--r--libraries/elementary/src/lib/elc_fileselector_entry.c508
-rw-r--r--libraries/elementary/src/lib/elc_fileselector_entry.h349
-rw-r--r--libraries/elementary/src/lib/elc_hoversel.c507
-rw-r--r--libraries/elementary/src/lib/elc_hoversel.h224
-rw-r--r--libraries/elementary/src/lib/elc_multibuttonentry.c1742
-rw-r--r--libraries/elementary/src/lib/elc_multibuttonentry.h318
-rw-r--r--libraries/elementary/src/lib/elc_naviframe.c1530
-rw-r--r--libraries/elementary/src/lib/elc_naviframe.h406
-rw-r--r--libraries/elementary/src/lib/elc_player.c590
-rw-r--r--libraries/elementary/src/lib/elc_popup.c1454
-rw-r--r--libraries/elementary/src/lib/elc_popup.h269
-rw-r--r--libraries/elementary/src/lib/elc_scrolled_entry.c193
-rw-r--r--libraries/elementary/src/lib/elm_access.c536
-rw-r--r--libraries/elementary/src/lib/elm_actionslider.c505
-rw-r--r--libraries/elementary/src/lib/elm_actionslider.h139
-rw-r--r--libraries/elementary/src/lib/elm_app.h193
-rw-r--r--libraries/elementary/src/lib/elm_authors.h61
-rw-r--r--libraries/elementary/src/lib/elm_bg.c324
-rw-r--r--libraries/elementary/src/lib/elm_bg.h199
-rw-r--r--libraries/elementary/src/lib/elm_box.c683
-rw-r--r--libraries/elementary/src/lib/elm_box.h498
-rw-r--r--libraries/elementary/src/lib/elm_bubble.c368
-rw-r--r--libraries/elementary/src/lib/elm_bubble.h111
-rw-r--r--libraries/elementary/src/lib/elm_button.c534
-rw-r--r--libraries/elementary/src/lib/elm_button.h159
-rw-r--r--libraries/elementary/src/lib/elm_cache.h31
-rw-r--r--libraries/elementary/src/lib/elm_calendar.c1029
-rw-r--r--libraries/elementary/src/lib/elm_calendar.h510
-rw-r--r--libraries/elementary/src/lib/elm_check.c518
-rw-r--r--libraries/elementary/src/lib/elm_check.h105
-rw-r--r--libraries/elementary/src/lib/elm_clock.c681
-rw-r--r--libraries/elementary/src/lib/elm_clock.h308
-rw-r--r--libraries/elementary/src/lib/elm_cnp.c1635
-rw-r--r--libraries/elementary/src/lib/elm_cnp.h163
-rw-r--r--libraries/elementary/src/lib/elm_colorselector.c1279
-rw-r--r--libraries/elementary/src/lib/elm_colorselector.h192
-rw-r--r--libraries/elementary/src/lib/elm_config.c2215
-rw-r--r--libraries/elementary/src/lib/elm_config.h948
-rw-r--r--libraries/elementary/src/lib/elm_conform.c692
-rw-r--r--libraries/elementary/src/lib/elm_conform.h49
-rw-r--r--libraries/elementary/src/lib/elm_cursor.h122
-rw-r--r--libraries/elementary/src/lib/elm_datetime.c1075
-rw-r--r--libraries/elementary/src/lib/elm_datetime.h592
-rw-r--r--libraries/elementary/src/lib/elm_debug.h28
-rw-r--r--libraries/elementary/src/lib/elm_deprecated.h423
-rw-r--r--libraries/elementary/src/lib/elm_diskselector.c1401
-rw-r--r--libraries/elementary/src/lib/elm_diskselector.h440
-rw-r--r--libraries/elementary/src/lib/elm_entry.c3934
-rw-r--r--libraries/elementary/src/lib/elm_entry.h1730
-rw-r--r--libraries/elementary/src/lib/elm_factory.c338
-rw-r--r--libraries/elementary/src/lib/elm_factory.h6
-rw-r--r--libraries/elementary/src/lib/elm_finger.h45
-rw-r--r--libraries/elementary/src/lib/elm_flip.c1941
-rw-r--r--libraries/elementary/src/lib/elm_flip.h257
-rw-r--r--libraries/elementary/src/lib/elm_flipselector.c936
-rw-r--r--libraries/elementary/src/lib/elm_flipselector.h310
-rw-r--r--libraries/elementary/src/lib/elm_focus.h214
-rw-r--r--libraries/elementary/src/lib/elm_font.c221
-rw-r--r--libraries/elementary/src/lib/elm_font.h99
-rw-r--r--libraries/elementary/src/lib/elm_frame.c325
-rw-r--r--libraries/elementary/src/lib/elm_frame.h114
-rw-r--r--libraries/elementary/src/lib/elm_gen.h63
-rw-r--r--libraries/elementary/src/lib/elm_gen_common.h204
-rw-r--r--libraries/elementary/src/lib/elm_general.h365
-rw-r--r--libraries/elementary/src/lib/elm_gengrid.c2869
-rw-r--r--libraries/elementary/src/lib/elm_gengrid.h1615
-rw-r--r--libraries/elementary/src/lib/elm_genlist.c6231
-rw-r--r--libraries/elementary/src/lib/elm_genlist.h1874
-rw-r--r--libraries/elementary/src/lib/elm_gesture_layer.c3520
-rw-r--r--libraries/elementary/src/lib/elm_gesture_layer.h336
-rw-r--r--libraries/elementary/src/lib/elm_getting_started.h197
-rw-r--r--libraries/elementary/src/lib/elm_glview.c462
-rw-r--r--libraries/elementary/src/lib/elm_glview.h226
-rw-r--r--libraries/elementary/src/lib/elm_grid.c177
-rw-r--r--libraries/elementary/src/lib/elm_grid.h125
-rw-r--r--libraries/elementary/src/lib/elm_hover.c852
-rw-r--r--libraries/elementary/src/lib/elm_hover.h199
-rw-r--r--libraries/elementary/src/lib/elm_icon.c1006
-rw-r--r--libraries/elementary/src/lib/elm_icon.h566
-rw-r--r--libraries/elementary/src/lib/elm_image.c352
-rw-r--r--libraries/elementary/src/lib/elm_image.h390
-rw-r--r--libraries/elementary/src/lib/elm_index.c932
-rw-r--r--libraries/elementary/src/lib/elm_index.h373
-rw-r--r--libraries/elementary/src/lib/elm_intro.h34
-rw-r--r--libraries/elementary/src/lib/elm_label.c543
-rw-r--r--libraries/elementary/src/lib/elm_label.h180
-rw-r--r--libraries/elementary/src/lib/elm_layout.c967
-rw-r--r--libraries/elementary/src/lib/elm_layout.h638
-rw-r--r--libraries/elementary/src/lib/elm_list.c2004
-rw-r--r--libraries/elementary/src/lib/elm_list.h779
-rw-r--r--libraries/elementary/src/lib/elm_macros.h3
-rw-r--r--libraries/elementary/src/lib/elm_main.c1490
-rw-r--r--libraries/elementary/src/lib/elm_map.c5669
-rw-r--r--libraries/elementary/src/lib/elm_map.h1503
-rw-r--r--libraries/elementary/src/lib/elm_mapbuf.c305
-rw-r--r--libraries/elementary/src/lib/elm_mapbuf.h149
-rw-r--r--libraries/elementary/src/lib/elm_menu.c968
-rw-r--r--libraries/elementary/src/lib/elm_menu.h283
-rw-r--r--libraries/elementary/src/lib/elm_mirroring.h59
-rw-r--r--libraries/elementary/src/lib/elm_module.c251
-rw-r--r--libraries/elementary/src/lib/elm_need.h49
-rw-r--r--libraries/elementary/src/lib/elm_notify.c626
-rw-r--r--libraries/elementary/src/lib/elm_notify.h173
-rw-r--r--libraries/elementary/src/lib/elm_object.h376
-rw-r--r--libraries/elementary/src/lib/elm_object_item.h434
-rw-r--r--libraries/elementary/src/lib/elm_panel.c399
-rw-r--r--libraries/elementary/src/lib/elm_panel.h105
-rw-r--r--libraries/elementary/src/lib/elm_panes.c470
-rw-r--r--libraries/elementary/src/lib/elm_panes.h205
-rw-r--r--libraries/elementary/src/lib/elm_photo.c633
-rw-r--r--libraries/elementary/src/lib/elm_photo.h113
-rw-r--r--libraries/elementary/src/lib/elm_photocam.c1962
-rw-r--r--libraries/elementary/src/lib/elm_photocam.h318
-rw-r--r--libraries/elementary/src/lib/elm_plug.c128
-rw-r--r--libraries/elementary/src/lib/elm_plug.h57
-rw-r--r--libraries/elementary/src/lib/elm_priv.h315
-rw-r--r--libraries/elementary/src/lib/elm_progressbar.c462
-rw-r--r--libraries/elementary/src/lib/elm_progressbar.h289
-rw-r--r--libraries/elementary/src/lib/elm_radio.c520
-rw-r--r--libraries/elementary/src/lib/elm_radio.h159
-rw-r--r--libraries/elementary/src/lib/elm_route.c286
-rw-r--r--libraries/elementary/src/lib/elm_route.h54
-rw-r--r--libraries/elementary/src/lib/elm_scale.h36
-rw-r--r--libraries/elementary/src/lib/elm_scroll.h114
-rw-r--r--libraries/elementary/src/lib/elm_scroller.c765
-rw-r--r--libraries/elementary/src/lib/elm_scroller.h423
-rw-r--r--libraries/elementary/src/lib/elm_segment_control.c742
-rw-r--r--libraries/elementary/src/lib/elm_segment_control.h290
-rw-r--r--libraries/elementary/src/lib/elm_separator.c106
-rw-r--r--libraries/elementary/src/lib/elm_separator.h44
-rw-r--r--libraries/elementary/src/lib/elm_slider.c1073
-rw-r--r--libraries/elementary/src/lib/elm_slider.h400
-rw-r--r--libraries/elementary/src/lib/elm_slideshow.c776
-rw-r--r--libraries/elementary/src/lib/elm_slideshow.h546
-rw-r--r--libraries/elementary/src/lib/elm_spinner.c830
-rw-r--r--libraries/elementary/src/lib/elm_spinner.h426
-rw-r--r--libraries/elementary/src/lib/elm_store.c751
-rw-r--r--libraries/elementary/src/lib/elm_store.h402
-rw-r--r--libraries/elementary/src/lib/elm_table.c243
-rw-r--r--libraries/elementary/src/lib/elm_table.h159
-rw-r--r--libraries/elementary/src/lib/elm_theme.c706
-rw-r--r--libraries/elementary/src/lib/elm_theme.h436
-rw-r--r--libraries/elementary/src/lib/elm_thumb.c728
-rw-r--r--libraries/elementary/src/lib/elm_thumb.h263
-rw-r--r--libraries/elementary/src/lib/elm_toolbar.c2061
-rw-r--r--libraries/elementary/src/lib/elm_toolbar.h900
-rw-r--r--libraries/elementary/src/lib/elm_tooltip.h100
-rw-r--r--libraries/elementary/src/lib/elm_transit.c2357
-rw-r--r--libraries/elementary/src/lib/elm_transit.h824
-rw-r--r--libraries/elementary/src/lib/elm_util.c46
-rw-r--r--libraries/elementary/src/lib/elm_video.c581
-rw-r--r--libraries/elementary/src/lib/elm_video.h268
-rw-r--r--libraries/elementary/src/lib/elm_web.c1944
-rw-r--r--libraries/elementary/src/lib/elm_web.h1060
-rw-r--r--libraries/elementary/src/lib/elm_widget.c3949
-rw-r--r--libraries/elementary/src/lib/elm_widget.h751
-rw-r--r--libraries/elementary/src/lib/elm_win.c3428
-rw-r--r--libraries/elementary/src/lib/elm_win.h1371
-rw-r--r--libraries/elementary/src/lib/els_box.c256
-rw-r--r--libraries/elementary/src/lib/els_box.h1
-rw-r--r--libraries/elementary/src/lib/els_cursor.c506
-rw-r--r--libraries/elementary/src/lib/els_icon.c842
-rw-r--r--libraries/elementary/src/lib/els_icon.h27
-rw-r--r--libraries/elementary/src/lib/els_pan.c332
-rw-r--r--libraries/elementary/src/lib/els_pan.h10
-rw-r--r--libraries/elementary/src/lib/els_scroller.c3000
-rw-r--r--libraries/elementary/src/lib/els_scroller.h48
-rw-r--r--libraries/elementary/src/lib/els_tooltip.c951
-rw-r--r--libraries/elementary/src/lib/elu_ews_wm.c545
182 files changed, 128110 insertions, 0 deletions
diff --git a/libraries/elementary/src/lib/Elementary.h b/libraries/elementary/src/lib/Elementary.h
new file mode 100644
index 0000000..1ffa87a
--- /dev/null
+++ b/libraries/elementary/src/lib/Elementary.h
@@ -0,0 +1,258 @@
1/* This is the primary Elementary header file that includes all other useful
2 * headers.
3 *
4 * Elementary is distributed under the LGPLv2 license. Please see the COPYING
5 * file that was distributed with this source.
6 */
7#ifndef ELEMENTARY_H
8#define ELEMENTARY_H
9
10#define ELM_UNIX
11#undef ELM_WIN32
12#undef ELM_WINCE
13#define ELM_EDBUS
14#define ELM_EFREET
15#define ELM_ETHUMB
16#undef ELM_WEB
17#undef ELM_EMAP
18#undef ELM_DEBUG
19#define ELM_ALLOCA_H
20#define ELM_LIBINTL_H
21#define ELM_DIRENT_H
22
23/* Standard headers for standard system calls etc. */
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <sys/param.h>
32#include <math.h>
33#include <fnmatch.h>
34#include <limits.h>
35#include <ctype.h>
36#include <time.h>
37#ifdef ELM_DIRENT_H
38#include <dirent.h>
39#endif
40#include <pwd.h>
41#include <errno.h>
42
43#ifdef ELM_UNIX
44#include <locale.h>
45#ifdef ELM_LIBINTL_H
46#include <libintl.h>
47#endif
48#include <signal.h>
49#include <grp.h>
50#include <glob.h>
51#endif
52
53#ifdef ELM_ALLOCA_H
54#include <alloca.h>
55#endif
56
57#if defined (ELM_WIN32) || defined (ELM_WINCE)
58#include <malloc.h>
59#ifndef alloca
60#define alloca _alloca
61#endif
62#endif
63
64/* EFL headers */
65#include <Eina.h>
66#include <Eet.h>
67#include <Evas.h>
68#include <Evas_GL.h>
69#include <Ecore.h>
70#include <Ecore_Evas.h>
71#include <Ecore_File.h>
72#include <Ecore_IMF.h>
73#include <Ecore_Con.h>
74#include <Edje.h>
75
76#ifdef ELM_EDBUS
77#include <E_DBus.h>
78#endif
79
80#ifdef ELM_EFREET
81#include <Efreet.h>
82#include <Efreet_Mime.h>
83#include <Efreet_Trash.h>
84#endif
85
86#ifdef ELM_ETHUMB
87#include <Ethumb_Client.h>
88#endif
89
90#ifdef ELM_EMAP
91#include <EMap.h>
92#endif
93
94#ifdef EAPI
95# undef EAPI
96#endif
97
98#ifdef _WIN32
99# ifdef ELEMENTARY_BUILD
100# ifdef DLL_EXPORT
101# define EAPI __declspec(dllexport)
102# else
103# define EAPI
104# endif /* ! DLL_EXPORT */
105# else
106# define EAPI __declspec(dllimport)
107# endif /* ! EFL_EVAS_BUILD */
108#else
109# ifdef __GNUC__
110# if __GNUC__ >= 4
111# define EAPI __attribute__ ((visibility("default")))
112# else
113# define EAPI
114# endif
115# else
116# define EAPI
117# endif
118#endif /* ! _WIN32 */
119
120#ifdef _WIN32
121# define EAPI_MAIN
122#else
123# define EAPI_MAIN EAPI
124#endif
125
126/* allow usage from c++ */
127#ifdef __cplusplus
128extern "C"
129{
130#endif
131
132/* docs */
133#include <elm_intro.h> // OK
134#include <elm_getting_started.h> // OK
135#include <elm_authors.h> // OK
136
137#define ELM_VERSION_MAJOR 1
138#define ELM_VERSION_MINOR 0
139
140typedef struct _Elm_Version
141{
142 int major;
143 int minor;
144 int micro;
145 int revision;
146} Elm_Version;
147
148EAPI extern Elm_Version *elm_version;
149
150/* include these first for general used definitions */
151#include <elm_general.h> // OK
152#include <elm_tooltip.h> // OK
153#include <elm_object_item.h> // OK
154
155/* special widgets - types used elsewhere */
156#include <elm_icon.h> // OK
157#include <elm_scroller.h> // OK
158#include <elm_entry.h> // OK
159#include <elm_list.h> // OK
160
161/* other includes */
162// Tom Hacohen
163#include <elc_ctxpopup.h> // OK
164#include <elc_dayselector.h> // OK
165#include <elc_fileselector_button.h> // OK
166#include <elc_fileselector_entry.h> // OK
167#include <elc_fileselector.h> // OK
168#include <elc_hoversel.h> // OK
169#include <elc_multibuttonentry.h> // OK
170#include <elc_naviframe.h> // OK
171#include <elc_popup.h> // OK
172#include <elm_actionslider.h> // OK
173#include <elm_app.h> // OK
174#include <elm_bg.h> // OK
175#include <elm_box.h> // OK
176
177// Daniel Juyung Seo
178#include <elm_bubble.h> // OK
179#include <elm_button.h> // OK
180#include <elm_cache.h> // OK
181#include <elm_calendar.h> // OK
182#include <elm_check.h> // OK
183#include <elm_clock.h> // OK
184#include <elm_cnp.h> // OK
185#include <elm_colorselector.h> // OK
186#include <elm_config.h> // OK
187#include <elm_conform.h> // OK
188#include <elm_cursor.h> // OK
189#include <elm_datetime.h> // OK
190#include <elm_debug.h> // OK
191#include <elm_diskselector.h> // OK
192
193// Chuneon Park
194//#include <elm_factory.h> // OK
195#include <elm_finger.h> // OK
196#include <elm_flip.h> // OK
197#include <elm_flipselector.h> // OK
198#include <elm_focus.h> // OK
199#include <elm_font.h> // OK
200#include <elm_frame.h> // OK
201#include <elm_gen.h> // OK
202#include <elm_gengrid.h> // OK
203#include <elm_genlist.h> // OK
204#include <elm_gesture_layer.h> // OK
205#include <elm_glview.h> // OK
206#include <elm_grid.h> // OK
207
208// Woohyun Jung
209#include <elm_hover.h> // OK
210#include <elm_image.h> // OK
211#include <elm_index.h> // OK
212#include <elm_label.h> // OK
213#include <elm_layout.h> // OK
214#include <elm_macros.h> // OK
215#include <elm_mapbuf.h> // OK
216#include <elm_map.h> // OK
217#include <elm_menu.h> // OK
218#include <elm_mirroring.h> // OK
219#include <elm_need.h> // OK
220#include <elm_notify.h> // OK
221#include <elm_object.h> // OK
222
223// SanjeevBA
224#include <elm_panel.h> // OK
225#include <elm_panes.h> // OK
226#include <elm_photocam.h> // OK
227#include <elm_photo.h> // OK
228#include <elm_plug.h> // OK
229#include <elm_progressbar.h> // OK
230#include <elm_radio.h> // OK
231#include <elm_route.h> // OK
232#include <elm_scale.h> // OK
233#include <elm_scroll.h> // OK
234#include <elm_segment_control.h> // OK
235
236// Carsten Haitzler
237#include <elm_separator.h> // OK
238#include <elm_slider.h> // OK
239#include <elm_slideshow.h> // OK
240#include <elm_spinner.h> // OK
241#include <elm_store.h> // OK
242#include <elm_table.h> // OK
243#include <elm_theme.h> // OK
244#include <elm_thumb.h> // OK
245#include <elm_toolbar.h> // OK
246#include <elm_transit.h> // OK
247#include <elm_video.h> // OK
248#include <elm_web.h>
249#include <elm_win.h> // OK
250
251/* include deprecated calls last of all */
252#include <elm_deprecated.h> // OK
253
254#ifdef __cplusplus
255}
256#endif
257
258#endif
diff --git a/libraries/elementary/src/lib/Elementary.h.in b/libraries/elementary/src/lib/Elementary.h.in
new file mode 100644
index 0000000..37ce93b
--- /dev/null
+++ b/libraries/elementary/src/lib/Elementary.h.in
@@ -0,0 +1,258 @@
1/* This is the primary Elementary header file that includes all other useful
2 * headers.
3 *
4 * Elementary is distributed under the LGPLv2 license. Please see the COPYING
5 * file that was distributed with this source.
6 */
7#ifndef ELEMENTARY_H
8#define ELEMENTARY_H
9
10@ELM_UNIX_DEF@ ELM_UNIX
11@ELM_WIN32_DEF@ ELM_WIN32
12@ELM_WINCE_DEF@ ELM_WINCE
13@ELM_EDBUS_DEF@ ELM_EDBUS
14@ELM_EFREET_DEF@ ELM_EFREET
15@ELM_ETHUMB_DEF@ ELM_ETHUMB
16@ELM_WEB_DEF@ ELM_WEB
17@ELM_EMAP_DEF@ ELM_EMAP
18@ELM_DEBUG_DEF@ ELM_DEBUG
19@ELM_ALLOCA_H_DEF@ ELM_ALLOCA_H
20@ELM_LIBINTL_H_DEF@ ELM_LIBINTL_H
21@ELM_DIRENT_H_DEF@ ELM_DIRENT_H
22
23/* Standard headers for standard system calls etc. */
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <sys/param.h>
32#include <math.h>
33#include <fnmatch.h>
34#include <limits.h>
35#include <ctype.h>
36#include <time.h>
37#ifdef ELM_DIRENT_H
38#include <dirent.h>
39#endif
40#include <pwd.h>
41#include <errno.h>
42
43#ifdef ELM_UNIX
44#include <locale.h>
45#ifdef ELM_LIBINTL_H
46#include <libintl.h>
47#endif
48#include <signal.h>
49#include <grp.h>
50#include <glob.h>
51#endif
52
53#ifdef ELM_ALLOCA_H
54#include <alloca.h>
55#endif
56
57#if defined (ELM_WIN32) || defined (ELM_WINCE)
58#include <malloc.h>
59#ifndef alloca
60#define alloca _alloca
61#endif
62#endif
63
64/* EFL headers */
65#include <Eina.h>
66#include <Eet.h>
67#include <Evas.h>
68#include <Evas_GL.h>
69#include <Ecore.h>
70#include <Ecore_Evas.h>
71#include <Ecore_File.h>
72@ELEMENTARY_ECORE_IMF_INC@
73@ELEMENTARY_ECORE_CON_INC@
74#include <Edje.h>
75
76#ifdef ELM_EDBUS
77#include <E_DBus.h>
78#endif
79
80#ifdef ELM_EFREET
81#include <Efreet.h>
82#include <Efreet_Mime.h>
83#include <Efreet_Trash.h>
84#endif
85
86#ifdef ELM_ETHUMB
87#include <Ethumb_Client.h>
88#endif
89
90#ifdef ELM_EMAP
91#include <EMap.h>
92#endif
93
94#ifdef EAPI
95# undef EAPI
96#endif
97
98#ifdef _WIN32
99# ifdef ELEMENTARY_BUILD
100# ifdef DLL_EXPORT
101# define EAPI __declspec(dllexport)
102# else
103# define EAPI
104# endif /* ! DLL_EXPORT */
105# else
106# define EAPI __declspec(dllimport)
107# endif /* ! EFL_EVAS_BUILD */
108#else
109# ifdef __GNUC__
110# if __GNUC__ >= 4
111# define EAPI __attribute__ ((visibility("default")))
112# else
113# define EAPI
114# endif
115# else
116# define EAPI
117# endif
118#endif /* ! _WIN32 */
119
120#ifdef _WIN32
121# define EAPI_MAIN
122#else
123# define EAPI_MAIN EAPI
124#endif
125
126/* allow usage from c++ */
127#ifdef __cplusplus
128extern "C"
129{
130#endif
131
132/* docs */
133#include <elm_intro.h> // OK
134#include <elm_getting_started.h> // OK
135#include <elm_authors.h> // OK
136
137#define ELM_VERSION_MAJOR @VMAJ@
138#define ELM_VERSION_MINOR @VMIN@
139
140typedef struct _Elm_Version
141{
142 int major;
143 int minor;
144 int micro;
145 int revision;
146} Elm_Version;
147
148EAPI extern Elm_Version *elm_version;
149
150/* include these first for general used definitions */
151#include <elm_general.h> // OK
152#include <elm_tooltip.h> // OK
153#include <elm_object_item.h> // OK
154
155/* special widgets - types used elsewhere */
156#include <elm_icon.h> // OK
157#include <elm_scroller.h> // OK
158#include <elm_entry.h> // OK
159#include <elm_list.h> // OK
160
161/* other includes */
162// Tom Hacohen
163#include <elc_ctxpopup.h> // OK
164#include <elc_dayselector.h> // OK
165#include <elc_fileselector_button.h> // OK
166#include <elc_fileselector_entry.h> // OK
167#include <elc_fileselector.h> // OK
168#include <elc_hoversel.h> // OK
169#include <elc_multibuttonentry.h> // OK
170#include <elc_naviframe.h> // OK
171#include <elc_popup.h> // OK
172#include <elm_actionslider.h> // OK
173#include <elm_app.h> // OK
174#include <elm_bg.h> // OK
175#include <elm_box.h> // OK
176
177// Daniel Juyung Seo
178#include <elm_bubble.h> // OK
179#include <elm_button.h> // OK
180#include <elm_cache.h> // OK
181#include <elm_calendar.h> // OK
182#include <elm_check.h> // OK
183#include <elm_clock.h> // OK
184#include <elm_cnp.h> // OK
185#include <elm_colorselector.h> // OK
186#include <elm_config.h> // OK
187#include <elm_conform.h> // OK
188#include <elm_cursor.h> // OK
189#include <elm_datetime.h> // OK
190#include <elm_debug.h> // OK
191#include <elm_diskselector.h> // OK
192
193// Chuneon Park
194//#include <elm_factory.h> // OK
195#include <elm_finger.h> // OK
196#include <elm_flip.h> // OK
197#include <elm_flipselector.h> // OK
198#include <elm_focus.h> // OK
199#include <elm_font.h> // OK
200#include <elm_frame.h> // OK
201#include <elm_gen.h> // OK
202#include <elm_gengrid.h> // OK
203#include <elm_genlist.h> // OK
204#include <elm_gesture_layer.h> // OK
205#include <elm_glview.h> // OK
206#include <elm_grid.h> // OK
207
208// Woohyun Jung
209#include <elm_hover.h> // OK
210#include <elm_image.h> // OK
211#include <elm_index.h> // OK
212#include <elm_label.h> // OK
213#include <elm_layout.h> // OK
214#include <elm_macros.h> // OK
215#include <elm_mapbuf.h> // OK
216#include <elm_map.h> // OK
217#include <elm_menu.h> // OK
218#include <elm_mirroring.h> // OK
219#include <elm_need.h> // OK
220#include <elm_notify.h> // OK
221#include <elm_object.h> // OK
222
223// SanjeevBA
224#include <elm_panel.h> // OK
225#include <elm_panes.h> // OK
226#include <elm_photocam.h> // OK
227#include <elm_photo.h> // OK
228#include <elm_plug.h> // OK
229#include <elm_progressbar.h> // OK
230#include <elm_radio.h> // OK
231#include <elm_route.h> // OK
232#include <elm_scale.h> // OK
233#include <elm_scroll.h> // OK
234#include <elm_segment_control.h> // OK
235
236// Carsten Haitzler
237#include <elm_separator.h> // OK
238#include <elm_slider.h> // OK
239#include <elm_slideshow.h> // OK
240#include <elm_spinner.h> // OK
241#include <elm_store.h> // OK
242#include <elm_table.h> // OK
243#include <elm_theme.h> // OK
244#include <elm_thumb.h> // OK
245#include <elm_toolbar.h> // OK
246#include <elm_transit.h> // OK
247#include <elm_video.h> // OK
248#include <elm_web.h>
249#include <elm_win.h> // OK
250
251/* include deprecated calls last of all */
252#include <elm_deprecated.h> // OK
253
254#ifdef __cplusplus
255}
256#endif
257
258#endif
diff --git a/libraries/elementary/src/lib/Elementary_Cursor.h b/libraries/elementary/src/lib/Elementary_Cursor.h
new file mode 100644
index 0000000..f77154b
--- /dev/null
+++ b/libraries/elementary/src/lib/Elementary_Cursor.h
@@ -0,0 +1,87 @@
1#ifndef _ELM_CURSOR_H
2#define _ELM_CURSOR_H
3
4/**
5 * @file
6 * @brief Defines the various cursor types for the X Windows system.
7 */
8
9#define ELM_CURSOR_X "x"
10#define ELM_CURSOR_ARROW "arrow"
11#define ELM_CURSOR_BASED_ARROW_DOWN "based_arrow_down"
12#define ELM_CURSOR_BASED_ARROW_UP "based_arrow_up"
13#define ELM_CURSOR_BOAT "boat"
14#define ELM_CURSOR_BOGOSITY "bogosity"
15#define ELM_CURSOR_BOTTOM_LEFT_CORNER "bottom_left_corner"
16#define ELM_CURSOR_BOTTOM_RIGHT_CORNER "bottom_right_corner"
17#define ELM_CURSOR_BOTTOM_SIDE "bottom_side"
18#define ELM_CURSOR_BOTTOM_TEE "bottom_tee"
19#define ELM_CURSOR_BOX_SPIRAL "box_spiral"
20#define ELM_CURSOR_CENTER_PTR "center_ptr"
21#define ELM_CURSOR_CIRCLE "circle"
22#define ELM_CURSOR_CLOCK "clock"
23#define ELM_CURSOR_COFFEE_MUG "coffee_mug"
24#define ELM_CURSOR_CROSS "cross"
25#define ELM_CURSOR_CROSS_REVERSE "cross_reverse"
26#define ELM_CURSOR_CROSSHAIR "crosshair"
27#define ELM_CURSOR_DIAMOND_CROSS "diamond_cross"
28#define ELM_CURSOR_DOT "dot"
29#define ELM_CURSOR_DOT_BOX_MASK "dot_box_mask"
30#define ELM_CURSOR_DOUBLE_ARROW "double_arrow"
31#define ELM_CURSOR_DRAFT_LARGE "draft_large"
32#define ELM_CURSOR_DRAFT_SMALL "draft_small"
33#define ELM_CURSOR_DRAPED_BOX "draped_box"
34#define ELM_CURSOR_EXCHANGE "exchange"
35#define ELM_CURSOR_FLEUR "fleur"
36#define ELM_CURSOR_GOBBLER "gobbler"
37#define ELM_CURSOR_GUMBY "gumby"
38#define ELM_CURSOR_HAND1 "hand1"
39#define ELM_CURSOR_HAND2 "hand2"
40#define ELM_CURSOR_HEART "heart"
41#define ELM_CURSOR_ICON "icon"
42#define ELM_CURSOR_IRON_CROSS "iron_cross"
43#define ELM_CURSOR_LEFT_PTR "left_ptr"
44#define ELM_CURSOR_LEFT_SIDE "left_side"
45#define ELM_CURSOR_LEFT_TEE "left_tee"
46#define ELM_CURSOR_LEFTBUTTON "leftbutton"
47#define ELM_CURSOR_LL_ANGLE "ll_angle"
48#define ELM_CURSOR_LR_ANGLE "lr_angle"
49#define ELM_CURSOR_MAN "man"
50#define ELM_CURSOR_MIDDLEBUTTON "middlebutton"
51#define ELM_CURSOR_MOUSE "mouse"
52#define ELM_CURSOR_PENCIL "pencil"
53#define ELM_CURSOR_PIRATE "pirate"
54#define ELM_CURSOR_PLUS "plus"
55#define ELM_CURSOR_QUESTION_ARROW "question_arrow"
56#define ELM_CURSOR_RIGHT_PTR "right_ptr"
57#define ELM_CURSOR_RIGHT_SIDE "right_side"
58#define ELM_CURSOR_RIGHT_TEE "right_tee"
59#define ELM_CURSOR_RIGHTBUTTON "rightbutton"
60#define ELM_CURSOR_RTL_LOGO "rtl_logo"
61#define ELM_CURSOR_SAILBOAT "sailboat"
62#define ELM_CURSOR_SB_DOWN_ARROW "sb_down_arrow"
63#define ELM_CURSOR_SB_H_DOUBLE_ARROW "sb_h_double_arrow"
64#define ELM_CURSOR_SB_LEFT_ARROW "sb_left_arrow"
65#define ELM_CURSOR_SB_RIGHT_ARROW "sb_right_arrow"
66#define ELM_CURSOR_SB_UP_ARROW "sb_up_arrow"
67#define ELM_CURSOR_SB_V_DOUBLE_ARROW "sb_v_double_arrow"
68#define ELM_CURSOR_SHUTTLE "shuttle"
69#define ELM_CURSOR_SIZING "sizing"
70#define ELM_CURSOR_SPIDER "spider"
71#define ELM_CURSOR_SPRAYCAN "spraycan"
72#define ELM_CURSOR_STAR "star"
73#define ELM_CURSOR_TARGET "target"
74#define ELM_CURSOR_TCROSS "tcross"
75#define ELM_CURSOR_TOP_LEFT_ARROW "top_left_arrow"
76#define ELM_CURSOR_TOP_LEFT_CORNER "top_left_corner"
77#define ELM_CURSOR_TOP_RIGHT_CORNER "top_right_corner"
78#define ELM_CURSOR_TOP_SIDE "top_side"
79#define ELM_CURSOR_TOP_TEE "top_tee"
80#define ELM_CURSOR_TREK "trek"
81#define ELM_CURSOR_UL_ANGLE "ul_angle"
82#define ELM_CURSOR_UMBRELLA "umbrella"
83#define ELM_CURSOR_UR_ANGLE "ur_angle"
84#define ELM_CURSOR_WATCH "watch"
85#define ELM_CURSOR_XTERM "xterm"
86
87#endif // ifndef _ELM_CURSOR_H
diff --git a/libraries/elementary/src/lib/Makefile.am b/libraries/elementary/src/lib/Makefile.am
new file mode 100644
index 0000000..844f481
--- /dev/null
+++ b/libraries/elementary/src/lib/Makefile.am
@@ -0,0 +1,253 @@
1AUTOMAKE_OPTIONS = 1.4 foreign
2MAINTAINERCLEANFILES = Makefile.in
3
4AM_CPPFLAGS = \
5-DELM_INTERNAL_API_ARGESFSDFEFC=1 \
6-DMODULES_PATH=\"$(libdir)/elementary/modules\" \
7-I. \
8-I$(top_builddir) \
9-I$(top_srcdir) \
10-I$(top_srcdir)/src/lib \
11-I$(top_builddir)/src/lib \
12-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
13-DLOCALE_DIR=\"@LOCALE_DIR@\" \
14-DPACKAGE_LIB_DIR=\"$(libdir)\" \
15@ELEMENTARY_CFLAGS@ \
16@ELEMENTARY_X_CFLAGS@ \
17@ELEMENTARY_FB_CFLAGS@ \
18@ELEMENTARY_SDL_CFLAGS@ \
19@ELEMENTARY_WIN32_CFLAGS@ \
20@ELEMENTARY_WINCE_CFLAGS@ \
21@ELEMENTARY_EDBUS_CFLAGS@ \
22@ELEMENTARY_EFREET_CFLAGS@ \
23@ELEMENTARY_ETHUMB_CFLAGS@ \
24@ELEMENTARY_WEB_CFLAGS@ \
25@ELEMENTARY_EMAP_CFLAGS@ \
26@ELEMENTARY_ECORE_CON_CFLAGS@ \
27@ELEMENTARY_ECORE_IMF_CFLAGS@ \
28@EVIL_CFLAGS@ \
29@EIO_CFLAGS@ \
30@EMOTION_CFLAGS@
31
32if ELEMENTARY_WINDOWS_BUILD
33AM_CPPFLAGS += -DELEMENTARY_BUILD
34endif
35
36lib_LTLIBRARIES = libelementary.la
37
38includes_HEADERS = \
39Elementary.h \
40Elementary_Cursor.h
41includesdir = $(includedir)/elementary-@VMAJ@
42
43includesunstable_HEADERS = \
44elm_widget.h
45includesunstabledir = $(includedir)/elementary-@VMAJ@
46
47includesub_HEADERS = \
48elc_ctxpopup.h \
49elc_dayselector.h \
50elc_fileselector_button.h \
51elc_fileselector_entry.h \
52elc_fileselector.h \
53elc_hoversel.h \
54elc_multibuttonentry.h \
55elc_naviframe.h \
56elc_popup.h \
57elm_actionslider.h \
58elm_app.h \
59elm_authors.h \
60elm_bg.h \
61elm_box.h \
62elm_bubble.h \
63elm_button.h \
64elm_cache.h \
65elm_calendar.h \
66elm_check.h \
67elm_clock.h \
68elm_cnp.h \
69elm_colorselector.h \
70elm_config.h \
71elm_conform.h \
72elm_cursor.h \
73elm_datetime.h \
74elm_debug.h \
75elm_deprecated.h \
76elm_diskselector.h \
77elm_entry.h \
78elm_finger.h \
79elm_flip.h \
80elm_flipselector.h \
81elm_focus.h \
82elm_font.h \
83elm_frame.h \
84elm_gen.h \
85elm_general.h \
86elm_gengrid.h \
87elm_genlist.h \
88elm_gesture_layer.h \
89elm_getting_started.h \
90elm_glview.h \
91elm_grid.h \
92elm_hover.h \
93elm_icon.h \
94elm_image.h \
95elm_plug.h \
96elm_index.h \
97elm_intro.h \
98elm_label.h \
99elm_layout.h \
100elm_list.h \
101elm_macros.h \
102elm_mapbuf.h \
103elm_map.h \
104elm_menu.h \
105elm_mirroring.h \
106elm_need.h \
107elm_notify.h \
108elm_object.h \
109elm_object_item.h \
110elm_panel.h \
111elm_panes.h \
112elm_photocam.h \
113elm_photo.h \
114elm_progressbar.h \
115elm_radio.h \
116elm_route.h \
117elm_scale.h \
118elm_scroller.h \
119elm_scroll.h \
120elm_segment_control.h \
121elm_separator.h \
122elm_slider.h \
123elm_slideshow.h \
124elm_spinner.h \
125elm_store.h \
126elm_table.h \
127elm_theme.h \
128elm_thumb.h \
129elm_toolbar.h \
130elm_tooltip.h \
131elm_transit.h \
132elm_video.h \
133elm_web.h \
134elm_win.h
135includesubdir = $(includedir)/elementary-@VMAJ@/
136
137libelementary_la_SOURCES = \
138elm_priv.h \
139elc_ctxpopup.c \
140elc_dayselector.c \
141elc_popup.c \
142elc_fileselector_button.c \
143elc_fileselector.c \
144elc_fileselector_entry.c \
145elc_hoversel.c \
146elc_naviframe.c \
147elc_multibuttonentry.c \
148elc_player.c \
149elc_scrolled_entry.c \
150elm_access.c \
151elm_actionslider.c \
152elm_bg.c \
153elm_box.c \
154elm_bubble.c \
155elm_button.c \
156elm_calendar.c \
157elm_check.c \
158elm_clock.c \
159elm_cnp.c \
160elm_colorselector.c \
161elm_config.c \
162elm_conform.c \
163elm_datetime.c \
164elm_diskselector.c \
165elm_entry.c \
166elm_flip.c \
167elm_flipselector.c \
168elm_font.c \
169elm_frame.c \
170elm_gengrid.c \
171elm_genlist.c \
172elm_gen_common.h \
173elm_gesture_layer.c \
174elm_glview.c \
175elm_grid.c \
176elm_hover.c \
177elm_icon.c \
178elm_image.c \
179elm_plug.c \
180elm_index.c \
181elm_label.c \
182elm_layout.c \
183elm_list.c \
184elm_main.c \
185elm_mapbuf.c \
186elm_map.c \
187elm_menu.c \
188elm_module.c \
189elm_notify.c \
190elm_panel.c \
191elm_panes.c \
192elm_photo.c \
193elm_photocam.c \
194elm_progressbar.c \
195elm_radio.c \
196elm_route.c \
197elm_scroller.c \
198elm_segment_control.c \
199elm_separator.c \
200elm_slider.c \
201elm_slideshow.c \
202elm_spinner.c \
203elm_store.c \
204elm_table.c \
205elm_theme.c \
206elm_thumb.c \
207elm_toolbar.c \
208elm_transit.c \
209elm_util.c \
210elm_video.c \
211elm_web.c \
212elm_widget.c \
213elm_win.c \
214els_box.c \
215els_box.h \
216els_cursor.c \
217els_icon.c \
218els_icon.h \
219els_pan.c \
220els_pan.h \
221els_scroller.c \
222els_scroller.h \
223els_tooltip.c \
224elu_ews_wm.c
225
226libelementary_la_CFLAGS =
227libelementary_la_LIBADD = \
228@my_libs@ \
229@dlopen_libs@ \
230@ELEMENTARY_LIBS@ \
231@ELEMENTARY_X_LIBS@ \
232@ELEMENTARY_FB_LIBS@ \
233@ELEMENTARY_SDL_LIBS@ \
234@ELEMENTARY_WIN32_LIBS@ \
235@ELEMENTARY_WINCE_LIBS@ \
236@ELEMENTARY_EDBUS_LIBS@ \
237@ELEMENTARY_EFREET_LIBS@ \
238@ELEMENTARY_ETHUMB_LIBS@ \
239@ELEMENTARY_WEB_LIBS@ \
240@ELEMENTARY_EMAP_LIBS@ \
241@ELEMENTARY_ECORE_IMF_LIBS@ \
242@ELEMENTARY_ECORE_CON_LIBS@ \
243@EVIL_LIBS@ \
244@EIO_LIBS@ \
245@EMOTION_LIBS@
246
247libelementary_la_LDFLAGS = \
248-no-undefined @lt_enable_auto_import@ \
249-version-info @version_info@ @release_info@
250
251EXTRA_DIST = \
252elm_factory.h \
253elm_factory.c
diff --git a/libraries/elementary/src/lib/Makefile.in b/libraries/elementary/src/lib/Makefile.in
new file mode 100644
index 0000000..f53e41b
--- /dev/null
+++ b/libraries/elementary/src/lib/Makefile.in
@@ -0,0 +1,1731 @@
1# Makefile.in generated by automake 1.11.1 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
6# Inc.
7# This Makefile.in is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
13# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14# PARTICULAR PURPOSE.
15
16@SET_MAKE@
17
18
19VPATH = @srcdir@
20pkgdatadir = $(datadir)/@PACKAGE@
21pkgincludedir = $(includedir)/@PACKAGE@
22pkglibdir = $(libdir)/@PACKAGE@
23pkglibexecdir = $(libexecdir)/@PACKAGE@
24am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
25install_sh_DATA = $(install_sh) -c -m 644
26install_sh_PROGRAM = $(install_sh) -c
27install_sh_SCRIPT = $(install_sh) -c
28INSTALL_HEADER = $(INSTALL_DATA)
29transform = $(program_transform_name)
30NORMAL_INSTALL = :
31PRE_INSTALL = :
32POST_INSTALL = :
33NORMAL_UNINSTALL = :
34PRE_UNINSTALL = :
35POST_UNINSTALL = :
36build_triplet = @build@
37host_triplet = @host@
38@ELEMENTARY_WINDOWS_BUILD_TRUE@am__append_1 = -DELEMENTARY_BUILD
39subdir = src/lib
40DIST_COMMON = $(includes_HEADERS) $(includesub_HEADERS) \
41 $(includesunstable_HEADERS) $(srcdir)/Elementary.h.in \
42 $(srcdir)/Makefile.am $(srcdir)/Makefile.in
43ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
44am__aclocal_m4_deps = $(top_srcdir)/m4/ac_attribute.m4 \
45 $(top_srcdir)/m4/efl_binary.m4 \
46 $(top_srcdir)/m4/efl_compiler_flag.m4 \
47 $(top_srcdir)/m4/efl_doxygen.m4 \
48 $(top_srcdir)/m4/efl_examples.m4 \
49 $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/gettext.m4 \
50 $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \
51 $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
52 $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libtool.m4 \
53 $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
54 $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
55 $(top_srcdir)/m4/nls.m4 $(top_srcdir)/m4/po.m4 \
56 $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac
57am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
58 $(ACLOCAL_M4)
59mkinstalldirs = $(install_sh) -d
60CONFIG_HEADER = $(top_builddir)/elementary_config.h
61CONFIG_CLEAN_FILES = Elementary.h
62CONFIG_CLEAN_VPATH_FILES =
63am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
64am__vpath_adj = case $$p in \
65 $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
66 *) f=$$p;; \
67 esac;
68am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
69am__install_max = 40
70am__nobase_strip_setup = \
71 srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
72am__nobase_strip = \
73 for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
74am__nobase_list = $(am__nobase_strip_setup); \
75 for p in $$list; do echo "$$p $$p"; done | \
76 sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
77 $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
78 if (++n[$$2] == $(am__install_max)) \
79 { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
80 END { for (dir in files) print dir, files[dir] }'
81am__base_list = \
82 sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
83 sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
84am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includesdir)" \
85 "$(DESTDIR)$(includesubdir)" \
86 "$(DESTDIR)$(includesunstabledir)"
87LTLIBRARIES = $(lib_LTLIBRARIES)
88libelementary_la_DEPENDENCIES =
89am_libelementary_la_OBJECTS = libelementary_la-elc_ctxpopup.lo \
90 libelementary_la-elc_dayselector.lo \
91 libelementary_la-elc_popup.lo \
92 libelementary_la-elc_fileselector_button.lo \
93 libelementary_la-elc_fileselector.lo \
94 libelementary_la-elc_fileselector_entry.lo \
95 libelementary_la-elc_hoversel.lo \
96 libelementary_la-elc_naviframe.lo \
97 libelementary_la-elc_multibuttonentry.lo \
98 libelementary_la-elc_player.lo \
99 libelementary_la-elc_scrolled_entry.lo \
100 libelementary_la-elm_access.lo \
101 libelementary_la-elm_actionslider.lo \
102 libelementary_la-elm_bg.lo libelementary_la-elm_box.lo \
103 libelementary_la-elm_bubble.lo libelementary_la-elm_button.lo \
104 libelementary_la-elm_calendar.lo libelementary_la-elm_check.lo \
105 libelementary_la-elm_clock.lo libelementary_la-elm_cnp.lo \
106 libelementary_la-elm_colorselector.lo \
107 libelementary_la-elm_config.lo libelementary_la-elm_conform.lo \
108 libelementary_la-elm_datetime.lo \
109 libelementary_la-elm_diskselector.lo \
110 libelementary_la-elm_entry.lo libelementary_la-elm_flip.lo \
111 libelementary_la-elm_flipselector.lo \
112 libelementary_la-elm_font.lo libelementary_la-elm_frame.lo \
113 libelementary_la-elm_gengrid.lo \
114 libelementary_la-elm_genlist.lo \
115 libelementary_la-elm_gesture_layer.lo \
116 libelementary_la-elm_glview.lo libelementary_la-elm_grid.lo \
117 libelementary_la-elm_hover.lo libelementary_la-elm_icon.lo \
118 libelementary_la-elm_image.lo libelementary_la-elm_plug.lo \
119 libelementary_la-elm_index.lo libelementary_la-elm_label.lo \
120 libelementary_la-elm_layout.lo libelementary_la-elm_list.lo \
121 libelementary_la-elm_main.lo libelementary_la-elm_mapbuf.lo \
122 libelementary_la-elm_map.lo libelementary_la-elm_menu.lo \
123 libelementary_la-elm_module.lo libelementary_la-elm_notify.lo \
124 libelementary_la-elm_panel.lo libelementary_la-elm_panes.lo \
125 libelementary_la-elm_photo.lo libelementary_la-elm_photocam.lo \
126 libelementary_la-elm_progressbar.lo \
127 libelementary_la-elm_radio.lo libelementary_la-elm_route.lo \
128 libelementary_la-elm_scroller.lo \
129 libelementary_la-elm_segment_control.lo \
130 libelementary_la-elm_separator.lo \
131 libelementary_la-elm_slider.lo \
132 libelementary_la-elm_slideshow.lo \
133 libelementary_la-elm_spinner.lo libelementary_la-elm_store.lo \
134 libelementary_la-elm_table.lo libelementary_la-elm_theme.lo \
135 libelementary_la-elm_thumb.lo libelementary_la-elm_toolbar.lo \
136 libelementary_la-elm_transit.lo libelementary_la-elm_util.lo \
137 libelementary_la-elm_video.lo libelementary_la-elm_web.lo \
138 libelementary_la-elm_widget.lo libelementary_la-elm_win.lo \
139 libelementary_la-els_box.lo libelementary_la-els_cursor.lo \
140 libelementary_la-els_icon.lo libelementary_la-els_pan.lo \
141 libelementary_la-els_scroller.lo \
142 libelementary_la-els_tooltip.lo libelementary_la-elu_ews_wm.lo
143libelementary_la_OBJECTS = $(am_libelementary_la_OBJECTS)
144AM_V_lt = $(am__v_lt_$(V))
145am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
146am__v_lt_0 = --silent
147libelementary_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
148 $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
149 $(libelementary_la_CFLAGS) $(CFLAGS) \
150 $(libelementary_la_LDFLAGS) $(LDFLAGS) -o $@
151DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
152depcomp = $(SHELL) $(top_srcdir)/depcomp
153am__depfiles_maybe = depfiles
154am__mv = mv -f
155COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
156 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
157LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
158 $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
159 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
160 $(AM_CFLAGS) $(CFLAGS)
161AM_V_CC = $(am__v_CC_$(V))
162am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
163am__v_CC_0 = @echo " CC " $@;
164AM_V_at = $(am__v_at_$(V))
165am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
166am__v_at_0 = @
167CCLD = $(CC)
168LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
169 $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
170 $(AM_LDFLAGS) $(LDFLAGS) -o $@
171AM_V_CCLD = $(am__v_CCLD_$(V))
172am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
173am__v_CCLD_0 = @echo " CCLD " $@;
174AM_V_GEN = $(am__v_GEN_$(V))
175am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
176am__v_GEN_0 = @echo " GEN " $@;
177SOURCES = $(libelementary_la_SOURCES)
178DIST_SOURCES = $(libelementary_la_SOURCES)
179HEADERS = $(includes_HEADERS) $(includesub_HEADERS) \
180 $(includesunstable_HEADERS)
181ETAGS = etags
182CTAGS = ctags
183DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
184ACLOCAL = @ACLOCAL@
185ALLOCA = @ALLOCA@
186AMTAR = @AMTAR@
187AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
188AR = @AR@
189AS = @AS@
190AUTOCONF = @AUTOCONF@
191AUTOHEADER = @AUTOHEADER@
192AUTOMAKE = @AUTOMAKE@
193AWK = @AWK@
194CC = @CC@
195CCDEPMODE = @CCDEPMODE@
196CFLAGS = @CFLAGS@
197CPP = @CPP@
198CPPFLAGS = @CPPFLAGS@
199CYGPATH_W = @CYGPATH_W@
200DEFS = @DEFS@
201DEPDIR = @DEPDIR@
202DLLTOOL = @DLLTOOL@
203DSYMUTIL = @DSYMUTIL@
204DUMPBIN = @DUMPBIN@
205ECHO_C = @ECHO_C@
206ECHO_N = @ECHO_N@
207ECHO_T = @ECHO_T@
208EGREP = @EGREP@
209EIO_CFLAGS = @EIO_CFLAGS@
210EIO_LIBS = @EIO_LIBS@
211ELEMENTARY_CFLAGS = @ELEMENTARY_CFLAGS@
212ELEMENTARY_COCOA_CFLAGS = @ELEMENTARY_COCOA_CFLAGS@
213ELEMENTARY_COCOA_LIBS = @ELEMENTARY_COCOA_LIBS@
214ELEMENTARY_CONFIG_PRG = @ELEMENTARY_CONFIG_PRG@
215ELEMENTARY_ECORE_CON_CFLAGS = @ELEMENTARY_ECORE_CON_CFLAGS@
216ELEMENTARY_ECORE_CON_INC = @ELEMENTARY_ECORE_CON_INC@
217ELEMENTARY_ECORE_CON_LIBS = @ELEMENTARY_ECORE_CON_LIBS@
218ELEMENTARY_ECORE_IMF_CFLAGS = @ELEMENTARY_ECORE_IMF_CFLAGS@
219ELEMENTARY_ECORE_IMF_INC = @ELEMENTARY_ECORE_IMF_INC@
220ELEMENTARY_ECORE_IMF_LIBS = @ELEMENTARY_ECORE_IMF_LIBS@
221ELEMENTARY_EDBUS_CFLAGS = @ELEMENTARY_EDBUS_CFLAGS@
222ELEMENTARY_EDBUS_LIBS = @ELEMENTARY_EDBUS_LIBS@
223ELEMENTARY_EFREET_CFLAGS = @ELEMENTARY_EFREET_CFLAGS@
224ELEMENTARY_EFREET_LIBS = @ELEMENTARY_EFREET_LIBS@
225ELEMENTARY_EMAP_CFLAGS = @ELEMENTARY_EMAP_CFLAGS@
226ELEMENTARY_EMAP_LIBS = @ELEMENTARY_EMAP_LIBS@
227ELEMENTARY_ETHUMB_CFLAGS = @ELEMENTARY_ETHUMB_CFLAGS@
228ELEMENTARY_ETHUMB_LIBS = @ELEMENTARY_ETHUMB_LIBS@
229ELEMENTARY_EWEATHER_CFLAGS = @ELEMENTARY_EWEATHER_CFLAGS@
230ELEMENTARY_EWEATHER_LIBS = @ELEMENTARY_EWEATHER_LIBS@
231ELEMENTARY_FB_CFLAGS = @ELEMENTARY_FB_CFLAGS@
232ELEMENTARY_FB_LIBS = @ELEMENTARY_FB_LIBS@
233ELEMENTARY_LIBS = @ELEMENTARY_LIBS@
234ELEMENTARY_PSL1GHT_CFLAGS = @ELEMENTARY_PSL1GHT_CFLAGS@
235ELEMENTARY_PSL1GHT_LIBS = @ELEMENTARY_PSL1GHT_LIBS@
236ELEMENTARY_SDL_CFLAGS = @ELEMENTARY_SDL_CFLAGS@
237ELEMENTARY_SDL_LIBS = @ELEMENTARY_SDL_LIBS@
238ELEMENTARY_TEST_PRG = @ELEMENTARY_TEST_PRG@
239ELEMENTARY_WEB_CFLAGS = @ELEMENTARY_WEB_CFLAGS@
240ELEMENTARY_WEB_LIBS = @ELEMENTARY_WEB_LIBS@
241ELEMENTARY_WIN32_CFLAGS = @ELEMENTARY_WIN32_CFLAGS@
242ELEMENTARY_WIN32_LIBS = @ELEMENTARY_WIN32_LIBS@
243ELEMENTARY_WINCE_CFLAGS = @ELEMENTARY_WINCE_CFLAGS@
244ELEMENTARY_WINCE_LIBS = @ELEMENTARY_WINCE_LIBS@
245ELEMENTARY_X_CFLAGS = @ELEMENTARY_X_CFLAGS@
246ELEMENTARY_X_LIBS = @ELEMENTARY_X_LIBS@
247ELM_ALLOCA_H_DEF = @ELM_ALLOCA_H_DEF@
248ELM_DEBUG_DEF = @ELM_DEBUG_DEF@
249ELM_DIRENT_H_DEF = @ELM_DIRENT_H_DEF@
250ELM_EDBUS_DEF = @ELM_EDBUS_DEF@
251ELM_EFREET_DEF = @ELM_EFREET_DEF@
252ELM_EMAP_DEF = @ELM_EMAP_DEF@
253ELM_ETHUMB_DEF = @ELM_ETHUMB_DEF@
254ELM_EWEATHER_DEF = @ELM_EWEATHER_DEF@
255ELM_LIBINTL_H_DEF = @ELM_LIBINTL_H_DEF@
256ELM_UNIX_DEF = @ELM_UNIX_DEF@
257ELM_WEB_DEF = @ELM_WEB_DEF@
258ELM_WIN32_DEF = @ELM_WIN32_DEF@
259ELM_WINCE_DEF = @ELM_WINCE_DEF@
260EMOTION_CFLAGS = @EMOTION_CFLAGS@
261EMOTION_LIBS = @EMOTION_LIBS@
262EVIL_CFLAGS = @EVIL_CFLAGS@
263EVIL_LIBS = @EVIL_LIBS@
264EXEEXT = @EXEEXT@
265FGREP = @FGREP@
266GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
267GMSGFMT = @GMSGFMT@
268GMSGFMT_015 = @GMSGFMT_015@
269GREP = @GREP@
270INSTALL = @INSTALL@
271INSTALL_DATA = @INSTALL_DATA@
272INSTALL_PROGRAM = @INSTALL_PROGRAM@
273INSTALL_SCRIPT = @INSTALL_SCRIPT@
274INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
275INTLLIBS = @INTLLIBS@
276INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
277LD = @LD@
278LDFLAGS = @LDFLAGS@
279LIBICONV = @LIBICONV@
280LIBINTL = @LIBINTL@
281LIBOBJS = @LIBOBJS@
282LIBS = @LIBS@
283LIBTOOL = @LIBTOOL@
284LIPO = @LIPO@
285LN_S = @LN_S@
286LOCALE_DIR = @LOCALE_DIR@
287LTLIBICONV = @LTLIBICONV@
288LTLIBINTL = @LTLIBINTL@
289LTLIBOBJS = @LTLIBOBJS@
290MAKEINFO = @MAKEINFO@
291MKDIR_P = @MKDIR_P@
292MODULE_ARCH = @MODULE_ARCH@
293MODULE_EDJE = @MODULE_EDJE@
294MSGFMT = @MSGFMT@
295MSGFMT_015 = @MSGFMT_015@
296MSGMERGE = @MSGMERGE@
297NM = @NM@
298NMEDIT = @NMEDIT@
299OBJDUMP = @OBJDUMP@
300OBJEXT = @OBJEXT@
301OTOOL = @OTOOL@
302OTOOL64 = @OTOOL64@
303PACKAGE = @PACKAGE@
304PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
305PACKAGE_NAME = @PACKAGE_NAME@
306PACKAGE_STRING = @PACKAGE_STRING@
307PACKAGE_TARNAME = @PACKAGE_TARNAME@
308PACKAGE_URL = @PACKAGE_URL@
309PACKAGE_VERSION = @PACKAGE_VERSION@
310PATH_SEPARATOR = @PATH_SEPARATOR@
311PKG_CONFIG = @PKG_CONFIG@
312PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
313PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
314POSUB = @POSUB@
315RANLIB = @RANLIB@
316SED = @SED@
317SET_MAKE = @SET_MAKE@
318SHELL = @SHELL@
319STRIP = @STRIP@
320USE_NLS = @USE_NLS@
321VERSION = @VERSION@
322VMAJ = @VMAJ@
323VMIN = @VMIN@
324XGETTEXT = @XGETTEXT@
325XGETTEXT_015 = @XGETTEXT_015@
326XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
327abs_builddir = @abs_builddir@
328abs_srcdir = @abs_srcdir@
329abs_top_builddir = @abs_top_builddir@
330abs_top_srcdir = @abs_top_srcdir@
331ac_ct_CC = @ac_ct_CC@
332ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
333am__include = @am__include@
334am__leading_dot = @am__leading_dot@
335am__quote = @am__quote@
336am__tar = @am__tar@
337am__untar = @am__untar@
338bindir = @bindir@
339build = @build@
340build_alias = @build_alias@
341build_cpu = @build_cpu@
342build_os = @build_os@
343build_vendor = @build_vendor@
344builddir = @builddir@
345datadir = @datadir@
346datarootdir = @datarootdir@
347dlopen_libs = @dlopen_libs@
348docdir = @docdir@
349dvidir = @dvidir@
350edje_cc = @edje_cc@
351eet_eet = @eet_eet@
352efl_doxygen = @efl_doxygen@
353efl_have_doxygen = @efl_have_doxygen@
354exec_prefix = @exec_prefix@
355host = @host@
356host_alias = @host_alias@
357host_cpu = @host_cpu@
358host_os = @host_os@
359host_vendor = @host_vendor@
360htmldir = @htmldir@
361includedir = @includedir@
362infodir = @infodir@
363install_sh = @install_sh@
364libdir = @libdir@
365libexecdir = @libexecdir@
366localedir = @localedir@
367localstatedir = @localstatedir@
368lt_ECHO = @lt_ECHO@
369lt_enable_auto_import = @lt_enable_auto_import@
370mandir = @mandir@
371mkdir_p = @mkdir_p@
372my_libs = @my_libs@
373oldincludedir = @oldincludedir@
374pdfdir = @pdfdir@
375pkgconfig_requires_private = @pkgconfig_requires_private@
376prefix = @prefix@
377program_transform_name = @program_transform_name@
378psdir = @psdir@
379release_info = @release_info@
380requirement_elm = @requirement_elm@
381sbindir = @sbindir@
382sharedstatedir = @sharedstatedir@
383srcdir = @srcdir@
384sysconfdir = @sysconfdir@
385target_alias = @target_alias@
386top_build_prefix = @top_build_prefix@
387top_builddir = @top_builddir@
388top_srcdir = @top_srcdir@
389version_info = @version_info@
390AUTOMAKE_OPTIONS = 1.4 foreign
391MAINTAINERCLEANFILES = Makefile.in
392AM_CPPFLAGS = -DELM_INTERNAL_API_ARGESFSDFEFC=1 \
393 -DMODULES_PATH=\"$(libdir)/elementary/modules\" -I. \
394 -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/src/lib \
395 -I$(top_builddir)/src/lib \
396 -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
397 -DLOCALE_DIR=\"@LOCALE_DIR@\" -DPACKAGE_LIB_DIR=\"$(libdir)\" \
398 @ELEMENTARY_CFLAGS@ @ELEMENTARY_X_CFLAGS@ \
399 @ELEMENTARY_FB_CFLAGS@ @ELEMENTARY_SDL_CFLAGS@ \
400 @ELEMENTARY_WIN32_CFLAGS@ @ELEMENTARY_WINCE_CFLAGS@ \
401 @ELEMENTARY_EDBUS_CFLAGS@ @ELEMENTARY_EFREET_CFLAGS@ \
402 @ELEMENTARY_ETHUMB_CFLAGS@ @ELEMENTARY_WEB_CFLAGS@ \
403 @ELEMENTARY_EMAP_CFLAGS@ @ELEMENTARY_ECORE_CON_CFLAGS@ \
404 @ELEMENTARY_ECORE_IMF_CFLAGS@ @EVIL_CFLAGS@ @EIO_CFLAGS@ \
405 @EMOTION_CFLAGS@ $(am__append_1)
406lib_LTLIBRARIES = libelementary.la
407includes_HEADERS = \
408Elementary.h \
409Elementary_Cursor.h
410
411includesdir = $(includedir)/elementary-@VMAJ@
412includesunstable_HEADERS = \
413elm_widget.h
414
415includesunstabledir = $(includedir)/elementary-@VMAJ@
416includesub_HEADERS = \
417elc_ctxpopup.h \
418elc_dayselector.h \
419elc_fileselector_button.h \
420elc_fileselector_entry.h \
421elc_fileselector.h \
422elc_hoversel.h \
423elc_multibuttonentry.h \
424elc_naviframe.h \
425elc_popup.h \
426elm_actionslider.h \
427elm_app.h \
428elm_authors.h \
429elm_bg.h \
430elm_box.h \
431elm_bubble.h \
432elm_button.h \
433elm_cache.h \
434elm_calendar.h \
435elm_check.h \
436elm_clock.h \
437elm_cnp.h \
438elm_colorselector.h \
439elm_config.h \
440elm_conform.h \
441elm_cursor.h \
442elm_datetime.h \
443elm_debug.h \
444elm_deprecated.h \
445elm_diskselector.h \
446elm_entry.h \
447elm_finger.h \
448elm_flip.h \
449elm_flipselector.h \
450elm_focus.h \
451elm_font.h \
452elm_frame.h \
453elm_gen.h \
454elm_general.h \
455elm_gengrid.h \
456elm_genlist.h \
457elm_gesture_layer.h \
458elm_getting_started.h \
459elm_glview.h \
460elm_grid.h \
461elm_hover.h \
462elm_icon.h \
463elm_image.h \
464elm_plug.h \
465elm_index.h \
466elm_intro.h \
467elm_label.h \
468elm_layout.h \
469elm_list.h \
470elm_macros.h \
471elm_mapbuf.h \
472elm_map.h \
473elm_menu.h \
474elm_mirroring.h \
475elm_need.h \
476elm_notify.h \
477elm_object.h \
478elm_object_item.h \
479elm_panel.h \
480elm_panes.h \
481elm_photocam.h \
482elm_photo.h \
483elm_progressbar.h \
484elm_radio.h \
485elm_route.h \
486elm_scale.h \
487elm_scroller.h \
488elm_scroll.h \
489elm_segment_control.h \
490elm_separator.h \
491elm_slider.h \
492elm_slideshow.h \
493elm_spinner.h \
494elm_store.h \
495elm_table.h \
496elm_theme.h \
497elm_thumb.h \
498elm_toolbar.h \
499elm_tooltip.h \
500elm_transit.h \
501elm_video.h \
502elm_web.h \
503elm_win.h
504
505includesubdir = $(includedir)/elementary-@VMAJ@/
506libelementary_la_SOURCES = \
507elm_priv.h \
508elc_ctxpopup.c \
509elc_dayselector.c \
510elc_popup.c \
511elc_fileselector_button.c \
512elc_fileselector.c \
513elc_fileselector_entry.c \
514elc_hoversel.c \
515elc_naviframe.c \
516elc_multibuttonentry.c \
517elc_player.c \
518elc_scrolled_entry.c \
519elm_access.c \
520elm_actionslider.c \
521elm_bg.c \
522elm_box.c \
523elm_bubble.c \
524elm_button.c \
525elm_calendar.c \
526elm_check.c \
527elm_clock.c \
528elm_cnp.c \
529elm_colorselector.c \
530elm_config.c \
531elm_conform.c \
532elm_datetime.c \
533elm_diskselector.c \
534elm_entry.c \
535elm_flip.c \
536elm_flipselector.c \
537elm_font.c \
538elm_frame.c \
539elm_gengrid.c \
540elm_genlist.c \
541elm_gen_common.h \
542elm_gesture_layer.c \
543elm_glview.c \
544elm_grid.c \
545elm_hover.c \
546elm_icon.c \
547elm_image.c \
548elm_plug.c \
549elm_index.c \
550elm_label.c \
551elm_layout.c \
552elm_list.c \
553elm_main.c \
554elm_mapbuf.c \
555elm_map.c \
556elm_menu.c \
557elm_module.c \
558elm_notify.c \
559elm_panel.c \
560elm_panes.c \
561elm_photo.c \
562elm_photocam.c \
563elm_progressbar.c \
564elm_radio.c \
565elm_route.c \
566elm_scroller.c \
567elm_segment_control.c \
568elm_separator.c \
569elm_slider.c \
570elm_slideshow.c \
571elm_spinner.c \
572elm_store.c \
573elm_table.c \
574elm_theme.c \
575elm_thumb.c \
576elm_toolbar.c \
577elm_transit.c \
578elm_util.c \
579elm_video.c \
580elm_web.c \
581elm_widget.c \
582elm_win.c \
583els_box.c \
584els_box.h \
585els_cursor.c \
586els_icon.c \
587els_icon.h \
588els_pan.c \
589els_pan.h \
590els_scroller.c \
591els_scroller.h \
592els_tooltip.c \
593elu_ews_wm.c
594
595libelementary_la_CFLAGS =
596libelementary_la_LIBADD = \
597@my_libs@ \
598@dlopen_libs@ \
599@ELEMENTARY_LIBS@ \
600@ELEMENTARY_X_LIBS@ \
601@ELEMENTARY_FB_LIBS@ \
602@ELEMENTARY_SDL_LIBS@ \
603@ELEMENTARY_WIN32_LIBS@ \
604@ELEMENTARY_WINCE_LIBS@ \
605@ELEMENTARY_EDBUS_LIBS@ \
606@ELEMENTARY_EFREET_LIBS@ \
607@ELEMENTARY_ETHUMB_LIBS@ \
608@ELEMENTARY_WEB_LIBS@ \
609@ELEMENTARY_EMAP_LIBS@ \
610@ELEMENTARY_ECORE_IMF_LIBS@ \
611@ELEMENTARY_ECORE_CON_LIBS@ \
612@EVIL_LIBS@ \
613@EIO_LIBS@ \
614@EMOTION_LIBS@
615
616libelementary_la_LDFLAGS = \
617-no-undefined @lt_enable_auto_import@ \
618-version-info @version_info@ @release_info@
619
620EXTRA_DIST = \
621elm_factory.h \
622elm_factory.c
623
624all: all-am
625
626.SUFFIXES:
627.SUFFIXES: .c .lo .o .obj
628$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
629 @for dep in $?; do \
630 case '$(am__configure_deps)' in \
631 *$$dep*) \
632 ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
633 && { if test -f $@; then exit 0; else break; fi; }; \
634 exit 1;; \
635 esac; \
636 done; \
637 echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/lib/Makefile'; \
638 $(am__cd) $(top_srcdir) && \
639 $(AUTOMAKE) --foreign src/lib/Makefile
640.PRECIOUS: Makefile
641Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
642 @case '$?' in \
643 *config.status*) \
644 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
645 *) \
646 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
647 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
648 esac;
649
650$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
651 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
652
653$(top_srcdir)/configure: $(am__configure_deps)
654 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
655$(ACLOCAL_M4): $(am__aclocal_m4_deps)
656 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
657$(am__aclocal_m4_deps):
658Elementary.h: $(top_builddir)/config.status $(srcdir)/Elementary.h.in
659 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
660install-libLTLIBRARIES: $(lib_LTLIBRARIES)
661 @$(NORMAL_INSTALL)
662 test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
663 @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
664 list2=; for p in $$list; do \
665 if test -f $$p; then \
666 list2="$$list2 $$p"; \
667 else :; fi; \
668 done; \
669 test -z "$$list2" || { \
670 echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
671 $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
672 }
673
674uninstall-libLTLIBRARIES:
675 @$(NORMAL_UNINSTALL)
676 @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
677 for p in $$list; do \
678 $(am__strip_dir) \
679 echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
680 $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
681 done
682
683clean-libLTLIBRARIES:
684 -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
685 @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
686 dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
687 test "$$dir" != "$$p" || dir=.; \
688 echo "rm -f \"$${dir}/so_locations\""; \
689 rm -f "$${dir}/so_locations"; \
690 done
691libelementary.la: $(libelementary_la_OBJECTS) $(libelementary_la_DEPENDENCIES)
692 $(AM_V_CCLD)$(libelementary_la_LINK) -rpath $(libdir) $(libelementary_la_OBJECTS) $(libelementary_la_LIBADD) $(LIBS)
693
694mostlyclean-compile:
695 -rm -f *.$(OBJEXT)
696
697distclean-compile:
698 -rm -f *.tab.c
699
700@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_ctxpopup.Plo@am__quote@
701@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_dayselector.Plo@am__quote@
702@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_fileselector.Plo@am__quote@
703@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_fileselector_button.Plo@am__quote@
704@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_fileselector_entry.Plo@am__quote@
705@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_hoversel.Plo@am__quote@
706@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_multibuttonentry.Plo@am__quote@
707@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_naviframe.Plo@am__quote@
708@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_player.Plo@am__quote@
709@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_popup.Plo@am__quote@
710@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elc_scrolled_entry.Plo@am__quote@
711@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_access.Plo@am__quote@
712@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_actionslider.Plo@am__quote@
713@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_bg.Plo@am__quote@
714@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_box.Plo@am__quote@
715@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_bubble.Plo@am__quote@
716@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_button.Plo@am__quote@
717@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_calendar.Plo@am__quote@
718@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_check.Plo@am__quote@
719@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_clock.Plo@am__quote@
720@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_cnp.Plo@am__quote@
721@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_colorselector.Plo@am__quote@
722@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_config.Plo@am__quote@
723@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_conform.Plo@am__quote@
724@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_datetime.Plo@am__quote@
725@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_diskselector.Plo@am__quote@
726@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_entry.Plo@am__quote@
727@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_flip.Plo@am__quote@
728@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_flipselector.Plo@am__quote@
729@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_font.Plo@am__quote@
730@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_frame.Plo@am__quote@
731@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_gengrid.Plo@am__quote@
732@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_genlist.Plo@am__quote@
733@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_gesture_layer.Plo@am__quote@
734@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_glview.Plo@am__quote@
735@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_grid.Plo@am__quote@
736@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_hover.Plo@am__quote@
737@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_icon.Plo@am__quote@
738@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_image.Plo@am__quote@
739@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_index.Plo@am__quote@
740@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_label.Plo@am__quote@
741@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_layout.Plo@am__quote@
742@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_list.Plo@am__quote@
743@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_main.Plo@am__quote@
744@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_map.Plo@am__quote@
745@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_mapbuf.Plo@am__quote@
746@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_menu.Plo@am__quote@
747@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_module.Plo@am__quote@
748@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_notify.Plo@am__quote@
749@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_panel.Plo@am__quote@
750@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_panes.Plo@am__quote@
751@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_photo.Plo@am__quote@
752@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_photocam.Plo@am__quote@
753@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_plug.Plo@am__quote@
754@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_progressbar.Plo@am__quote@
755@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_radio.Plo@am__quote@
756@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_route.Plo@am__quote@
757@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_scroller.Plo@am__quote@
758@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_segment_control.Plo@am__quote@
759@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_separator.Plo@am__quote@
760@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_slider.Plo@am__quote@
761@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_slideshow.Plo@am__quote@
762@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_spinner.Plo@am__quote@
763@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_store.Plo@am__quote@
764@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_table.Plo@am__quote@
765@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_theme.Plo@am__quote@
766@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_thumb.Plo@am__quote@
767@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_toolbar.Plo@am__quote@
768@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_transit.Plo@am__quote@
769@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_util.Plo@am__quote@
770@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_video.Plo@am__quote@
771@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_web.Plo@am__quote@
772@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_widget.Plo@am__quote@
773@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elm_win.Plo@am__quote@
774@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-els_box.Plo@am__quote@
775@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-els_cursor.Plo@am__quote@
776@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-els_icon.Plo@am__quote@
777@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-els_pan.Plo@am__quote@
778@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-els_scroller.Plo@am__quote@
779@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-els_tooltip.Plo@am__quote@
780@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libelementary_la-elu_ews_wm.Plo@am__quote@
781
782.c.o:
783@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
784@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
785@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
786@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
787@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
788@am__fastdepCC_FALSE@ $(COMPILE) -c $<
789
790.c.obj:
791@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
792@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
793@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
794@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
795@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
796@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
797
798.c.lo:
799@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
800@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
801@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
802@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
803@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
804@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
805
806libelementary_la-elc_ctxpopup.lo: elc_ctxpopup.c
807@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_ctxpopup.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_ctxpopup.Tpo -c -o libelementary_la-elc_ctxpopup.lo `test -f 'elc_ctxpopup.c' || echo '$(srcdir)/'`elc_ctxpopup.c
808@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_ctxpopup.Tpo $(DEPDIR)/libelementary_la-elc_ctxpopup.Plo
809@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
810@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_ctxpopup.c' object='libelementary_la-elc_ctxpopup.lo' libtool=yes @AMDEPBACKSLASH@
811@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
812@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_ctxpopup.lo `test -f 'elc_ctxpopup.c' || echo '$(srcdir)/'`elc_ctxpopup.c
813
814libelementary_la-elc_dayselector.lo: elc_dayselector.c
815@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_dayselector.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_dayselector.Tpo -c -o libelementary_la-elc_dayselector.lo `test -f 'elc_dayselector.c' || echo '$(srcdir)/'`elc_dayselector.c
816@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_dayselector.Tpo $(DEPDIR)/libelementary_la-elc_dayselector.Plo
817@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
818@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_dayselector.c' object='libelementary_la-elc_dayselector.lo' libtool=yes @AMDEPBACKSLASH@
819@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
820@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_dayselector.lo `test -f 'elc_dayselector.c' || echo '$(srcdir)/'`elc_dayselector.c
821
822libelementary_la-elc_popup.lo: elc_popup.c
823@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_popup.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_popup.Tpo -c -o libelementary_la-elc_popup.lo `test -f 'elc_popup.c' || echo '$(srcdir)/'`elc_popup.c
824@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_popup.Tpo $(DEPDIR)/libelementary_la-elc_popup.Plo
825@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
826@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_popup.c' object='libelementary_la-elc_popup.lo' libtool=yes @AMDEPBACKSLASH@
827@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
828@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_popup.lo `test -f 'elc_popup.c' || echo '$(srcdir)/'`elc_popup.c
829
830libelementary_la-elc_fileselector_button.lo: elc_fileselector_button.c
831@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_fileselector_button.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_fileselector_button.Tpo -c -o libelementary_la-elc_fileselector_button.lo `test -f 'elc_fileselector_button.c' || echo '$(srcdir)/'`elc_fileselector_button.c
832@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_fileselector_button.Tpo $(DEPDIR)/libelementary_la-elc_fileselector_button.Plo
833@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
834@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_fileselector_button.c' object='libelementary_la-elc_fileselector_button.lo' libtool=yes @AMDEPBACKSLASH@
835@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
836@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_fileselector_button.lo `test -f 'elc_fileselector_button.c' || echo '$(srcdir)/'`elc_fileselector_button.c
837
838libelementary_la-elc_fileselector.lo: elc_fileselector.c
839@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_fileselector.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_fileselector.Tpo -c -o libelementary_la-elc_fileselector.lo `test -f 'elc_fileselector.c' || echo '$(srcdir)/'`elc_fileselector.c
840@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_fileselector.Tpo $(DEPDIR)/libelementary_la-elc_fileselector.Plo
841@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
842@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_fileselector.c' object='libelementary_la-elc_fileselector.lo' libtool=yes @AMDEPBACKSLASH@
843@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
844@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_fileselector.lo `test -f 'elc_fileselector.c' || echo '$(srcdir)/'`elc_fileselector.c
845
846libelementary_la-elc_fileselector_entry.lo: elc_fileselector_entry.c
847@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_fileselector_entry.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_fileselector_entry.Tpo -c -o libelementary_la-elc_fileselector_entry.lo `test -f 'elc_fileselector_entry.c' || echo '$(srcdir)/'`elc_fileselector_entry.c
848@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_fileselector_entry.Tpo $(DEPDIR)/libelementary_la-elc_fileselector_entry.Plo
849@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
850@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_fileselector_entry.c' object='libelementary_la-elc_fileselector_entry.lo' libtool=yes @AMDEPBACKSLASH@
851@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
852@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_fileselector_entry.lo `test -f 'elc_fileselector_entry.c' || echo '$(srcdir)/'`elc_fileselector_entry.c
853
854libelementary_la-elc_hoversel.lo: elc_hoversel.c
855@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_hoversel.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_hoversel.Tpo -c -o libelementary_la-elc_hoversel.lo `test -f 'elc_hoversel.c' || echo '$(srcdir)/'`elc_hoversel.c
856@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_hoversel.Tpo $(DEPDIR)/libelementary_la-elc_hoversel.Plo
857@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
858@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_hoversel.c' object='libelementary_la-elc_hoversel.lo' libtool=yes @AMDEPBACKSLASH@
859@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
860@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_hoversel.lo `test -f 'elc_hoversel.c' || echo '$(srcdir)/'`elc_hoversel.c
861
862libelementary_la-elc_naviframe.lo: elc_naviframe.c
863@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_naviframe.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_naviframe.Tpo -c -o libelementary_la-elc_naviframe.lo `test -f 'elc_naviframe.c' || echo '$(srcdir)/'`elc_naviframe.c
864@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_naviframe.Tpo $(DEPDIR)/libelementary_la-elc_naviframe.Plo
865@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
866@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_naviframe.c' object='libelementary_la-elc_naviframe.lo' libtool=yes @AMDEPBACKSLASH@
867@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
868@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_naviframe.lo `test -f 'elc_naviframe.c' || echo '$(srcdir)/'`elc_naviframe.c
869
870libelementary_la-elc_multibuttonentry.lo: elc_multibuttonentry.c
871@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_multibuttonentry.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_multibuttonentry.Tpo -c -o libelementary_la-elc_multibuttonentry.lo `test -f 'elc_multibuttonentry.c' || echo '$(srcdir)/'`elc_multibuttonentry.c
872@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_multibuttonentry.Tpo $(DEPDIR)/libelementary_la-elc_multibuttonentry.Plo
873@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
874@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_multibuttonentry.c' object='libelementary_la-elc_multibuttonentry.lo' libtool=yes @AMDEPBACKSLASH@
875@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
876@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_multibuttonentry.lo `test -f 'elc_multibuttonentry.c' || echo '$(srcdir)/'`elc_multibuttonentry.c
877
878libelementary_la-elc_player.lo: elc_player.c
879@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_player.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_player.Tpo -c -o libelementary_la-elc_player.lo `test -f 'elc_player.c' || echo '$(srcdir)/'`elc_player.c
880@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_player.Tpo $(DEPDIR)/libelementary_la-elc_player.Plo
881@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
882@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_player.c' object='libelementary_la-elc_player.lo' libtool=yes @AMDEPBACKSLASH@
883@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
884@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_player.lo `test -f 'elc_player.c' || echo '$(srcdir)/'`elc_player.c
885
886libelementary_la-elc_scrolled_entry.lo: elc_scrolled_entry.c
887@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elc_scrolled_entry.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elc_scrolled_entry.Tpo -c -o libelementary_la-elc_scrolled_entry.lo `test -f 'elc_scrolled_entry.c' || echo '$(srcdir)/'`elc_scrolled_entry.c
888@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elc_scrolled_entry.Tpo $(DEPDIR)/libelementary_la-elc_scrolled_entry.Plo
889@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
890@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elc_scrolled_entry.c' object='libelementary_la-elc_scrolled_entry.lo' libtool=yes @AMDEPBACKSLASH@
891@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
892@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elc_scrolled_entry.lo `test -f 'elc_scrolled_entry.c' || echo '$(srcdir)/'`elc_scrolled_entry.c
893
894libelementary_la-elm_access.lo: elm_access.c
895@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_access.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_access.Tpo -c -o libelementary_la-elm_access.lo `test -f 'elm_access.c' || echo '$(srcdir)/'`elm_access.c
896@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_access.Tpo $(DEPDIR)/libelementary_la-elm_access.Plo
897@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
898@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_access.c' object='libelementary_la-elm_access.lo' libtool=yes @AMDEPBACKSLASH@
899@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
900@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_access.lo `test -f 'elm_access.c' || echo '$(srcdir)/'`elm_access.c
901
902libelementary_la-elm_actionslider.lo: elm_actionslider.c
903@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_actionslider.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_actionslider.Tpo -c -o libelementary_la-elm_actionslider.lo `test -f 'elm_actionslider.c' || echo '$(srcdir)/'`elm_actionslider.c
904@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_actionslider.Tpo $(DEPDIR)/libelementary_la-elm_actionslider.Plo
905@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
906@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_actionslider.c' object='libelementary_la-elm_actionslider.lo' libtool=yes @AMDEPBACKSLASH@
907@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
908@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_actionslider.lo `test -f 'elm_actionslider.c' || echo '$(srcdir)/'`elm_actionslider.c
909
910libelementary_la-elm_bg.lo: elm_bg.c
911@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_bg.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_bg.Tpo -c -o libelementary_la-elm_bg.lo `test -f 'elm_bg.c' || echo '$(srcdir)/'`elm_bg.c
912@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_bg.Tpo $(DEPDIR)/libelementary_la-elm_bg.Plo
913@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
914@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_bg.c' object='libelementary_la-elm_bg.lo' libtool=yes @AMDEPBACKSLASH@
915@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
916@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_bg.lo `test -f 'elm_bg.c' || echo '$(srcdir)/'`elm_bg.c
917
918libelementary_la-elm_box.lo: elm_box.c
919@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_box.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_box.Tpo -c -o libelementary_la-elm_box.lo `test -f 'elm_box.c' || echo '$(srcdir)/'`elm_box.c
920@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_box.Tpo $(DEPDIR)/libelementary_la-elm_box.Plo
921@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
922@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_box.c' object='libelementary_la-elm_box.lo' libtool=yes @AMDEPBACKSLASH@
923@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
924@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_box.lo `test -f 'elm_box.c' || echo '$(srcdir)/'`elm_box.c
925
926libelementary_la-elm_bubble.lo: elm_bubble.c
927@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_bubble.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_bubble.Tpo -c -o libelementary_la-elm_bubble.lo `test -f 'elm_bubble.c' || echo '$(srcdir)/'`elm_bubble.c
928@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_bubble.Tpo $(DEPDIR)/libelementary_la-elm_bubble.Plo
929@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
930@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_bubble.c' object='libelementary_la-elm_bubble.lo' libtool=yes @AMDEPBACKSLASH@
931@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
932@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_bubble.lo `test -f 'elm_bubble.c' || echo '$(srcdir)/'`elm_bubble.c
933
934libelementary_la-elm_button.lo: elm_button.c
935@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_button.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_button.Tpo -c -o libelementary_la-elm_button.lo `test -f 'elm_button.c' || echo '$(srcdir)/'`elm_button.c
936@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_button.Tpo $(DEPDIR)/libelementary_la-elm_button.Plo
937@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
938@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_button.c' object='libelementary_la-elm_button.lo' libtool=yes @AMDEPBACKSLASH@
939@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
940@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_button.lo `test -f 'elm_button.c' || echo '$(srcdir)/'`elm_button.c
941
942libelementary_la-elm_calendar.lo: elm_calendar.c
943@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_calendar.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_calendar.Tpo -c -o libelementary_la-elm_calendar.lo `test -f 'elm_calendar.c' || echo '$(srcdir)/'`elm_calendar.c
944@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_calendar.Tpo $(DEPDIR)/libelementary_la-elm_calendar.Plo
945@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
946@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_calendar.c' object='libelementary_la-elm_calendar.lo' libtool=yes @AMDEPBACKSLASH@
947@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
948@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_calendar.lo `test -f 'elm_calendar.c' || echo '$(srcdir)/'`elm_calendar.c
949
950libelementary_la-elm_check.lo: elm_check.c
951@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_check.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_check.Tpo -c -o libelementary_la-elm_check.lo `test -f 'elm_check.c' || echo '$(srcdir)/'`elm_check.c
952@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_check.Tpo $(DEPDIR)/libelementary_la-elm_check.Plo
953@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
954@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_check.c' object='libelementary_la-elm_check.lo' libtool=yes @AMDEPBACKSLASH@
955@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
956@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_check.lo `test -f 'elm_check.c' || echo '$(srcdir)/'`elm_check.c
957
958libelementary_la-elm_clock.lo: elm_clock.c
959@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_clock.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_clock.Tpo -c -o libelementary_la-elm_clock.lo `test -f 'elm_clock.c' || echo '$(srcdir)/'`elm_clock.c
960@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_clock.Tpo $(DEPDIR)/libelementary_la-elm_clock.Plo
961@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
962@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_clock.c' object='libelementary_la-elm_clock.lo' libtool=yes @AMDEPBACKSLASH@
963@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
964@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_clock.lo `test -f 'elm_clock.c' || echo '$(srcdir)/'`elm_clock.c
965
966libelementary_la-elm_cnp.lo: elm_cnp.c
967@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_cnp.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_cnp.Tpo -c -o libelementary_la-elm_cnp.lo `test -f 'elm_cnp.c' || echo '$(srcdir)/'`elm_cnp.c
968@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_cnp.Tpo $(DEPDIR)/libelementary_la-elm_cnp.Plo
969@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
970@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_cnp.c' object='libelementary_la-elm_cnp.lo' libtool=yes @AMDEPBACKSLASH@
971@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
972@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_cnp.lo `test -f 'elm_cnp.c' || echo '$(srcdir)/'`elm_cnp.c
973
974libelementary_la-elm_colorselector.lo: elm_colorselector.c
975@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_colorselector.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_colorselector.Tpo -c -o libelementary_la-elm_colorselector.lo `test -f 'elm_colorselector.c' || echo '$(srcdir)/'`elm_colorselector.c
976@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_colorselector.Tpo $(DEPDIR)/libelementary_la-elm_colorselector.Plo
977@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
978@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_colorselector.c' object='libelementary_la-elm_colorselector.lo' libtool=yes @AMDEPBACKSLASH@
979@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
980@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_colorselector.lo `test -f 'elm_colorselector.c' || echo '$(srcdir)/'`elm_colorselector.c
981
982libelementary_la-elm_config.lo: elm_config.c
983@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_config.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_config.Tpo -c -o libelementary_la-elm_config.lo `test -f 'elm_config.c' || echo '$(srcdir)/'`elm_config.c
984@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_config.Tpo $(DEPDIR)/libelementary_la-elm_config.Plo
985@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
986@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_config.c' object='libelementary_la-elm_config.lo' libtool=yes @AMDEPBACKSLASH@
987@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
988@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_config.lo `test -f 'elm_config.c' || echo '$(srcdir)/'`elm_config.c
989
990libelementary_la-elm_conform.lo: elm_conform.c
991@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_conform.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_conform.Tpo -c -o libelementary_la-elm_conform.lo `test -f 'elm_conform.c' || echo '$(srcdir)/'`elm_conform.c
992@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_conform.Tpo $(DEPDIR)/libelementary_la-elm_conform.Plo
993@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
994@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_conform.c' object='libelementary_la-elm_conform.lo' libtool=yes @AMDEPBACKSLASH@
995@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
996@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_conform.lo `test -f 'elm_conform.c' || echo '$(srcdir)/'`elm_conform.c
997
998libelementary_la-elm_datetime.lo: elm_datetime.c
999@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_datetime.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_datetime.Tpo -c -o libelementary_la-elm_datetime.lo `test -f 'elm_datetime.c' || echo '$(srcdir)/'`elm_datetime.c
1000@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_datetime.Tpo $(DEPDIR)/libelementary_la-elm_datetime.Plo
1001@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1002@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_datetime.c' object='libelementary_la-elm_datetime.lo' libtool=yes @AMDEPBACKSLASH@
1003@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1004@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_datetime.lo `test -f 'elm_datetime.c' || echo '$(srcdir)/'`elm_datetime.c
1005
1006libelementary_la-elm_diskselector.lo: elm_diskselector.c
1007@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_diskselector.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_diskselector.Tpo -c -o libelementary_la-elm_diskselector.lo `test -f 'elm_diskselector.c' || echo '$(srcdir)/'`elm_diskselector.c
1008@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_diskselector.Tpo $(DEPDIR)/libelementary_la-elm_diskselector.Plo
1009@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1010@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_diskselector.c' object='libelementary_la-elm_diskselector.lo' libtool=yes @AMDEPBACKSLASH@
1011@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1012@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_diskselector.lo `test -f 'elm_diskselector.c' || echo '$(srcdir)/'`elm_diskselector.c
1013
1014libelementary_la-elm_entry.lo: elm_entry.c
1015@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_entry.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_entry.Tpo -c -o libelementary_la-elm_entry.lo `test -f 'elm_entry.c' || echo '$(srcdir)/'`elm_entry.c
1016@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_entry.Tpo $(DEPDIR)/libelementary_la-elm_entry.Plo
1017@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1018@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_entry.c' object='libelementary_la-elm_entry.lo' libtool=yes @AMDEPBACKSLASH@
1019@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1020@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_entry.lo `test -f 'elm_entry.c' || echo '$(srcdir)/'`elm_entry.c
1021
1022libelementary_la-elm_flip.lo: elm_flip.c
1023@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_flip.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_flip.Tpo -c -o libelementary_la-elm_flip.lo `test -f 'elm_flip.c' || echo '$(srcdir)/'`elm_flip.c
1024@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_flip.Tpo $(DEPDIR)/libelementary_la-elm_flip.Plo
1025@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1026@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_flip.c' object='libelementary_la-elm_flip.lo' libtool=yes @AMDEPBACKSLASH@
1027@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1028@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_flip.lo `test -f 'elm_flip.c' || echo '$(srcdir)/'`elm_flip.c
1029
1030libelementary_la-elm_flipselector.lo: elm_flipselector.c
1031@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_flipselector.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_flipselector.Tpo -c -o libelementary_la-elm_flipselector.lo `test -f 'elm_flipselector.c' || echo '$(srcdir)/'`elm_flipselector.c
1032@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_flipselector.Tpo $(DEPDIR)/libelementary_la-elm_flipselector.Plo
1033@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1034@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_flipselector.c' object='libelementary_la-elm_flipselector.lo' libtool=yes @AMDEPBACKSLASH@
1035@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1036@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_flipselector.lo `test -f 'elm_flipselector.c' || echo '$(srcdir)/'`elm_flipselector.c
1037
1038libelementary_la-elm_font.lo: elm_font.c
1039@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_font.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_font.Tpo -c -o libelementary_la-elm_font.lo `test -f 'elm_font.c' || echo '$(srcdir)/'`elm_font.c
1040@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_font.Tpo $(DEPDIR)/libelementary_la-elm_font.Plo
1041@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1042@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_font.c' object='libelementary_la-elm_font.lo' libtool=yes @AMDEPBACKSLASH@
1043@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1044@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_font.lo `test -f 'elm_font.c' || echo '$(srcdir)/'`elm_font.c
1045
1046libelementary_la-elm_frame.lo: elm_frame.c
1047@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_frame.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_frame.Tpo -c -o libelementary_la-elm_frame.lo `test -f 'elm_frame.c' || echo '$(srcdir)/'`elm_frame.c
1048@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_frame.Tpo $(DEPDIR)/libelementary_la-elm_frame.Plo
1049@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1050@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_frame.c' object='libelementary_la-elm_frame.lo' libtool=yes @AMDEPBACKSLASH@
1051@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1052@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_frame.lo `test -f 'elm_frame.c' || echo '$(srcdir)/'`elm_frame.c
1053
1054libelementary_la-elm_gengrid.lo: elm_gengrid.c
1055@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_gengrid.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_gengrid.Tpo -c -o libelementary_la-elm_gengrid.lo `test -f 'elm_gengrid.c' || echo '$(srcdir)/'`elm_gengrid.c
1056@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_gengrid.Tpo $(DEPDIR)/libelementary_la-elm_gengrid.Plo
1057@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1058@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_gengrid.c' object='libelementary_la-elm_gengrid.lo' libtool=yes @AMDEPBACKSLASH@
1059@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1060@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_gengrid.lo `test -f 'elm_gengrid.c' || echo '$(srcdir)/'`elm_gengrid.c
1061
1062libelementary_la-elm_genlist.lo: elm_genlist.c
1063@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_genlist.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_genlist.Tpo -c -o libelementary_la-elm_genlist.lo `test -f 'elm_genlist.c' || echo '$(srcdir)/'`elm_genlist.c
1064@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_genlist.Tpo $(DEPDIR)/libelementary_la-elm_genlist.Plo
1065@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1066@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_genlist.c' object='libelementary_la-elm_genlist.lo' libtool=yes @AMDEPBACKSLASH@
1067@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1068@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_genlist.lo `test -f 'elm_genlist.c' || echo '$(srcdir)/'`elm_genlist.c
1069
1070libelementary_la-elm_gesture_layer.lo: elm_gesture_layer.c
1071@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_gesture_layer.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_gesture_layer.Tpo -c -o libelementary_la-elm_gesture_layer.lo `test -f 'elm_gesture_layer.c' || echo '$(srcdir)/'`elm_gesture_layer.c
1072@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_gesture_layer.Tpo $(DEPDIR)/libelementary_la-elm_gesture_layer.Plo
1073@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1074@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_gesture_layer.c' object='libelementary_la-elm_gesture_layer.lo' libtool=yes @AMDEPBACKSLASH@
1075@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1076@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_gesture_layer.lo `test -f 'elm_gesture_layer.c' || echo '$(srcdir)/'`elm_gesture_layer.c
1077
1078libelementary_la-elm_glview.lo: elm_glview.c
1079@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_glview.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_glview.Tpo -c -o libelementary_la-elm_glview.lo `test -f 'elm_glview.c' || echo '$(srcdir)/'`elm_glview.c
1080@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_glview.Tpo $(DEPDIR)/libelementary_la-elm_glview.Plo
1081@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1082@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_glview.c' object='libelementary_la-elm_glview.lo' libtool=yes @AMDEPBACKSLASH@
1083@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1084@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_glview.lo `test -f 'elm_glview.c' || echo '$(srcdir)/'`elm_glview.c
1085
1086libelementary_la-elm_grid.lo: elm_grid.c
1087@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_grid.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_grid.Tpo -c -o libelementary_la-elm_grid.lo `test -f 'elm_grid.c' || echo '$(srcdir)/'`elm_grid.c
1088@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_grid.Tpo $(DEPDIR)/libelementary_la-elm_grid.Plo
1089@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1090@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_grid.c' object='libelementary_la-elm_grid.lo' libtool=yes @AMDEPBACKSLASH@
1091@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1092@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_grid.lo `test -f 'elm_grid.c' || echo '$(srcdir)/'`elm_grid.c
1093
1094libelementary_la-elm_hover.lo: elm_hover.c
1095@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_hover.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_hover.Tpo -c -o libelementary_la-elm_hover.lo `test -f 'elm_hover.c' || echo '$(srcdir)/'`elm_hover.c
1096@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_hover.Tpo $(DEPDIR)/libelementary_la-elm_hover.Plo
1097@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1098@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_hover.c' object='libelementary_la-elm_hover.lo' libtool=yes @AMDEPBACKSLASH@
1099@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1100@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_hover.lo `test -f 'elm_hover.c' || echo '$(srcdir)/'`elm_hover.c
1101
1102libelementary_la-elm_icon.lo: elm_icon.c
1103@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_icon.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_icon.Tpo -c -o libelementary_la-elm_icon.lo `test -f 'elm_icon.c' || echo '$(srcdir)/'`elm_icon.c
1104@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_icon.Tpo $(DEPDIR)/libelementary_la-elm_icon.Plo
1105@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1106@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_icon.c' object='libelementary_la-elm_icon.lo' libtool=yes @AMDEPBACKSLASH@
1107@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1108@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_icon.lo `test -f 'elm_icon.c' || echo '$(srcdir)/'`elm_icon.c
1109
1110libelementary_la-elm_image.lo: elm_image.c
1111@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_image.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_image.Tpo -c -o libelementary_la-elm_image.lo `test -f 'elm_image.c' || echo '$(srcdir)/'`elm_image.c
1112@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_image.Tpo $(DEPDIR)/libelementary_la-elm_image.Plo
1113@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1114@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_image.c' object='libelementary_la-elm_image.lo' libtool=yes @AMDEPBACKSLASH@
1115@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1116@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_image.lo `test -f 'elm_image.c' || echo '$(srcdir)/'`elm_image.c
1117
1118libelementary_la-elm_plug.lo: elm_plug.c
1119@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_plug.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_plug.Tpo -c -o libelementary_la-elm_plug.lo `test -f 'elm_plug.c' || echo '$(srcdir)/'`elm_plug.c
1120@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_plug.Tpo $(DEPDIR)/libelementary_la-elm_plug.Plo
1121@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1122@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_plug.c' object='libelementary_la-elm_plug.lo' libtool=yes @AMDEPBACKSLASH@
1123@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1124@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_plug.lo `test -f 'elm_plug.c' || echo '$(srcdir)/'`elm_plug.c
1125
1126libelementary_la-elm_index.lo: elm_index.c
1127@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_index.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_index.Tpo -c -o libelementary_la-elm_index.lo `test -f 'elm_index.c' || echo '$(srcdir)/'`elm_index.c
1128@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_index.Tpo $(DEPDIR)/libelementary_la-elm_index.Plo
1129@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1130@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_index.c' object='libelementary_la-elm_index.lo' libtool=yes @AMDEPBACKSLASH@
1131@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1132@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_index.lo `test -f 'elm_index.c' || echo '$(srcdir)/'`elm_index.c
1133
1134libelementary_la-elm_label.lo: elm_label.c
1135@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_label.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_label.Tpo -c -o libelementary_la-elm_label.lo `test -f 'elm_label.c' || echo '$(srcdir)/'`elm_label.c
1136@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_label.Tpo $(DEPDIR)/libelementary_la-elm_label.Plo
1137@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1138@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_label.c' object='libelementary_la-elm_label.lo' libtool=yes @AMDEPBACKSLASH@
1139@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1140@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_label.lo `test -f 'elm_label.c' || echo '$(srcdir)/'`elm_label.c
1141
1142libelementary_la-elm_layout.lo: elm_layout.c
1143@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_layout.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_layout.Tpo -c -o libelementary_la-elm_layout.lo `test -f 'elm_layout.c' || echo '$(srcdir)/'`elm_layout.c
1144@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_layout.Tpo $(DEPDIR)/libelementary_la-elm_layout.Plo
1145@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1146@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_layout.c' object='libelementary_la-elm_layout.lo' libtool=yes @AMDEPBACKSLASH@
1147@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1148@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_layout.lo `test -f 'elm_layout.c' || echo '$(srcdir)/'`elm_layout.c
1149
1150libelementary_la-elm_list.lo: elm_list.c
1151@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_list.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_list.Tpo -c -o libelementary_la-elm_list.lo `test -f 'elm_list.c' || echo '$(srcdir)/'`elm_list.c
1152@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_list.Tpo $(DEPDIR)/libelementary_la-elm_list.Plo
1153@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1154@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_list.c' object='libelementary_la-elm_list.lo' libtool=yes @AMDEPBACKSLASH@
1155@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1156@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_list.lo `test -f 'elm_list.c' || echo '$(srcdir)/'`elm_list.c
1157
1158libelementary_la-elm_main.lo: elm_main.c
1159@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_main.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_main.Tpo -c -o libelementary_la-elm_main.lo `test -f 'elm_main.c' || echo '$(srcdir)/'`elm_main.c
1160@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_main.Tpo $(DEPDIR)/libelementary_la-elm_main.Plo
1161@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1162@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_main.c' object='libelementary_la-elm_main.lo' libtool=yes @AMDEPBACKSLASH@
1163@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1164@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_main.lo `test -f 'elm_main.c' || echo '$(srcdir)/'`elm_main.c
1165
1166libelementary_la-elm_mapbuf.lo: elm_mapbuf.c
1167@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_mapbuf.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_mapbuf.Tpo -c -o libelementary_la-elm_mapbuf.lo `test -f 'elm_mapbuf.c' || echo '$(srcdir)/'`elm_mapbuf.c
1168@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_mapbuf.Tpo $(DEPDIR)/libelementary_la-elm_mapbuf.Plo
1169@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1170@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_mapbuf.c' object='libelementary_la-elm_mapbuf.lo' libtool=yes @AMDEPBACKSLASH@
1171@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1172@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_mapbuf.lo `test -f 'elm_mapbuf.c' || echo '$(srcdir)/'`elm_mapbuf.c
1173
1174libelementary_la-elm_map.lo: elm_map.c
1175@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_map.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_map.Tpo -c -o libelementary_la-elm_map.lo `test -f 'elm_map.c' || echo '$(srcdir)/'`elm_map.c
1176@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_map.Tpo $(DEPDIR)/libelementary_la-elm_map.Plo
1177@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1178@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_map.c' object='libelementary_la-elm_map.lo' libtool=yes @AMDEPBACKSLASH@
1179@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1180@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_map.lo `test -f 'elm_map.c' || echo '$(srcdir)/'`elm_map.c
1181
1182libelementary_la-elm_menu.lo: elm_menu.c
1183@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_menu.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_menu.Tpo -c -o libelementary_la-elm_menu.lo `test -f 'elm_menu.c' || echo '$(srcdir)/'`elm_menu.c
1184@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_menu.Tpo $(DEPDIR)/libelementary_la-elm_menu.Plo
1185@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1186@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_menu.c' object='libelementary_la-elm_menu.lo' libtool=yes @AMDEPBACKSLASH@
1187@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1188@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_menu.lo `test -f 'elm_menu.c' || echo '$(srcdir)/'`elm_menu.c
1189
1190libelementary_la-elm_module.lo: elm_module.c
1191@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_module.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_module.Tpo -c -o libelementary_la-elm_module.lo `test -f 'elm_module.c' || echo '$(srcdir)/'`elm_module.c
1192@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_module.Tpo $(DEPDIR)/libelementary_la-elm_module.Plo
1193@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1194@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_module.c' object='libelementary_la-elm_module.lo' libtool=yes @AMDEPBACKSLASH@
1195@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1196@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_module.lo `test -f 'elm_module.c' || echo '$(srcdir)/'`elm_module.c
1197
1198libelementary_la-elm_notify.lo: elm_notify.c
1199@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_notify.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_notify.Tpo -c -o libelementary_la-elm_notify.lo `test -f 'elm_notify.c' || echo '$(srcdir)/'`elm_notify.c
1200@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_notify.Tpo $(DEPDIR)/libelementary_la-elm_notify.Plo
1201@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1202@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_notify.c' object='libelementary_la-elm_notify.lo' libtool=yes @AMDEPBACKSLASH@
1203@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1204@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_notify.lo `test -f 'elm_notify.c' || echo '$(srcdir)/'`elm_notify.c
1205
1206libelementary_la-elm_panel.lo: elm_panel.c
1207@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_panel.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_panel.Tpo -c -o libelementary_la-elm_panel.lo `test -f 'elm_panel.c' || echo '$(srcdir)/'`elm_panel.c
1208@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_panel.Tpo $(DEPDIR)/libelementary_la-elm_panel.Plo
1209@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1210@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_panel.c' object='libelementary_la-elm_panel.lo' libtool=yes @AMDEPBACKSLASH@
1211@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1212@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_panel.lo `test -f 'elm_panel.c' || echo '$(srcdir)/'`elm_panel.c
1213
1214libelementary_la-elm_panes.lo: elm_panes.c
1215@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_panes.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_panes.Tpo -c -o libelementary_la-elm_panes.lo `test -f 'elm_panes.c' || echo '$(srcdir)/'`elm_panes.c
1216@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_panes.Tpo $(DEPDIR)/libelementary_la-elm_panes.Plo
1217@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1218@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_panes.c' object='libelementary_la-elm_panes.lo' libtool=yes @AMDEPBACKSLASH@
1219@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1220@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_panes.lo `test -f 'elm_panes.c' || echo '$(srcdir)/'`elm_panes.c
1221
1222libelementary_la-elm_photo.lo: elm_photo.c
1223@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_photo.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_photo.Tpo -c -o libelementary_la-elm_photo.lo `test -f 'elm_photo.c' || echo '$(srcdir)/'`elm_photo.c
1224@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_photo.Tpo $(DEPDIR)/libelementary_la-elm_photo.Plo
1225@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1226@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_photo.c' object='libelementary_la-elm_photo.lo' libtool=yes @AMDEPBACKSLASH@
1227@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1228@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_photo.lo `test -f 'elm_photo.c' || echo '$(srcdir)/'`elm_photo.c
1229
1230libelementary_la-elm_photocam.lo: elm_photocam.c
1231@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_photocam.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_photocam.Tpo -c -o libelementary_la-elm_photocam.lo `test -f 'elm_photocam.c' || echo '$(srcdir)/'`elm_photocam.c
1232@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_photocam.Tpo $(DEPDIR)/libelementary_la-elm_photocam.Plo
1233@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1234@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_photocam.c' object='libelementary_la-elm_photocam.lo' libtool=yes @AMDEPBACKSLASH@
1235@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1236@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_photocam.lo `test -f 'elm_photocam.c' || echo '$(srcdir)/'`elm_photocam.c
1237
1238libelementary_la-elm_progressbar.lo: elm_progressbar.c
1239@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_progressbar.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_progressbar.Tpo -c -o libelementary_la-elm_progressbar.lo `test -f 'elm_progressbar.c' || echo '$(srcdir)/'`elm_progressbar.c
1240@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_progressbar.Tpo $(DEPDIR)/libelementary_la-elm_progressbar.Plo
1241@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1242@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_progressbar.c' object='libelementary_la-elm_progressbar.lo' libtool=yes @AMDEPBACKSLASH@
1243@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1244@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_progressbar.lo `test -f 'elm_progressbar.c' || echo '$(srcdir)/'`elm_progressbar.c
1245
1246libelementary_la-elm_radio.lo: elm_radio.c
1247@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_radio.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_radio.Tpo -c -o libelementary_la-elm_radio.lo `test -f 'elm_radio.c' || echo '$(srcdir)/'`elm_radio.c
1248@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_radio.Tpo $(DEPDIR)/libelementary_la-elm_radio.Plo
1249@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1250@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_radio.c' object='libelementary_la-elm_radio.lo' libtool=yes @AMDEPBACKSLASH@
1251@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1252@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_radio.lo `test -f 'elm_radio.c' || echo '$(srcdir)/'`elm_radio.c
1253
1254libelementary_la-elm_route.lo: elm_route.c
1255@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_route.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_route.Tpo -c -o libelementary_la-elm_route.lo `test -f 'elm_route.c' || echo '$(srcdir)/'`elm_route.c
1256@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_route.Tpo $(DEPDIR)/libelementary_la-elm_route.Plo
1257@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1258@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_route.c' object='libelementary_la-elm_route.lo' libtool=yes @AMDEPBACKSLASH@
1259@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1260@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_route.lo `test -f 'elm_route.c' || echo '$(srcdir)/'`elm_route.c
1261
1262libelementary_la-elm_scroller.lo: elm_scroller.c
1263@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_scroller.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_scroller.Tpo -c -o libelementary_la-elm_scroller.lo `test -f 'elm_scroller.c' || echo '$(srcdir)/'`elm_scroller.c
1264@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_scroller.Tpo $(DEPDIR)/libelementary_la-elm_scroller.Plo
1265@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1266@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_scroller.c' object='libelementary_la-elm_scroller.lo' libtool=yes @AMDEPBACKSLASH@
1267@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1268@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_scroller.lo `test -f 'elm_scroller.c' || echo '$(srcdir)/'`elm_scroller.c
1269
1270libelementary_la-elm_segment_control.lo: elm_segment_control.c
1271@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_segment_control.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_segment_control.Tpo -c -o libelementary_la-elm_segment_control.lo `test -f 'elm_segment_control.c' || echo '$(srcdir)/'`elm_segment_control.c
1272@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_segment_control.Tpo $(DEPDIR)/libelementary_la-elm_segment_control.Plo
1273@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1274@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_segment_control.c' object='libelementary_la-elm_segment_control.lo' libtool=yes @AMDEPBACKSLASH@
1275@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1276@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_segment_control.lo `test -f 'elm_segment_control.c' || echo '$(srcdir)/'`elm_segment_control.c
1277
1278libelementary_la-elm_separator.lo: elm_separator.c
1279@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_separator.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_separator.Tpo -c -o libelementary_la-elm_separator.lo `test -f 'elm_separator.c' || echo '$(srcdir)/'`elm_separator.c
1280@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_separator.Tpo $(DEPDIR)/libelementary_la-elm_separator.Plo
1281@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1282@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_separator.c' object='libelementary_la-elm_separator.lo' libtool=yes @AMDEPBACKSLASH@
1283@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1284@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_separator.lo `test -f 'elm_separator.c' || echo '$(srcdir)/'`elm_separator.c
1285
1286libelementary_la-elm_slider.lo: elm_slider.c
1287@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_slider.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_slider.Tpo -c -o libelementary_la-elm_slider.lo `test -f 'elm_slider.c' || echo '$(srcdir)/'`elm_slider.c
1288@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_slider.Tpo $(DEPDIR)/libelementary_la-elm_slider.Plo
1289@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1290@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_slider.c' object='libelementary_la-elm_slider.lo' libtool=yes @AMDEPBACKSLASH@
1291@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1292@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_slider.lo `test -f 'elm_slider.c' || echo '$(srcdir)/'`elm_slider.c
1293
1294libelementary_la-elm_slideshow.lo: elm_slideshow.c
1295@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_slideshow.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_slideshow.Tpo -c -o libelementary_la-elm_slideshow.lo `test -f 'elm_slideshow.c' || echo '$(srcdir)/'`elm_slideshow.c
1296@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_slideshow.Tpo $(DEPDIR)/libelementary_la-elm_slideshow.Plo
1297@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1298@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_slideshow.c' object='libelementary_la-elm_slideshow.lo' libtool=yes @AMDEPBACKSLASH@
1299@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1300@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_slideshow.lo `test -f 'elm_slideshow.c' || echo '$(srcdir)/'`elm_slideshow.c
1301
1302libelementary_la-elm_spinner.lo: elm_spinner.c
1303@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_spinner.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_spinner.Tpo -c -o libelementary_la-elm_spinner.lo `test -f 'elm_spinner.c' || echo '$(srcdir)/'`elm_spinner.c
1304@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_spinner.Tpo $(DEPDIR)/libelementary_la-elm_spinner.Plo
1305@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1306@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_spinner.c' object='libelementary_la-elm_spinner.lo' libtool=yes @AMDEPBACKSLASH@
1307@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1308@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_spinner.lo `test -f 'elm_spinner.c' || echo '$(srcdir)/'`elm_spinner.c
1309
1310libelementary_la-elm_store.lo: elm_store.c
1311@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_store.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_store.Tpo -c -o libelementary_la-elm_store.lo `test -f 'elm_store.c' || echo '$(srcdir)/'`elm_store.c
1312@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_store.Tpo $(DEPDIR)/libelementary_la-elm_store.Plo
1313@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1314@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_store.c' object='libelementary_la-elm_store.lo' libtool=yes @AMDEPBACKSLASH@
1315@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1316@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_store.lo `test -f 'elm_store.c' || echo '$(srcdir)/'`elm_store.c
1317
1318libelementary_la-elm_table.lo: elm_table.c
1319@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_table.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_table.Tpo -c -o libelementary_la-elm_table.lo `test -f 'elm_table.c' || echo '$(srcdir)/'`elm_table.c
1320@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_table.Tpo $(DEPDIR)/libelementary_la-elm_table.Plo
1321@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1322@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_table.c' object='libelementary_la-elm_table.lo' libtool=yes @AMDEPBACKSLASH@
1323@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1324@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_table.lo `test -f 'elm_table.c' || echo '$(srcdir)/'`elm_table.c
1325
1326libelementary_la-elm_theme.lo: elm_theme.c
1327@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_theme.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_theme.Tpo -c -o libelementary_la-elm_theme.lo `test -f 'elm_theme.c' || echo '$(srcdir)/'`elm_theme.c
1328@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_theme.Tpo $(DEPDIR)/libelementary_la-elm_theme.Plo
1329@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1330@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_theme.c' object='libelementary_la-elm_theme.lo' libtool=yes @AMDEPBACKSLASH@
1331@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1332@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_theme.lo `test -f 'elm_theme.c' || echo '$(srcdir)/'`elm_theme.c
1333
1334libelementary_la-elm_thumb.lo: elm_thumb.c
1335@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_thumb.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_thumb.Tpo -c -o libelementary_la-elm_thumb.lo `test -f 'elm_thumb.c' || echo '$(srcdir)/'`elm_thumb.c
1336@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_thumb.Tpo $(DEPDIR)/libelementary_la-elm_thumb.Plo
1337@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1338@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_thumb.c' object='libelementary_la-elm_thumb.lo' libtool=yes @AMDEPBACKSLASH@
1339@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1340@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_thumb.lo `test -f 'elm_thumb.c' || echo '$(srcdir)/'`elm_thumb.c
1341
1342libelementary_la-elm_toolbar.lo: elm_toolbar.c
1343@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_toolbar.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_toolbar.Tpo -c -o libelementary_la-elm_toolbar.lo `test -f 'elm_toolbar.c' || echo '$(srcdir)/'`elm_toolbar.c
1344@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_toolbar.Tpo $(DEPDIR)/libelementary_la-elm_toolbar.Plo
1345@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1346@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_toolbar.c' object='libelementary_la-elm_toolbar.lo' libtool=yes @AMDEPBACKSLASH@
1347@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1348@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_toolbar.lo `test -f 'elm_toolbar.c' || echo '$(srcdir)/'`elm_toolbar.c
1349
1350libelementary_la-elm_transit.lo: elm_transit.c
1351@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_transit.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_transit.Tpo -c -o libelementary_la-elm_transit.lo `test -f 'elm_transit.c' || echo '$(srcdir)/'`elm_transit.c
1352@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_transit.Tpo $(DEPDIR)/libelementary_la-elm_transit.Plo
1353@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1354@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_transit.c' object='libelementary_la-elm_transit.lo' libtool=yes @AMDEPBACKSLASH@
1355@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1356@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_transit.lo `test -f 'elm_transit.c' || echo '$(srcdir)/'`elm_transit.c
1357
1358libelementary_la-elm_util.lo: elm_util.c
1359@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_util.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_util.Tpo -c -o libelementary_la-elm_util.lo `test -f 'elm_util.c' || echo '$(srcdir)/'`elm_util.c
1360@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_util.Tpo $(DEPDIR)/libelementary_la-elm_util.Plo
1361@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1362@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_util.c' object='libelementary_la-elm_util.lo' libtool=yes @AMDEPBACKSLASH@
1363@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1364@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_util.lo `test -f 'elm_util.c' || echo '$(srcdir)/'`elm_util.c
1365
1366libelementary_la-elm_video.lo: elm_video.c
1367@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_video.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_video.Tpo -c -o libelementary_la-elm_video.lo `test -f 'elm_video.c' || echo '$(srcdir)/'`elm_video.c
1368@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_video.Tpo $(DEPDIR)/libelementary_la-elm_video.Plo
1369@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1370@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_video.c' object='libelementary_la-elm_video.lo' libtool=yes @AMDEPBACKSLASH@
1371@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1372@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_video.lo `test -f 'elm_video.c' || echo '$(srcdir)/'`elm_video.c
1373
1374libelementary_la-elm_web.lo: elm_web.c
1375@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_web.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_web.Tpo -c -o libelementary_la-elm_web.lo `test -f 'elm_web.c' || echo '$(srcdir)/'`elm_web.c
1376@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_web.Tpo $(DEPDIR)/libelementary_la-elm_web.Plo
1377@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1378@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_web.c' object='libelementary_la-elm_web.lo' libtool=yes @AMDEPBACKSLASH@
1379@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1380@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_web.lo `test -f 'elm_web.c' || echo '$(srcdir)/'`elm_web.c
1381
1382libelementary_la-elm_widget.lo: elm_widget.c
1383@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_widget.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_widget.Tpo -c -o libelementary_la-elm_widget.lo `test -f 'elm_widget.c' || echo '$(srcdir)/'`elm_widget.c
1384@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_widget.Tpo $(DEPDIR)/libelementary_la-elm_widget.Plo
1385@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1386@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_widget.c' object='libelementary_la-elm_widget.lo' libtool=yes @AMDEPBACKSLASH@
1387@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1388@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_widget.lo `test -f 'elm_widget.c' || echo '$(srcdir)/'`elm_widget.c
1389
1390libelementary_la-elm_win.lo: elm_win.c
1391@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elm_win.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elm_win.Tpo -c -o libelementary_la-elm_win.lo `test -f 'elm_win.c' || echo '$(srcdir)/'`elm_win.c
1392@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elm_win.Tpo $(DEPDIR)/libelementary_la-elm_win.Plo
1393@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1394@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elm_win.c' object='libelementary_la-elm_win.lo' libtool=yes @AMDEPBACKSLASH@
1395@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1396@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elm_win.lo `test -f 'elm_win.c' || echo '$(srcdir)/'`elm_win.c
1397
1398libelementary_la-els_box.lo: els_box.c
1399@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-els_box.lo -MD -MP -MF $(DEPDIR)/libelementary_la-els_box.Tpo -c -o libelementary_la-els_box.lo `test -f 'els_box.c' || echo '$(srcdir)/'`els_box.c
1400@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-els_box.Tpo $(DEPDIR)/libelementary_la-els_box.Plo
1401@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1402@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='els_box.c' object='libelementary_la-els_box.lo' libtool=yes @AMDEPBACKSLASH@
1403@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1404@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-els_box.lo `test -f 'els_box.c' || echo '$(srcdir)/'`els_box.c
1405
1406libelementary_la-els_cursor.lo: els_cursor.c
1407@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-els_cursor.lo -MD -MP -MF $(DEPDIR)/libelementary_la-els_cursor.Tpo -c -o libelementary_la-els_cursor.lo `test -f 'els_cursor.c' || echo '$(srcdir)/'`els_cursor.c
1408@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-els_cursor.Tpo $(DEPDIR)/libelementary_la-els_cursor.Plo
1409@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1410@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='els_cursor.c' object='libelementary_la-els_cursor.lo' libtool=yes @AMDEPBACKSLASH@
1411@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1412@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-els_cursor.lo `test -f 'els_cursor.c' || echo '$(srcdir)/'`els_cursor.c
1413
1414libelementary_la-els_icon.lo: els_icon.c
1415@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-els_icon.lo -MD -MP -MF $(DEPDIR)/libelementary_la-els_icon.Tpo -c -o libelementary_la-els_icon.lo `test -f 'els_icon.c' || echo '$(srcdir)/'`els_icon.c
1416@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-els_icon.Tpo $(DEPDIR)/libelementary_la-els_icon.Plo
1417@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1418@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='els_icon.c' object='libelementary_la-els_icon.lo' libtool=yes @AMDEPBACKSLASH@
1419@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1420@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-els_icon.lo `test -f 'els_icon.c' || echo '$(srcdir)/'`els_icon.c
1421
1422libelementary_la-els_pan.lo: els_pan.c
1423@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-els_pan.lo -MD -MP -MF $(DEPDIR)/libelementary_la-els_pan.Tpo -c -o libelementary_la-els_pan.lo `test -f 'els_pan.c' || echo '$(srcdir)/'`els_pan.c
1424@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-els_pan.Tpo $(DEPDIR)/libelementary_la-els_pan.Plo
1425@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1426@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='els_pan.c' object='libelementary_la-els_pan.lo' libtool=yes @AMDEPBACKSLASH@
1427@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1428@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-els_pan.lo `test -f 'els_pan.c' || echo '$(srcdir)/'`els_pan.c
1429
1430libelementary_la-els_scroller.lo: els_scroller.c
1431@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-els_scroller.lo -MD -MP -MF $(DEPDIR)/libelementary_la-els_scroller.Tpo -c -o libelementary_la-els_scroller.lo `test -f 'els_scroller.c' || echo '$(srcdir)/'`els_scroller.c
1432@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-els_scroller.Tpo $(DEPDIR)/libelementary_la-els_scroller.Plo
1433@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1434@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='els_scroller.c' object='libelementary_la-els_scroller.lo' libtool=yes @AMDEPBACKSLASH@
1435@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1436@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-els_scroller.lo `test -f 'els_scroller.c' || echo '$(srcdir)/'`els_scroller.c
1437
1438libelementary_la-els_tooltip.lo: els_tooltip.c
1439@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-els_tooltip.lo -MD -MP -MF $(DEPDIR)/libelementary_la-els_tooltip.Tpo -c -o libelementary_la-els_tooltip.lo `test -f 'els_tooltip.c' || echo '$(srcdir)/'`els_tooltip.c
1440@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-els_tooltip.Tpo $(DEPDIR)/libelementary_la-els_tooltip.Plo
1441@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1442@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='els_tooltip.c' object='libelementary_la-els_tooltip.lo' libtool=yes @AMDEPBACKSLASH@
1443@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1444@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-els_tooltip.lo `test -f 'els_tooltip.c' || echo '$(srcdir)/'`els_tooltip.c
1445
1446libelementary_la-elu_ews_wm.lo: elu_ews_wm.c
1447@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -MT libelementary_la-elu_ews_wm.lo -MD -MP -MF $(DEPDIR)/libelementary_la-elu_ews_wm.Tpo -c -o libelementary_la-elu_ews_wm.lo `test -f 'elu_ews_wm.c' || echo '$(srcdir)/'`elu_ews_wm.c
1448@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libelementary_la-elu_ews_wm.Tpo $(DEPDIR)/libelementary_la-elu_ews_wm.Plo
1449@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
1450@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='elu_ews_wm.c' object='libelementary_la-elu_ews_wm.lo' libtool=yes @AMDEPBACKSLASH@
1451@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
1452@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libelementary_la_CFLAGS) $(CFLAGS) -c -o libelementary_la-elu_ews_wm.lo `test -f 'elu_ews_wm.c' || echo '$(srcdir)/'`elu_ews_wm.c
1453
1454mostlyclean-libtool:
1455 -rm -f *.lo
1456
1457clean-libtool:
1458 -rm -rf .libs _libs
1459install-includesHEADERS: $(includes_HEADERS)
1460 @$(NORMAL_INSTALL)
1461 test -z "$(includesdir)" || $(MKDIR_P) "$(DESTDIR)$(includesdir)"
1462 @list='$(includes_HEADERS)'; test -n "$(includesdir)" || list=; \
1463 for p in $$list; do \
1464 if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
1465 echo "$$d$$p"; \
1466 done | $(am__base_list) | \
1467 while read files; do \
1468 echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includesdir)'"; \
1469 $(INSTALL_HEADER) $$files "$(DESTDIR)$(includesdir)" || exit $$?; \
1470 done
1471
1472uninstall-includesHEADERS:
1473 @$(NORMAL_UNINSTALL)
1474 @list='$(includes_HEADERS)'; test -n "$(includesdir)" || list=; \
1475 files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
1476 test -n "$$files" || exit 0; \
1477 echo " ( cd '$(DESTDIR)$(includesdir)' && rm -f" $$files ")"; \
1478 cd "$(DESTDIR)$(includesdir)" && rm -f $$files
1479install-includesubHEADERS: $(includesub_HEADERS)
1480 @$(NORMAL_INSTALL)
1481 test -z "$(includesubdir)" || $(MKDIR_P) "$(DESTDIR)$(includesubdir)"
1482 @list='$(includesub_HEADERS)'; test -n "$(includesubdir)" || list=; \
1483 for p in $$list; do \
1484 if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
1485 echo "$$d$$p"; \
1486 done | $(am__base_list) | \
1487 while read files; do \
1488 echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includesubdir)'"; \
1489 $(INSTALL_HEADER) $$files "$(DESTDIR)$(includesubdir)" || exit $$?; \
1490 done
1491
1492uninstall-includesubHEADERS:
1493 @$(NORMAL_UNINSTALL)
1494 @list='$(includesub_HEADERS)'; test -n "$(includesubdir)" || list=; \
1495 files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
1496 test -n "$$files" || exit 0; \
1497 echo " ( cd '$(DESTDIR)$(includesubdir)' && rm -f" $$files ")"; \
1498 cd "$(DESTDIR)$(includesubdir)" && rm -f $$files
1499install-includesunstableHEADERS: $(includesunstable_HEADERS)
1500 @$(NORMAL_INSTALL)
1501 test -z "$(includesunstabledir)" || $(MKDIR_P) "$(DESTDIR)$(includesunstabledir)"
1502 @list='$(includesunstable_HEADERS)'; test -n "$(includesunstabledir)" || list=; \
1503 for p in $$list; do \
1504 if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
1505 echo "$$d$$p"; \
1506 done | $(am__base_list) | \
1507 while read files; do \
1508 echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includesunstabledir)'"; \
1509 $(INSTALL_HEADER) $$files "$(DESTDIR)$(includesunstabledir)" || exit $$?; \
1510 done
1511
1512uninstall-includesunstableHEADERS:
1513 @$(NORMAL_UNINSTALL)
1514 @list='$(includesunstable_HEADERS)'; test -n "$(includesunstabledir)" || list=; \
1515 files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
1516 test -n "$$files" || exit 0; \
1517 echo " ( cd '$(DESTDIR)$(includesunstabledir)' && rm -f" $$files ")"; \
1518 cd "$(DESTDIR)$(includesunstabledir)" && rm -f $$files
1519
1520ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
1521 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
1522 unique=`for i in $$list; do \
1523 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
1524 done | \
1525 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
1526 END { if (nonempty) { for (i in files) print i; }; }'`; \
1527 mkid -fID $$unique
1528tags: TAGS
1529
1530TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
1531 $(TAGS_FILES) $(LISP)
1532 set x; \
1533 here=`pwd`; \
1534 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
1535 unique=`for i in $$list; do \
1536 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
1537 done | \
1538 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
1539 END { if (nonempty) { for (i in files) print i; }; }'`; \
1540 shift; \
1541 if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
1542 test -n "$$unique" || unique=$$empty_fix; \
1543 if test $$# -gt 0; then \
1544 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
1545 "$$@" $$unique; \
1546 else \
1547 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
1548 $$unique; \
1549 fi; \
1550 fi
1551ctags: CTAGS
1552CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
1553 $(TAGS_FILES) $(LISP)
1554 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
1555 unique=`for i in $$list; do \
1556 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
1557 done | \
1558 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
1559 END { if (nonempty) { for (i in files) print i; }; }'`; \
1560 test -z "$(CTAGS_ARGS)$$unique" \
1561 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
1562 $$unique
1563
1564GTAGS:
1565 here=`$(am__cd) $(top_builddir) && pwd` \
1566 && $(am__cd) $(top_srcdir) \
1567 && gtags -i $(GTAGS_ARGS) "$$here"
1568
1569distclean-tags:
1570 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
1571
1572distdir: $(DISTFILES)
1573 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
1574 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
1575 list='$(DISTFILES)'; \
1576 dist_files=`for file in $$list; do echo $$file; done | \
1577 sed -e "s|^$$srcdirstrip/||;t" \
1578 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
1579 case $$dist_files in \
1580 */*) $(MKDIR_P) `echo "$$dist_files" | \
1581 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
1582 sort -u` ;; \
1583 esac; \
1584 for file in $$dist_files; do \
1585 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
1586 if test -d $$d/$$file; then \
1587 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
1588 if test -d "$(distdir)/$$file"; then \
1589 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
1590 fi; \
1591 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
1592 cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
1593 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
1594 fi; \
1595 cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
1596 else \
1597 test -f "$(distdir)/$$file" \
1598 || cp -p $$d/$$file "$(distdir)/$$file" \
1599 || exit 1; \
1600 fi; \
1601 done
1602check-am: all-am
1603check: check-am
1604all-am: Makefile $(LTLIBRARIES) $(HEADERS)
1605installdirs:
1606 for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includesdir)" "$(DESTDIR)$(includesubdir)" "$(DESTDIR)$(includesunstabledir)"; do \
1607 test -z "$$dir" || $(MKDIR_P) "$$dir"; \
1608 done
1609install: install-am
1610install-exec: install-exec-am
1611install-data: install-data-am
1612uninstall: uninstall-am
1613
1614install-am: all-am
1615 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
1616
1617installcheck: installcheck-am
1618install-strip:
1619 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
1620 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
1621 `test -z '$(STRIP)' || \
1622 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
1623mostlyclean-generic:
1624
1625clean-generic:
1626
1627distclean-generic:
1628 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
1629 -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
1630
1631maintainer-clean-generic:
1632 @echo "This command is intended for maintainers to use"
1633 @echo "it deletes files that may require special tools to rebuild."
1634 -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
1635clean: clean-am
1636
1637clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
1638 mostlyclean-am
1639
1640distclean: distclean-am
1641 -rm -rf ./$(DEPDIR)
1642 -rm -f Makefile
1643distclean-am: clean-am distclean-compile distclean-generic \
1644 distclean-tags
1645
1646dvi: dvi-am
1647
1648dvi-am:
1649
1650html: html-am
1651
1652html-am:
1653
1654info: info-am
1655
1656info-am:
1657
1658install-data-am: install-includesHEADERS install-includesubHEADERS \
1659 install-includesunstableHEADERS
1660
1661install-dvi: install-dvi-am
1662
1663install-dvi-am:
1664
1665install-exec-am: install-libLTLIBRARIES
1666
1667install-html: install-html-am
1668
1669install-html-am:
1670
1671install-info: install-info-am
1672
1673install-info-am:
1674
1675install-man:
1676
1677install-pdf: install-pdf-am
1678
1679install-pdf-am:
1680
1681install-ps: install-ps-am
1682
1683install-ps-am:
1684
1685installcheck-am:
1686
1687maintainer-clean: maintainer-clean-am
1688 -rm -rf ./$(DEPDIR)
1689 -rm -f Makefile
1690maintainer-clean-am: distclean-am maintainer-clean-generic
1691
1692mostlyclean: mostlyclean-am
1693
1694mostlyclean-am: mostlyclean-compile mostlyclean-generic \
1695 mostlyclean-libtool
1696
1697pdf: pdf-am
1698
1699pdf-am:
1700
1701ps: ps-am
1702
1703ps-am:
1704
1705uninstall-am: uninstall-includesHEADERS uninstall-includesubHEADERS \
1706 uninstall-includesunstableHEADERS uninstall-libLTLIBRARIES
1707
1708.MAKE: install-am install-strip
1709
1710.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
1711 clean-libLTLIBRARIES clean-libtool ctags distclean \
1712 distclean-compile distclean-generic distclean-libtool \
1713 distclean-tags distdir dvi dvi-am html html-am info info-am \
1714 install install-am install-data install-data-am install-dvi \
1715 install-dvi-am install-exec install-exec-am install-html \
1716 install-html-am install-includesHEADERS \
1717 install-includesubHEADERS install-includesunstableHEADERS \
1718 install-info install-info-am install-libLTLIBRARIES \
1719 install-man install-pdf install-pdf-am install-ps \
1720 install-ps-am install-strip installcheck installcheck-am \
1721 installdirs maintainer-clean maintainer-clean-generic \
1722 mostlyclean mostlyclean-compile mostlyclean-generic \
1723 mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
1724 uninstall-am uninstall-includesHEADERS \
1725 uninstall-includesubHEADERS uninstall-includesunstableHEADERS \
1726 uninstall-libLTLIBRARIES
1727
1728
1729# Tell versions [3.59,3.63) of GNU make to not export all variables.
1730# Otherwise a system limit (for SysV at least) may be exceeded.
1731.NOEXPORT:
diff --git a/libraries/elementary/src/lib/elc_ctxpopup.c b/libraries/elementary/src/lib/elc_ctxpopup.c
new file mode 100644
index 0000000..31f57a8
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_ctxpopup.c
@@ -0,0 +1,1433 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Ctxpopup_Item Elm_Ctxpopup_Item;
6
7struct _Elm_Ctxpopup_Item
8{
9 ELM_WIDGET_ITEM;
10 Elm_Object_Item *list_item;
11};
12
13struct _Widget_Data
14{
15 Evas_Object *parent;
16 Evas_Object *base;
17 Evas_Object *content;
18 Evas_Object *list;
19 Evas_Object *box;
20 Evas_Object *arrow;
21 Evas_Object *bg;
22 Elm_Ctxpopup_Direction dir;
23 Elm_Ctxpopup_Direction dir_priority[4];
24 Eina_Bool horizontal:1;
25 Eina_Bool visible:1;
26 Eina_Bool list_visible:1;
27 Eina_Bool finished:1;
28};
29
30static const char *widtype = NULL;
31
32static void _freeze_on(void *data, Evas_Object *obj, void *event_info);
33static void _freeze_off(void *data, Evas_Object *obj, void *event_info);
34static void _hold_on(void *data, Evas_Object *obj, void *event_info);
35static void _hold_off(void *data, Evas_Object *obj, void *event_info);
36static void _on_focus_hook(void *data, Evas_Object *obj);
37static Eina_Bool _event_hook(Evas_Object *obj,
38 Evas_Object *src,
39 Evas_Callback_Type type,
40 void *event_info);
41static void _parent_cut_off(Evas_Object *obj);
42static void _parent_resize(void *data,
43 Evas *e,
44 Evas_Object *obj,
45 void *event_info);
46static void _parent_move(void *data,
47 Evas *e,
48 Evas_Object *obj,
49 void *event_info);
50static void _parent_del(void *data,
51 Evas *e,
52 Evas_Object *obj,
53 void *event_info);
54static void _adjust_pos_x(Evas_Coord_Point *pos,
55 Evas_Coord_Point *base_size,
56 Evas_Coord_Rectangle *hover_area);
57static void _adjust_pos_y(Evas_Coord_Point *pos,
58 Evas_Coord_Point *base_size,
59 Evas_Coord_Rectangle *hover_area);
60static Elm_Ctxpopup_Direction _calc_base_geometry(Evas_Object *obj,
61 Evas_Coord_Rectangle *rect);
62static void _update_arrow(Evas_Object *obj,
63 Elm_Ctxpopup_Direction dir,
64 Evas_Coord_Rectangle rect);
65static void _sizing_eval(Evas_Object *obj);
66static void _hide_signal_emit(Evas_Object *obj,
67 Elm_Ctxpopup_Direction dir);
68static void _show_signal_emit(Evas_Object *obj,
69 Elm_Ctxpopup_Direction dir);
70static void _shift_base_by_arrow(Evas_Object *arrow,
71 Elm_Ctxpopup_Direction dir,
72 Evas_Coord_Rectangle *rect);
73static void _del_pre_hook(Evas_Object *obj);
74static void _del_hook(Evas_Object *obj);
75static void _theme_hook(Evas_Object *obj);
76static void _content_set_hook(Evas_Object *obj,
77 const char *part,
78 Evas_Object *content);
79static Evas_Object * _content_unset_hook(Evas_Object *obj,
80 const char *part__);
81static Evas_Object * _content_get_hook(const Evas_Object *obj,
82 const char *part);
83static void _item_text_set_hook(Elm_Object_Item *it,
84 const char *part,
85 const char *label);
86static const char * _item_text_get_hook(const Elm_Object_Item *it,
87 const char *part);
88static void _item_content_set_hook(Elm_Object_Item *it,
89 const char *part,
90 Evas_Object *content);
91static Evas_Object * _item_content_get_hook(const Elm_Object_Item *it,
92 const char *part);
93static void _item_disable_hook(Elm_Object_Item *it);
94static void _item_signal_emit_hook(Elm_Object_Item *it,
95 const char *emission,
96 const char *source);
97static void _bg_clicked_cb(void *data, Evas_Object *obj,
98 const char *emission,
99 const char *source);
100static void _ctxpopup_show(void *data,
101 Evas *e,
102 Evas_Object *obj,
103 void *event_info);
104static void _hide_finished(void *data,
105 Evas_Object *obj,
106 const char *emission,
107 const char *source __UNUSED__);
108static void _ctxpopup_hide(void *data,
109 Evas *e,
110 Evas_Object *obj,
111 void *event_info);
112static void _content_resize(void *data,
113 Evas *e,
114 Evas_Object *obj,
115 void *event_info);
116static void _ctxpopup_move(void *data,
117 Evas *e,
118 Evas_Object *obj,
119 void *event_info);
120static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
121static void _content_del(void *data,
122 Evas *e,
123 Evas_Object *obj,
124 void *event_info);
125static void _list_del(Widget_Data *wd);
126static void _disable_hook(Evas_Object *obj);
127static void _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source);
128static void _signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data);
129static void _signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data);
130
131static const char SIG_DISMISSED[] = "dismissed";
132
133static const Evas_Smart_Cb_Description _signals[] = {
134 {SIG_DISMISSED, ""},
135 {NULL, NULL}
136};
137
138static void
139_freeze_on(void *data __UNUSED__, Evas_Object *obj,
140 void *event_info __UNUSED__)
141{
142 Widget_Data *wd = elm_widget_data_get(obj);
143
144 if ((!wd) || (!wd->list)) return;
145 elm_widget_scroll_freeze_push(wd->list);
146}
147
148static void
149_freeze_off(void *data __UNUSED__, Evas_Object *obj,
150 void *event_info __UNUSED__)
151{
152 Widget_Data *wd = elm_widget_data_get(obj);
153
154 if ((!wd) || (!wd->list)) return;
155 elm_widget_scroll_freeze_pop(wd->list);
156}
157
158static void
159_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
160{
161 Widget_Data *wd = elm_widget_data_get(obj);
162
163 if ((!wd) || (!wd->list)) return;
164 elm_widget_scroll_hold_push(wd->list);
165}
166
167static void
168_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
169{
170 Widget_Data *wd = elm_widget_data_get(obj);
171
172 if ((!wd) || (!wd->list)) return;
173 elm_widget_scroll_hold_pop(wd->list);
174}
175
176static void
177_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
178{
179 Widget_Data *wd = elm_widget_data_get(obj);
180 if (!wd) return;
181
182
183 if (elm_widget_focus_get(obj))
184 {
185 //FIXME:
186 }
187 else
188 {
189 //FIXME:
190 }
191}
192
193static Eina_Bool
194_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
195 Evas_Callback_Type type, void *event_info)
196{
197 Evas_Event_Key_Down *ev;
198 Widget_Data *wd;
199
200 if (type != EVAS_CALLBACK_KEY_DOWN)
201 return EINA_FALSE;
202 wd = elm_widget_data_get(obj);
203 if (!wd) return EINA_FALSE;
204
205 ev = event_info;
206 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
207 if (strcmp(ev->keyname, "Escape")) return EINA_FALSE;
208
209 evas_object_hide(obj);
210 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
211 return EINA_TRUE;
212}
213
214static void
215_parent_cut_off(Evas_Object *obj)
216{
217 Widget_Data *wd = elm_widget_data_get(obj);
218
219 if (!wd) return;
220
221 evas_object_event_callback_del_full(wd->parent,
222 EVAS_CALLBACK_DEL,
223 _parent_del,
224 obj);
225 evas_object_event_callback_del_full(wd->parent,
226 EVAS_CALLBACK_MOVE,
227 _parent_move,
228 obj);
229 evas_object_event_callback_del_full(wd->parent,
230 EVAS_CALLBACK_RESIZE,
231 _parent_resize,
232 obj);
233
234 elm_widget_sub_object_del(wd->parent, obj);
235}
236
237static void
238_parent_resize(void *data,
239 Evas *e __UNUSED__,
240 Evas_Object *obj __UNUSED__,
241 void *event_info __UNUSED__)
242{
243 Widget_Data *wd = elm_widget_data_get(data);
244 if (!wd) return;
245
246 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
247
248 evas_object_hide(data);
249}
250
251static void
252_parent_move(void *data,
253 Evas *e __UNUSED__,
254 Evas_Object *obj __UNUSED__,
255 void *event_info __UNUSED__)
256{
257 Widget_Data *wd = elm_widget_data_get(data);
258
259 if (!wd) return;
260
261 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
262
263 if (wd->visible)
264 {
265 _sizing_eval(obj);
266 }
267}
268
269static void
270_parent_del(void *data,
271 Evas *e __UNUSED__,
272 Evas_Object *obj __UNUSED__,
273 void *event_info __UNUSED__)
274{
275 evas_object_del(data);
276}
277
278static void
279_adjust_pos_x(Evas_Coord_Point *pos, Evas_Coord_Point *base_size,
280 Evas_Coord_Rectangle *hover_area)
281{
282 pos->x -= (base_size->x / 2);
283
284 if (pos->x < hover_area->x)
285 pos->x = hover_area->x;
286 else if ((pos->x + base_size->x) > (hover_area->x + hover_area->w))
287 pos->x = (hover_area->x + hover_area->w) - base_size->x;
288
289 if (base_size->x > hover_area->w)
290 base_size->x -= (base_size->x - hover_area->w);
291
292 if (pos->x < hover_area->x)
293 pos->x = hover_area->x;
294}
295
296static void
297_adjust_pos_y(Evas_Coord_Point *pos, Evas_Coord_Point *base_size,
298 Evas_Coord_Rectangle *hover_area)
299{
300 pos->y -= (base_size->y / 2);
301
302 if (pos->y < hover_area->y)
303 pos->y = hover_area->y;
304 else if ((pos->y + base_size->y) > (hover_area->y + hover_area->h))
305 pos->y = hover_area->y + hover_area->h - base_size->y;
306
307 if (base_size->y > hover_area->h)
308 base_size->y -= (base_size->y - hover_area->h);
309
310 if (pos->y < hover_area->y)
311 pos->y = hover_area->y;
312}
313
314static Elm_Ctxpopup_Direction
315_calc_base_geometry(Evas_Object *obj, Evas_Coord_Rectangle *rect)
316{
317 Widget_Data *wd;
318 Evas_Coord_Point pos = {0, 0};
319 Evas_Coord_Point base_size;
320 Evas_Coord_Point max_size;
321 Evas_Coord_Point min_size;
322 Evas_Coord_Rectangle hover_area;
323 Evas_Coord_Point arrow_size;
324 Elm_Ctxpopup_Direction dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
325 Evas_Coord_Point temp;
326 int idx;
327
328 wd = elm_widget_data_get(obj);
329
330 if ((!wd) || (!rect))
331 return ELM_CTXPOPUP_DIRECTION_DOWN;
332
333 edje_object_part_geometry_get(wd->arrow, "ctxpopup_arrow", NULL, NULL,
334 &arrow_size.x, &arrow_size.y);
335 evas_object_resize(wd->arrow, arrow_size.x, arrow_size.y);
336
337 //Initialize Area Rectangle.
338 evas_object_geometry_get(wd->parent,
339 &hover_area.x,
340 &hover_area.y,
341 &hover_area.w,
342 &hover_area.h);
343
344 evas_object_geometry_get(obj, &pos.x, &pos.y, NULL, NULL);
345
346 //recalc the edje
347 edje_object_size_min_calc(wd->base, &base_size.x, &base_size.y);
348 evas_object_smart_calculate(wd->base);
349
350 //Limit to Max Size
351 evas_object_size_hint_max_get(obj, &max_size.x, &max_size.y);
352
353 if ((max_size.y > 0) && (base_size.y > max_size.y))
354 base_size.y = max_size.y;
355
356 if ((max_size.x > 0) && (base_size.x > max_size.x))
357 base_size.x = max_size.x;
358
359
360 //Limit to Min Size
361 evas_object_size_hint_min_get(obj, &min_size.x, &min_size.y);
362
363 if ((min_size.y > 0) && (base_size.y < min_size.y))
364 base_size.y = min_size.y;
365
366 if ((min_size.x > 0) && (base_size.x < min_size.x))
367 base_size.x = min_size.x;
368
369 //Check the Which direction is available.
370 //If find a avaialble direction, it adjusts position and size.
371 for (idx = 0; idx < 4; idx++)
372 {
373 switch (wd->dir_priority[idx])
374 {
375 case ELM_CTXPOPUP_DIRECTION_UNKNOWN:
376 case ELM_CTXPOPUP_DIRECTION_UP:
377 temp.y = (pos.y - base_size.y);
378 if ((temp.y - arrow_size.y) < hover_area.y)
379 continue;
380 _adjust_pos_x(&pos, &base_size, &hover_area);
381 pos.y -= base_size.y;
382 dir = ELM_CTXPOPUP_DIRECTION_UP;
383 break;
384 case ELM_CTXPOPUP_DIRECTION_LEFT:
385 temp.x = (pos.x - base_size.x);
386 if ((temp.x - arrow_size.x) < hover_area.x)
387 continue;
388 _adjust_pos_y(&pos, &base_size, &hover_area);
389 pos.x -= base_size.x;
390 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
391 break;
392 case ELM_CTXPOPUP_DIRECTION_RIGHT:
393 temp.x = (pos.x + base_size.x);
394 if ((temp.x + arrow_size.x) >
395 (hover_area.x + hover_area.w))
396 continue;
397 _adjust_pos_y(&pos, &base_size, &hover_area);
398 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
399 break;
400 case ELM_CTXPOPUP_DIRECTION_DOWN:
401 temp.y = (pos.y + base_size.y);
402 if ((temp.y + arrow_size.y) >
403 (hover_area.y + hover_area.h))
404 continue;
405 _adjust_pos_x(&pos, &base_size, &hover_area);
406 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
407 break;
408 default:
409 break;
410 }
411 break;
412 }
413
414 //In this case, all directions are invalid because of lack of space.
415 if (idx == 4)
416 {
417 Evas_Coord length[2];
418
419 if (!wd->horizontal)
420 {
421 length[0] = pos.y - hover_area.y;
422 length[1] = (hover_area.y + hover_area.h) - pos.y;
423
424 // ELM_CTXPOPUP_DIRECTION_UP
425 if (length[0] > length[1])
426 {
427 _adjust_pos_x(&pos, &base_size, &hover_area);
428 pos.y -= base_size.y;
429 dir = ELM_CTXPOPUP_DIRECTION_UP;
430 if (pos.y < (hover_area.y + arrow_size.y))
431 {
432 base_size.y -= ((hover_area.y + arrow_size.y) - pos.y);
433 pos.y = hover_area.y + arrow_size.y;
434 }
435 }
436 //ELM_CTXPOPUP_DIRECTION_DOWN
437 else
438 {
439 _adjust_pos_x(&pos, &base_size, &hover_area);
440 dir = ELM_CTXPOPUP_DIRECTION_DOWN;
441 if ((pos.y + arrow_size.y + base_size.y) >
442 (hover_area.y + hover_area.h))
443 base_size.y -=
444 ((pos.y + arrow_size.y + base_size.y) -
445 (hover_area.y + hover_area.h));
446 }
447 }
448 else
449 {
450 length[0] = pos.x - hover_area.x;
451 length[1] = (hover_area.x + hover_area.w) - pos.x;
452
453 //ELM_CTXPOPUP_DIRECTION_LEFT
454 if (length[0] > length[1])
455 {
456 _adjust_pos_y(&pos, &base_size, &hover_area);
457 pos.x -= base_size.x;
458 dir = ELM_CTXPOPUP_DIRECTION_LEFT;
459 if (pos.x < (hover_area.x + arrow_size.x))
460 {
461 base_size.x -= ((hover_area.x + arrow_size.x) - pos.x);
462 pos.x = hover_area.x + arrow_size.x;
463 }
464 }
465 //ELM_CTXPOPUP_DIRECTION_RIGHT
466 else
467 {
468 _adjust_pos_y(&pos, &base_size, &hover_area);
469 dir = ELM_CTXPOPUP_DIRECTION_RIGHT;
470 if (pos.x + (arrow_size.x + base_size.x) >
471 hover_area.x + hover_area.w)
472 base_size.x -=
473 ((pos.x + arrow_size.x + base_size.x) -
474 (hover_area.x + hover_area.w));
475 }
476 }
477 }
478
479 //Final position and size.
480 rect->x = pos.x;
481 rect->y = pos.y;
482 rect->w = base_size.x;
483 rect->h = base_size.y;
484
485 return dir;
486}
487
488static void
489_update_arrow(Evas_Object *obj, Elm_Ctxpopup_Direction dir,
490 Evas_Coord_Rectangle base_size)
491{
492 Evas_Coord x, y;
493 Evas_Coord_Rectangle arrow_size;
494 Widget_Data *wd;
495 double drag;
496
497 wd = elm_widget_data_get(obj);
498 if (!wd) return;
499
500 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
501 evas_object_geometry_get(wd->arrow, NULL, NULL, &arrow_size.w,
502 &arrow_size.h);
503
504 //edje_object_part_unswallow(wd->base, wd->arrow);
505
506 switch (dir)
507 {
508 case ELM_CTXPOPUP_DIRECTION_RIGHT:
509 edje_object_signal_emit(wd->arrow, "elm,state,left", "elm");
510 edje_object_part_swallow(wd->base,
511 "elm.swallow.arrow_left",
512 wd->arrow);
513 if (base_size.h > 0)
514 {
515 if (y < ((arrow_size.h * 0.5) + base_size.y))
516 y = 0;
517 else if (y > base_size.y + base_size.h - (arrow_size.h * 0.5))
518 y = base_size.h - arrow_size.h;
519 else
520 y = y - base_size.y - (arrow_size.h * 0.5);
521 drag = (double) (y) / (double) (base_size.h - arrow_size.h);
522 edje_object_part_drag_value_set(wd->base,
523 "elm.swallow.arrow_left",
524 1,
525 drag);
526 }
527 break;
528 case ELM_CTXPOPUP_DIRECTION_LEFT:
529 edje_object_signal_emit(wd->arrow, "elm,state,right", "elm");
530 edje_object_part_swallow(wd->base,
531 "elm.swallow.arrow_right",
532 wd->arrow);
533 if (base_size.h > 0)
534 {
535 if (y < ((arrow_size.h * 0.5) + base_size.y))
536 y = 0;
537 else if (y > (base_size.y + base_size.h - (arrow_size.h * 0.5)))
538 y = base_size.h - arrow_size.h;
539 else
540 y = y - base_size.y - (arrow_size.h * 0.5);
541 drag = (double) (y) / (double) (base_size.h - arrow_size.h);
542 edje_object_part_drag_value_set(wd->base,
543 "elm.swallow.arrow_right",
544 0,
545 drag);
546 }
547 break;
548 case ELM_CTXPOPUP_DIRECTION_DOWN:
549 edje_object_signal_emit(wd->arrow, "elm,state,top", "elm");
550 edje_object_part_swallow(wd->base, "elm.swallow.arrow_up", wd->arrow);
551 if (base_size.w > 0)
552 {
553 if (x < ((arrow_size.w * 0.5) + base_size.x))
554 x = 0;
555 else if (x > (base_size.x + base_size.w - (arrow_size.w * 0.5)))
556 x = base_size.w - arrow_size.w;
557 else
558 x = x - base_size.x - (arrow_size.w * 0.5);
559 drag = (double) (x) / (double) (base_size.w - arrow_size.w);
560 edje_object_part_drag_value_set(wd->base,
561 "elm.swallow.arrow_up",
562 drag,
563 1);
564 }
565 break;
566 case ELM_CTXPOPUP_DIRECTION_UP:
567 edje_object_signal_emit(wd->arrow, "elm,state,bottom", "elm");
568 edje_object_part_swallow(wd->base,
569 "elm.swallow.arrow_down",
570 wd->arrow);
571 if (base_size.w > 0)
572 {
573 if (x < ((arrow_size.w * 0.5) + base_size.x))
574 x = 0;
575 else if (x > (base_size.x + base_size.w - (arrow_size.w * 0.5)))
576 x = base_size.w - arrow_size.w;
577 else x = x - base_size.x - (arrow_size.w * 0.5);
578 drag = (double) (x) / (double) (base_size.w - arrow_size.w);
579 edje_object_part_drag_value_set(wd->base,
580 "elm.swallow.arrow_down",
581 drag,
582 0);
583 }
584 break;
585 default:
586 break;
587 }
588
589 //should be here for getting accurate geometry value
590 evas_object_smart_calculate(wd->base);
591}
592
593static void
594_hide_signal_emit(Evas_Object *obj, Elm_Ctxpopup_Direction dir)
595{
596 Widget_Data *wd;
597
598 wd = elm_widget_data_get(obj);
599 if (!wd->visible) return;
600
601 switch (dir)
602 {
603 case ELM_CTXPOPUP_DIRECTION_UP:
604 edje_object_signal_emit(wd->base, "elm,state,hide,up", "elm");
605 break;
606 case ELM_CTXPOPUP_DIRECTION_LEFT:
607 edje_object_signal_emit(wd->base, "elm,state,hide,left", "elm");
608 break;
609 case ELM_CTXPOPUP_DIRECTION_RIGHT:
610 edje_object_signal_emit(wd->base, "elm,state,hide,right", "elm");
611 break;
612 case ELM_CTXPOPUP_DIRECTION_DOWN:
613 edje_object_signal_emit(wd->base, "elm,state,hide,down", "elm");
614 break;
615 default:
616 break;
617 }
618
619 edje_object_signal_emit(wd->bg, "elm,state,hide", "elm");
620}
621
622static void
623_show_signal_emit(Evas_Object *obj, Elm_Ctxpopup_Direction dir)
624{
625 Widget_Data *wd;
626
627 wd = elm_widget_data_get(obj);
628 if (!wd->visible) return;
629 if ((wd->list) && (!wd->list_visible)) return;
630
631 switch (dir)
632 {
633 case ELM_CTXPOPUP_DIRECTION_UP:
634 edje_object_signal_emit(wd->base, "elm,state,show,up", "elm");
635 break;
636 case ELM_CTXPOPUP_DIRECTION_LEFT:
637 edje_object_signal_emit(wd->base, "elm,state,show,left", "elm");
638 break;
639 case ELM_CTXPOPUP_DIRECTION_RIGHT:
640 edje_object_signal_emit(wd->base, "elm,state,show,right", "elm");
641 break;
642 case ELM_CTXPOPUP_DIRECTION_DOWN:
643 edje_object_signal_emit(wd->base, "elm,state,show,down", "elm");
644 break;
645 default:
646 break;
647 }
648 edje_object_signal_emit(wd->bg, "elm,state,show", "elm");
649 edje_object_signal_emit(wd->base, "elm,state,show", "elm");
650}
651
652static void
653_sizing_eval(Evas_Object *obj)
654{
655 Widget_Data *wd;
656 Evas_Coord_Rectangle rect = { 0, 0, 1, 1 };
657 Evas_Coord_Point list_size = { 0, 0 };
658
659 wd = elm_widget_data_get(obj);
660 if (!wd) return;
661
662 //Base
663 wd->dir = _calc_base_geometry(obj, &rect);
664 _update_arrow(obj, wd->dir, rect);
665 _shift_base_by_arrow(wd->arrow, wd->dir, &rect);
666
667 if ((wd->list) && (wd->list_visible))
668 {
669 evas_object_geometry_get(wd->list, 0, 0, &list_size.x, &list_size.y);
670 if ((list_size.x >= rect.w) || (list_size.y >= rect.h))
671 {
672 elm_list_mode_set(wd->list, ELM_LIST_COMPRESS);
673 evas_object_size_hint_min_set(wd->box, rect.w, rect.h);
674 evas_object_size_hint_min_set(obj, rect.w, rect.h);
675 }
676 }
677
678 evas_object_move(wd->base, rect.x, rect.y);
679 evas_object_resize(wd->base, rect.w, rect.h);
680 _show_signal_emit(obj, wd->dir);
681}
682
683static void
684_shift_base_by_arrow(Evas_Object *arrow, Elm_Ctxpopup_Direction dir,
685 Evas_Coord_Rectangle *rect)
686{
687 Evas_Coord arrow_w, arrow_h;
688
689 evas_object_geometry_get(arrow, NULL, NULL, &arrow_w, &arrow_h);
690 switch (dir)
691 {
692 case ELM_CTXPOPUP_DIRECTION_RIGHT:
693 rect->x += arrow_w;
694 break;
695 case ELM_CTXPOPUP_DIRECTION_LEFT:
696 rect->x -= arrow_w;
697 break;
698 case ELM_CTXPOPUP_DIRECTION_DOWN:
699 rect->y += arrow_h;
700 break;
701 case ELM_CTXPOPUP_DIRECTION_UP:
702 rect->y -= arrow_h;
703 break;
704 default:
705 break;
706 }
707}
708
709static void
710_del_pre_hook(Evas_Object *obj)
711{
712 Widget_Data *wd;
713
714 wd = elm_widget_data_get(obj);
715 if (!wd) return;
716
717 evas_object_event_callback_del_full(wd->box, EVAS_CALLBACK_RESIZE,
718 _content_resize, obj);
719 _parent_cut_off(obj);
720}
721
722static void
723_del_hook(Evas_Object *obj)
724{
725 Widget_Data *wd;
726
727 wd = elm_widget_data_get(obj);
728 if (!wd) return;
729
730 elm_ctxpopup_clear(obj);
731 evas_object_del(wd->arrow);
732 evas_object_del(wd->base);
733 free(wd);
734}
735
736//FIXME: lost the content size when theme hook is called.
737static void
738_theme_hook(Evas_Object *obj)
739{
740 Widget_Data *wd;
741 Eina_Bool rtl;
742
743 wd = elm_widget_data_get(obj);
744 if (!wd) return;
745
746 _elm_widget_mirrored_reload(obj);
747 rtl = elm_widget_mirrored_get(obj);
748
749 _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg",
750 elm_widget_style_get(obj));
751 _elm_theme_object_set(obj, wd->base, "ctxpopup", "base",
752 elm_widget_style_get(obj));
753 _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow",
754 elm_widget_style_get(obj));
755
756 if (wd->list)
757 {
758 if (!strncmp(elm_object_style_get(obj), "default", strlen("default")))
759 elm_object_style_set(wd->list, "ctxpopup");
760 else
761 elm_object_style_set(wd->list, elm_object_style_get(obj));
762 }
763
764 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
765
766 if (wd->visible)
767 {
768 _sizing_eval(obj);
769 }
770}
771
772static void
773_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
774{
775 ELM_CHECK_WIDTYPE(obj, widtype);
776 Evas_Coord min_w = -1, min_h = -1;
777 Widget_Data *wd;
778 if ((part) && (strcmp(part, "default"))) return;
779 wd = elm_widget_data_get(obj);
780 if ((!wd) || (!content)) return;
781 if (content == wd->content) return;
782
783 //TODO: wd->list
784 if (wd->content) evas_object_del(wd->content);
785
786 //Use Box
787 wd->box = elm_box_add(obj);
788 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
789 EVAS_HINT_EXPAND);
790 evas_object_size_hint_weight_set(content, EVAS_HINT_EXPAND,
791 EVAS_HINT_EXPAND);
792 evas_object_size_hint_fill_set(content, EVAS_HINT_FILL,
793 EVAS_HINT_FILL);
794 evas_object_show(content);
795 evas_object_size_hint_min_get(content, &min_w, &min_h);
796 evas_object_size_hint_min_set(wd->box, min_w, min_h);
797 elm_box_pack_end(wd->box, content);
798
799 evas_object_event_callback_add(wd->box, EVAS_CALLBACK_RESIZE,
800 _content_resize, obj);
801 evas_object_event_callback_add(wd->box, EVAS_CALLBACK_DEL,
802 _content_del, obj);
803
804 elm_widget_sub_object_add(obj, wd->box);
805 edje_object_part_swallow(wd->base, "elm.swallow.content", wd->box);
806
807 wd->content = content;
808 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
809
810 if (wd->visible)
811 _sizing_eval(obj);
812}
813
814static Evas_Object *
815_content_unset_hook(Evas_Object *obj, const char *part)
816{
817 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
818
819 Widget_Data *wd;
820 Evas_Object *content;
821 if ((part) && (strcmp(part, "default"))) return NULL;
822 wd = elm_widget_data_get(obj);
823 if (!wd) return NULL;
824
825 content = wd->content;
826 if ((!content) || (!wd->box)) return NULL;
827
828 edje_object_part_unswallow(wd->base, wd->box);
829 elm_widget_sub_object_del(obj, wd->box);
830 evas_object_event_callback_del(wd->box, EVAS_CALLBACK_DEL, _content_del);
831 edje_object_signal_emit(wd->base, "elm,state,content,disable", "elm");
832
833 evas_object_del(wd->box);
834 wd->box = NULL;
835 wd->content = NULL;
836 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
837
838 return content;
839}
840
841static Evas_Object *
842_content_get_hook(const Evas_Object *obj, const char *part)
843{
844 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
845 Widget_Data *wd;
846 if ((part) && (strcmp(part, "default"))) return NULL;
847 wd = elm_widget_data_get(obj);
848 if (!wd) return NULL;
849 return wd->content;
850}
851
852static void
853_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
854{
855 Widget_Data *wd;
856 Elm_Ctxpopup_Item *ctxpopup_it;
857
858 if ((part) && (strcmp(part, "default"))) return;
859
860 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
861
862 wd = elm_widget_data_get(WIDGET(ctxpopup_it));
863 if (!wd) return;
864
865 elm_object_item_part_text_set(ctxpopup_it->list_item, "default", label);
866 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
867
868 if (wd->visible)
869 {
870 _sizing_eval(WIDGET(ctxpopup_it));
871 }
872}
873
874static const char *
875_item_text_get_hook(const Elm_Object_Item *it, const char *part)
876{
877 Elm_Ctxpopup_Item *ctxpopup_it;
878 if (part && strcmp(part, "default")) return NULL;
879 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
880 return elm_object_item_part_text_get(ctxpopup_it->list_item, "default");
881}
882
883static void
884_item_content_set_hook(Elm_Object_Item *it,
885 const char *part,
886 Evas_Object *content)
887{
888 Widget_Data *wd;
889 Elm_Ctxpopup_Item *ctxpopup_it;
890
891 if ((part) && (strcmp(part, "icon"))
892 && (strcmp(part, "start"))
893 && (strcmp(part, "end"))) return;
894
895 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
896
897 wd = elm_widget_data_get(WIDGET(ctxpopup_it));
898 if (!wd) return;
899
900 if ((part) && (!strcmp(part, "end")))
901 elm_object_item_part_content_set(ctxpopup_it->list_item, "end", content);
902 else
903 elm_object_item_part_content_set(ctxpopup_it->list_item, "start", content);
904
905 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
906
907 if (wd->visible)
908 {
909 _sizing_eval(WIDGET(ctxpopup_it));
910 }
911}
912
913static Evas_Object *
914_item_content_get_hook(const Elm_Object_Item *it, const char *part)
915{
916 Elm_Ctxpopup_Item *ctxpopup_it;
917
918 if (part && strcmp(part, "icon") && strcmp(part, "start")
919 && strcmp(part, "end")) return NULL;
920
921 ctxpopup_it = (Elm_Ctxpopup_Item *)it;
922
923 if (part && !strcmp(part, "end"))
924 return elm_object_item_part_content_get(ctxpopup_it->list_item, "end");
925 else
926 return elm_object_item_part_content_get(ctxpopup_it->list_item, "start");
927}
928
929static void
930_item_disable_hook(Elm_Object_Item *it)
931{
932 Widget_Data *wd;
933 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
934
935 wd = elm_widget_data_get(WIDGET(ctxpopup_it));
936 if (!wd) return;
937
938 elm_object_item_disabled_set(ctxpopup_it->list_item,
939 elm_widget_item_disabled_get(ctxpopup_it));
940}
941
942static void
943_item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
944 const char *source)
945{
946 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
947 elm_object_item_signal_emit(ctxpopup_it->list_item, emission, source);
948}
949
950static void
951_bg_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
952 const char *emission __UNUSED__, const char *source __UNUSED__)
953{
954 Widget_Data *wd = elm_widget_data_get(data);
955 if (!wd) return;
956 _hide_signal_emit(data, wd->dir);
957}
958
959static void
960_ctxpopup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
961 void *event_info __UNUSED__)
962{
963 Widget_Data *wd;
964
965 wd = elm_widget_data_get(obj);
966 if (!wd) return;
967
968 if ((!wd->list) && (!wd->content)) return;
969
970 if (wd->list)
971 {
972 elm_list_go(wd->list);
973 wd->visible = EINA_TRUE;
974 return;
975 }
976
977 wd->visible = EINA_TRUE;
978
979 evas_object_show(wd->bg);
980 evas_object_show(wd->base);
981 evas_object_show(wd->arrow);
982
983 edje_object_signal_emit(wd->bg, "elm,state,show", "elm");
984 edje_object_signal_emit(wd->base, "elm,state,show", "elm");
985
986 _sizing_eval(obj);
987
988 elm_object_focus_set(obj, EINA_TRUE);
989}
990
991static void
992_hide_finished(void *data, Evas_Object *obj __UNUSED__,
993 const char *emission __UNUSED__, const char *source __UNUSED__)
994{
995 evas_object_hide(data);
996 evas_object_smart_callback_call(data, SIG_DISMISSED, NULL);
997}
998
999static void
1000_ctxpopup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1001 void *event_info __UNUSED__)
1002{
1003 Widget_Data *wd = elm_widget_data_get(obj);
1004 if ((!wd) || (!wd->visible)) return;
1005
1006 evas_object_hide(wd->bg);
1007 evas_object_hide(wd->arrow);
1008 evas_object_hide(wd->base);
1009
1010 wd->visible = EINA_FALSE;
1011 wd->list_visible = EINA_FALSE;
1012}
1013
1014static void
1015_content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
1016 void *event_info __UNUSED__)
1017{
1018 Widget_Data *wd = elm_widget_data_get(data);
1019 if (!wd) return;
1020 elm_box_recalculate(wd->box);
1021 _sizing_eval(data);
1022}
1023
1024static void
1025_list_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
1026 void *event_info __UNUSED__)
1027{
1028 Widget_Data *wd = elm_widget_data_get(data);
1029 if (!wd) return;
1030 if (!wd->visible) return;
1031 if (wd->list_visible) return;
1032
1033 wd->list_visible = EINA_TRUE;
1034
1035 evas_object_show(wd->bg);
1036 evas_object_show(wd->base);
1037 evas_object_show(wd->arrow);
1038 _sizing_eval(obj);
1039}
1040
1041static void
1042_ctxpopup_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1043 void *event_info __UNUSED__)
1044{
1045 Widget_Data *wd;
1046
1047 wd = elm_widget_data_get(obj);
1048
1049 if (!wd) return;
1050
1051 if (wd->visible)
1052 evas_object_show(wd->arrow);
1053
1054 _sizing_eval(obj);
1055}
1056
1057static void
1058_restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1059{
1060 Widget_Data *wd = elm_widget_data_get(obj);
1061 if (!wd) return;
1062 evas_object_layer_set(wd->bg,
1063 evas_object_layer_get(obj));
1064 evas_object_layer_set(wd->base,
1065 evas_object_layer_get(obj));
1066}
1067
1068static void
1069_content_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
1070 void *event_info __UNUSED__)
1071{
1072 elm_object_content_unset(data);
1073}
1074
1075static void
1076_list_del(Widget_Data *wd)
1077{
1078 if (!wd->list) return;
1079
1080 edje_object_part_unswallow(wd->base, wd->box);
1081 elm_box_unpack(wd->box, wd->list);
1082 evas_object_del(wd->list);
1083 wd->list = NULL;
1084 wd->box = NULL;
1085}
1086
1087static Eina_Bool
1088_item_del_pre_hook(Elm_Object_Item *it)
1089{
1090 Evas_Object *list;
1091 Widget_Data *wd;
1092 Elm_Ctxpopup_Item *ctxpopup_it = (Elm_Ctxpopup_Item *)it;
1093
1094 wd = elm_widget_data_get(WIDGET(ctxpopup_it));
1095 if (!wd) return EINA_FALSE;
1096
1097 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1098
1099 list = elm_object_item_widget_get(ctxpopup_it->list_item);
1100
1101 if (eina_list_count(elm_list_items_get(list)) < 2)
1102 {
1103 elm_object_item_del(ctxpopup_it->list_item);
1104 evas_object_hide(WIDGET(ctxpopup_it));
1105 return EINA_TRUE;
1106 }
1107
1108 elm_object_item_del(ctxpopup_it->list_item);
1109 if (wd->list_visible)
1110 _sizing_eval(WIDGET(ctxpopup_it));
1111
1112 return EINA_TRUE;
1113}
1114
1115static void
1116_disable_hook(Evas_Object *obj)
1117{
1118 //TODO: elm_object_disabled_set(); does not ignite this part
1119 Widget_Data *wd = elm_widget_data_get(obj);
1120 if (!wd) return;
1121
1122 elm_object_disabled_set(wd->list, elm_widget_disabled_get(obj));
1123}
1124
1125static void
1126_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
1127{
1128 Widget_Data *wd = elm_widget_data_get(obj);
1129 if (!wd) return;
1130 edje_object_signal_emit(wd->base, emission, source);
1131}
1132
1133static void
1134_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
1135{
1136 Widget_Data *wd = elm_widget_data_get(obj);
1137 if (!wd) return;
1138 edje_object_signal_callback_add(wd->base, emission, source, func_cb, data);
1139}
1140
1141static void
1142_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
1143{
1144 Widget_Data *wd = elm_widget_data_get(obj);
1145 if (!wd) return;
1146 edje_object_signal_callback_del_full(wd->base, emission, source, func_cb, data);
1147}
1148
1149EAPI Evas_Object *
1150elm_ctxpopup_add(Evas_Object *parent)
1151{
1152 Evas_Object *obj;
1153 Evas *e;
1154 Widget_Data *wd;
1155
1156 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1157
1158 ELM_SET_WIDTYPE(widtype, "ctxpopup");
1159 elm_widget_type_set(obj, "ctxpopup");
1160 elm_widget_data_set(obj, wd);
1161 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1162 elm_widget_del_hook_set(obj, _del_hook);
1163 elm_widget_theme_hook_set(obj, _theme_hook);
1164 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1165 elm_widget_can_focus_set(obj, EINA_TRUE);
1166 elm_widget_event_hook_set(obj, _event_hook);
1167 elm_widget_content_set_hook_set(obj, _content_set_hook);
1168 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1169 elm_widget_content_get_hook_set(obj, _content_get_hook);
1170 elm_widget_disable_hook_set(obj, _disable_hook);
1171 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1172 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
1173 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
1174
1175 //Background
1176 wd->bg = edje_object_add(e);
1177 elm_widget_sub_object_add(obj, wd->bg);
1178 _elm_theme_object_set(obj, wd->bg, "ctxpopup", "bg", "default");
1179 edje_object_signal_callback_add(wd->bg,
1180 "elm,action,click",
1181 "",
1182 _bg_clicked_cb,
1183 obj);
1184 //Base
1185 wd->base = edje_object_add(e);
1186 elm_widget_sub_object_add(obj, wd->base);
1187 _elm_theme_object_set(obj, wd->base, "ctxpopup", "base", "default");
1188 edje_object_signal_callback_add(wd->base, "elm,action,hide,finished", "",
1189 _hide_finished, obj);
1190
1191 //Arrow
1192 wd->arrow = edje_object_add(e);
1193 elm_widget_sub_object_add(obj, wd->arrow);
1194 _elm_theme_object_set(obj, wd->arrow, "ctxpopup", "arrow", "default");
1195
1196 wd->dir_priority[0] = ELM_CTXPOPUP_DIRECTION_UP;
1197 wd->dir_priority[1] = ELM_CTXPOPUP_DIRECTION_LEFT;
1198 wd->dir_priority[2] = ELM_CTXPOPUP_DIRECTION_RIGHT;
1199 wd->dir_priority[3] = ELM_CTXPOPUP_DIRECTION_DOWN;
1200 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1201
1202 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _ctxpopup_show,
1203 NULL);
1204 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _ctxpopup_hide,
1205 NULL);
1206 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _ctxpopup_move,
1207 NULL);
1208 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
1209 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1210 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1211 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1212 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1213
1214 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1215
1216 //default parent is to be hover parent
1217 elm_ctxpopup_hover_parent_set(obj, parent);
1218
1219 return obj;
1220}
1221
1222EAPI void
1223elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
1224{
1225 ELM_CHECK_WIDTYPE(obj, widtype);
1226
1227 Widget_Data *wd;
1228 Evas_Coord x, y, w, h;
1229
1230 wd = elm_widget_data_get(obj);
1231 if ((!wd) || (!parent)) return;
1232
1233 _parent_cut_off(obj);
1234
1235 if (parent)
1236 {
1237 evas_object_event_callback_add(parent,
1238 EVAS_CALLBACK_DEL,
1239 _parent_del,
1240 obj);
1241 evas_object_event_callback_add(parent,
1242 EVAS_CALLBACK_MOVE,
1243 _parent_move,
1244 obj);
1245 evas_object_event_callback_add(parent,
1246 EVAS_CALLBACK_RESIZE,
1247 _parent_resize,
1248 obj);
1249 }
1250
1251 elm_widget_sub_object_add(parent, obj);
1252 wd->parent = parent;
1253
1254 //Update Background
1255 evas_object_geometry_get(parent, &x, &y, &w, &h);
1256 evas_object_move(wd->bg, x, y);
1257 evas_object_resize(wd->bg, w, h);
1258
1259 if (wd->visible) _sizing_eval(obj);
1260}
1261
1262EAPI Evas_Object *
1263elm_ctxpopup_hover_parent_get(const Evas_Object *obj)
1264{
1265 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1266
1267 Widget_Data *wd;
1268
1269 wd = elm_widget_data_get(obj);
1270 if (!wd) return NULL;
1271
1272 return wd->parent;
1273}
1274
1275EAPI void
1276elm_ctxpopup_clear(Evas_Object * obj)
1277{
1278 ELM_CHECK_WIDTYPE(obj, widtype);
1279
1280 Widget_Data *wd = elm_widget_data_get(obj);
1281 if (!wd) return;
1282
1283 _list_del(wd);
1284 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1285}
1286
1287EAPI void
1288elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
1289{
1290 ELM_CHECK_WIDTYPE(obj, widtype);
1291
1292 Widget_Data *wd;
1293
1294 wd = elm_widget_data_get(obj);
1295 if (!wd) return;
1296
1297 wd->horizontal = !!horizontal;
1298
1299 if ((!wd->list))
1300 return;
1301
1302 if (!horizontal)
1303 {
1304 elm_list_horizontal_set(wd->list, wd->horizontal);
1305 }
1306 else
1307 {
1308 elm_list_horizontal_set(wd->list, wd->horizontal);
1309 }
1310
1311 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1312
1313 if (wd->visible)
1314 _sizing_eval(obj);
1315}
1316
1317EAPI Eina_Bool
1318elm_ctxpopup_horizontal_get(const Evas_Object *obj)
1319{
1320 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1321
1322 Widget_Data *wd;
1323
1324 wd = elm_widget_data_get(obj);
1325 if (!wd) return EINA_FALSE;
1326
1327 return wd->horizontal;
1328}
1329
1330EAPI Elm_Object_Item *
1331elm_ctxpopup_item_append(Evas_Object *obj, const char *label,
1332 Evas_Object *icon, Evas_Smart_Cb func,
1333 const void *data)
1334{
1335 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1336
1337 Widget_Data *wd;
1338 Elm_Ctxpopup_Item *item;
1339
1340 wd = elm_widget_data_get(obj);
1341 if (!wd) return NULL;
1342
1343 item = elm_widget_item_new(obj, Elm_Ctxpopup_Item);
1344 if (!item) return NULL;
1345
1346 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
1347 elm_widget_item_disable_hook_set(item, _item_disable_hook);
1348 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
1349 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
1350 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
1351 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
1352 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
1353
1354 if (!wd->list)
1355 {
1356 //The first item is appended.
1357 wd->list = elm_list_add(obj);
1358 elm_list_mode_set(wd->list, ELM_LIST_EXPAND);
1359 elm_list_horizontal_set(wd->list, wd->horizontal);
1360 evas_object_event_callback_add(wd->list, EVAS_CALLBACK_RESIZE,
1361 _list_resize, obj);
1362 _content_set_hook(obj, "default", wd->list);
1363 }
1364
1365 item->list_item = elm_list_item_append(wd->list, label, icon, NULL, func, data);
1366
1367 wd->dir = ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1368
1369 if (wd->visible) _sizing_eval(obj);
1370
1371 return (Elm_Object_Item *)item;
1372}
1373
1374EAPI void
1375elm_ctxpopup_direction_priority_set(Evas_Object *obj,
1376 Elm_Ctxpopup_Direction first,
1377 Elm_Ctxpopup_Direction second,
1378 Elm_Ctxpopup_Direction third,
1379 Elm_Ctxpopup_Direction fourth)
1380{
1381 ELM_CHECK_WIDTYPE(obj, widtype);
1382 Widget_Data *wd;
1383
1384 wd = elm_widget_data_get(obj);
1385 if (!wd) return;
1386
1387 wd->dir_priority[0] = first;
1388 wd->dir_priority[1] = second;
1389 wd->dir_priority[2] = third;
1390 wd->dir_priority[3] = fourth;
1391
1392 if (wd->visible)
1393 _sizing_eval(obj);
1394}
1395
1396EAPI void
1397elm_ctxpopup_direction_priority_get(Evas_Object *obj,
1398 Elm_Ctxpopup_Direction *first,
1399 Elm_Ctxpopup_Direction *second,
1400 Elm_Ctxpopup_Direction *third,
1401 Elm_Ctxpopup_Direction *fourth)
1402{
1403 ELM_CHECK_WIDTYPE(obj, widtype);
1404 Widget_Data *wd;
1405
1406 wd = elm_widget_data_get(obj);
1407 if (!wd) return;
1408
1409 if (first) *first = wd->dir_priority[0];
1410 if (second) *second = wd->dir_priority[1];
1411 if (third) *third = wd->dir_priority[2];
1412 if (fourth) *fourth = wd->dir_priority[3];
1413}
1414
1415EAPI Elm_Ctxpopup_Direction
1416elm_ctxpopup_direction_get(const Evas_Object *obj)
1417{
1418 ELM_CHECK_WIDTYPE(obj, widtype) ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1419 Widget_Data *wd;
1420
1421 wd = elm_widget_data_get(obj);
1422 if (!wd) return ELM_CTXPOPUP_DIRECTION_UNKNOWN;
1423 return wd->dir;
1424}
1425
1426EAPI void
1427elm_ctxpopup_dismiss(Evas_Object *obj)
1428{
1429 ELM_CHECK_WIDTYPE(obj, widtype);
1430 Widget_Data *wd = elm_widget_data_get(obj);
1431 if (!wd) return;
1432 _hide_signal_emit(obj, wd->dir);
1433}
diff --git a/libraries/elementary/src/lib/elc_ctxpopup.h b/libraries/elementary/src/lib/elc_ctxpopup.h
new file mode 100644
index 0000000..67a7b9f
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_ctxpopup.h
@@ -0,0 +1,211 @@
1/**
2 * @defgroup Ctxpopup Ctxpopup
3 * @ingroup Elementary
4 *
5 * @image html img/widget/ctxpopup/preview-00.png
6 * @image latex img/widget/ctxpopup/preview-00.eps
7 *
8 * @brief Context popup widget.
9 *
10 * A ctxpopup is a widget that, when shown, pops up a list of items.
11 * It automatically chooses an area inside its parent object's view
12 * (set via elm_ctxpopup_add() and elm_ctxpopup_hover_parent_set()) to
13 * optimally fit into it. In the default theme, it will also point an
14 * arrow to it's top left position at the time one shows it. Ctxpopup
15 * items have a label and/or an icon. It is intended for a small
16 * number of items (hence the use of list, not genlist).
17 *
18 * @note Ctxpopup is a specialization of @ref Hover.
19 *
20 * Signals that you can add callbacks for are:
21 * "dismissed" - the ctxpopup was dismissed
22 *
23 * Default content parts of the ctxpopup widget that you can use for are:
24 * @li "default" - A content of the ctxpopup
25 *
26 * Default content parts of the ctxpopup items that you can use for are:
27 * @li "icon" - An icon in the title area
28 *
29 * Default text parts of the ctxpopup items that you can use for are:
30 * @li "default" - Title label in the title area
31 *
32 * Supported elm_object common APIs.
33 * @li @ref elm_object_disabled_set
34 * @li @ref elm_object_disabled_get
35 * @li @ref elm_object_part_content_set
36 * @li @ref elm_object_part_content_get
37 * @li @ref elm_object_part_content_unset
38 * @li @ref elm_object_signal_emit
39 * @li @ref elm_object_signal_callback_add
40 * @li @ref elm_object_signal_callback_del
41 *
42 * Supported elm_object_item common APIs.
43 * @li @ref elm_object_item_disabled_set
44 * @li @ref elm_object_item_disabled_get
45 * @li @ref elm_object_item_part_text_set
46 * @li @ref elm_object_item_part_text_get
47 * @li @ref elm_object_item_part_content_set
48 * @li @ref elm_object_item_part_content_get
49 * @li @ref elm_object_item_signal_emit
50 *
51 * @ref tutorial_ctxpopup shows the usage of a good deal of the API.
52 * @{
53 */
54
55typedef enum
56{
57 ELM_CTXPOPUP_DIRECTION_DOWN, /**< ctxpopup show appear below clicked area */
58 ELM_CTXPOPUP_DIRECTION_RIGHT, /**< ctxpopup show appear to the right of the clicked area */
59 ELM_CTXPOPUP_DIRECTION_LEFT, /**< ctxpopup show appear to the left of the clicked area */
60 ELM_CTXPOPUP_DIRECTION_UP, /**< ctxpopup show appear above the clicked area */
61 ELM_CTXPOPUP_DIRECTION_UNKNOWN, /**< ctxpopup does not determine it's direction yet*/
62} Elm_Ctxpopup_Direction; /**< Direction in which to show the popup */
63
64/**
65 * @brief Add a new Ctxpopup object to the parent.
66 *
67 * @param parent Parent object
68 * @return New object or @c NULL, if it cannot be created
69 *
70 * @ingroup Ctxpopup
71 */
72EAPI Evas_Object *elm_ctxpopup_add(Evas_Object *parent);
73
74/**
75 * @brief Set the Ctxpopup's parent
76 *
77 * @param obj The ctxpopup object
78 * @param parent The parent to use
79 *
80 * Set the parent object.
81 *
82 * @note elm_ctxpopup_add() will automatically call this function
83 * with its @c parent argument.
84 *
85 * @see elm_ctxpopup_add()
86 * @see elm_hover_parent_set()
87 *
88 * @ingroup Ctxpopup
89 */
90EAPI void elm_ctxpopup_hover_parent_set(Evas_Object *obj, Evas_Object *parent);
91
92/**
93 * @brief Get the Ctxpopup's parent
94 *
95 * @param obj The ctxpopup object
96 *
97 * @see elm_ctxpopup_hover_parent_set() for more information
98 *
99 * @ingroup Ctxpopup
100 */
101EAPI Evas_Object *elm_ctxpopup_hover_parent_get(const Evas_Object *obj);
102
103/**
104 * @brief Clear all items in the given ctxpopup object.
105 *
106 * @param obj Ctxpopup object
107 *
108 * @ingroup Ctxpopup
109 */
110EAPI void elm_ctxpopup_clear(Evas_Object *obj);
111
112/**
113 * @brief Change the ctxpopup's orientation to horizontal or vertical.
114 *
115 * @param obj Ctxpopup object
116 * @param horizontal @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical
117 *
118 * @ingroup Ctxpopup
119 */
120EAPI void elm_ctxpopup_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
121
122/**
123 * @brief Get the value of current ctxpopup object's orientation.
124 *
125 * @param obj Ctxpopup object
126 * @return @c EINA_TRUE for horizontal mode, @c EINA_FALSE for vertical mode (or errors)
127 *
128 * @see elm_ctxpopup_horizontal_set()
129 *
130 * @ingroup Ctxpopup
131 */
132EAPI Eina_Bool elm_ctxpopup_horizontal_get(const Evas_Object *obj);
133
134/**
135 * @brief Add a new item to a ctxpopup object.
136 *
137 * @param obj Ctxpopup object
138 * @param icon Icon to be set on new item
139 * @param label The Label of the new item
140 * @param func Convenience function called when item selected
141 * @param data Data passed to @p func
142 * @return A handle to the item added or @c NULL, on errors
143 *
144 * @warning Ctxpopup can't hold both an item list and a content at the same
145 * time. When an item is added, any previous content will be removed.
146 *
147 * @see elm_object_content_set()
148 *
149 * @ingroup Ctxpopup
150 */
151EAPI Elm_Object_Item *elm_ctxpopup_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data);
152
153/**
154 * @brief Set the direction priority of a ctxpopup.
155 *
156 * @param obj Ctxpopup object
157 * @param first 1st priority of direction
158 * @param second 2nd priority of direction
159 * @param third 3th priority of direction
160 * @param fourth 4th priority of direction
161 *
162 * This functions gives a chance to user to set the priority of ctxpopup
163 * showing direction. This doesn't guarantee the ctxpopup will appear in the
164 * requested direction.
165 *
166 * @see Elm_Ctxpopup_Direction
167 *
168 * @ingroup Ctxpopup
169 */
170EAPI 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);
171
172/**
173 * @brief Get the direction priority of a ctxpopup.
174 *
175 * @param obj Ctxpopup object
176 * @param first 1st priority of direction to be returned
177 * @param second 2nd priority of direction to be returned
178 * @param third 3th priority of direction to be returned
179 * @param fourth 4th priority of direction to be returned
180 *
181 * @see elm_ctxpopup_direction_priority_set() for more information.
182 *
183 * @ingroup Ctxpopup
184 */
185EAPI 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);
186
187/**
188 * @brief Get the current direction of a ctxpopup.
189 *
190 * @param obj Ctxpopup object
191 * @return current direction of a ctxpopup
192 *
193 * @warning Once the ctxpopup showed up, the direction would be determined
194 *
195 * @ingroup Ctxpopup
196 */
197EAPI Elm_Ctxpopup_Direction elm_ctxpopup_direction_get(const Evas_Object *obj);
198
199/**
200 * @brief Dismiss a ctxpopup object
201 *
202 * @param obj The ctxpopup object
203 * Use this function to simulate clicking outside the ctxpopup to dismiss it.
204 * In this way, the ctxpopup will be hidden and the "clicked" signal will be
205 * emitted.
206 */
207EAPI void elm_ctxpopup_dismiss(Evas_Object *obj);
208
209/**
210 * @}
211 */
diff --git a/libraries/elementary/src/lib/elc_dayselector.c b/libraries/elementary/src/lib/elc_dayselector.c
new file mode 100644
index 0000000..68f351b
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_dayselector.c
@@ -0,0 +1,669 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Dayselector_Item Elm_Dayselector_Item;
6
7/* signals to edc */
8#define ITEM_TYPE_WEEKDAY_DEFAULT "elm,type,weekday,default"
9#define ITEM_TYPE_WEEKDAY_STYLE1 "elm,type,weekday,style1"
10#define ITEM_TYPE_WEEKEND_DEFAULT "elm,type,weekend,default"
11#define ITEM_TYPE_WEEKEND_STYLE1 "elm,type,weekend,style1"
12#define ITEM_POS_LEFT "elm,pos,check,left"
13#define ITEM_POS_RIGHT "elm,pos,check,right"
14#define ITEM_POS_MIDDLE "elm,pos,check,middle"
15
16struct _Widget_Data
17{
18 Evas_Object *base;
19 Eina_List *items;
20 Elm_Dayselector_Day week_start;
21 Elm_Dayselector_Day weekend_start;
22 unsigned int weekend_len;
23};
24
25struct _Elm_Dayselector_Item
26{
27 ELM_WIDGET_ITEM;
28 Elm_Dayselector_Day day;
29 const char *day_style;
30};
31
32static const char *widtype = NULL;
33static void _del_hook(Evas_Object *obj);
34static void _sizing_eval(Evas_Object* obj);
35static void _dayselector_resize(void *data, Evas *e __UNUSED__,
36 Evas_Object *obj __UNUSED__, void *event_info __UNUSED__);
37static void _disable_hook(Evas_Object *obj);
38static Eina_Bool _focus_next_hook(const Evas_Object *obj,
39 Elm_Focus_Direction dir __UNUSED__,
40 Evas_Object **next __UNUSED__);
41static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
42static void _translate_hook(Evas_Object *obj);
43static void _theme_hook(Evas_Object *obj);
44static void _item_text_set_hook(Evas_Object *obj, const char *item,
45 const char *label);
46static const char *_item_text_get_hook(const Evas_Object *obj,
47 const char *item);
48static void _content_set_hook(Evas_Object *obj, const char *item,
49 Evas_Object *content);
50static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *item);
51static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *item);
52static void _signal_emit_cb(void *data, Evas_Object *obj, const char *emission,
53 const char *source __UNUSED__);
54static void _item_clicked_cb(void *data, Evas_Object *obj,
55 void *event_info __UNUSED__);
56static Elm_Dayselector_Item * _item_find(const Evas_Object *obj,
57 Elm_Dayselector_Day day);
58static void _items_style_set(Evas_Object *obj);
59static void _update_items(Evas_Object *obj);
60static void _create_items(Evas_Object *obj);
61
62static const char SIG_CHANGED[] = "dayselector,changed";
63static const char SIG_LANG_CHANGED[] = "language,changed";
64static const Evas_Smart_Cb_Description _signals[] = {
65 {SIG_CHANGED, ""},
66 {SIG_LANG_CHANGED, ""},
67 {NULL, NULL}
68};
69
70static void
71_del_hook(Evas_Object *obj)
72{
73 Elm_Dayselector_Item *it;
74 Widget_Data *wd = elm_widget_data_get(obj);
75 if (!wd) return;
76
77 EINA_LIST_FREE(wd->items, it)
78 {
79 wd->items = eina_list_remove(wd->items, it);
80 eina_stringshare_del(it->day_style);
81 elm_widget_item_free(it);
82 }
83 free(wd);
84}
85
86static void
87_sizing_eval(Evas_Object* obj)
88{
89 Evas_Coord min_w = -1, min_h = -1;
90 Widget_Data *wd = elm_widget_data_get(obj);
91 if (!wd) return;
92
93 elm_coords_finger_size_adjust(ELM_DAYSELECTOR_MAX, &min_w, 1, &min_h);
94 edje_object_size_min_restricted_calc(wd->base, &min_w, &min_h, min_w, min_h);
95 elm_coords_finger_size_adjust(ELM_DAYSELECTOR_MAX, &min_w, 1, &min_h);
96 evas_object_size_hint_min_set(obj, min_w, min_h);
97}
98
99static void
100_dayselector_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
101 void *event_info __UNUSED__)
102{
103 _sizing_eval(data);
104}
105
106static void
107_disable_hook(Evas_Object *obj)
108{
109 Widget_Data* wd = elm_widget_data_get(obj);
110 if (!wd) return;
111
112 if (elm_widget_disabled_get(obj))
113 edje_object_signal_emit(wd->base, "elm,state,disabled", "elm");
114 else
115 edje_object_signal_emit(wd->base, "elm,state,enabled", "elm");
116}
117
118static Eina_Bool
119_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir __UNUSED__,
120 Evas_Object **next __UNUSED__)
121{
122 Widget_Data *wd = elm_widget_data_get(obj);
123 if (!wd) return EINA_FALSE;
124
125 /* TODO: Focus switch support to Elm_widget_Item is not supported yet.*/
126 return EINA_FALSE;
127}
128
129static void
130_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
131{
132 Widget_Data *wd = elm_widget_data_get(obj);
133 if (!wd) return;
134
135 edje_object_mirrored_set(wd->base, rtl);
136}
137
138static void
139_translate_hook(Evas_Object *obj)
140{
141 Eina_List *l;
142 Elm_Dayselector_Item *it;
143 struct tm time_daysel;
144 time_t t;
145 char buf[1024];
146 Widget_Data *wd = elm_widget_data_get(obj);
147 if (!wd) return;
148
149 t = time(NULL);
150 localtime_r(&t, &time_daysel);
151 EINA_LIST_FOREACH(wd->items, l, it)
152 {
153 time_daysel.tm_wday = it->day;
154 strftime(buf, sizeof(buf), "%a", &time_daysel);
155 elm_object_text_set(VIEW(it), buf);
156 }
157 evas_object_smart_callback_call(obj, SIG_LANG_CHANGED, NULL);
158}
159
160static void
161_theme_hook(Evas_Object *obj)
162{
163 Eina_List *l;
164 Elm_Dayselector_Item *it;
165 char buf[1024];
166 unsigned int loc;
167 Widget_Data* wd = elm_widget_data_get(obj);
168 if (!wd) return;
169
170 _elm_widget_mirrored_reload(obj);
171 _mirrored_set(obj, elm_widget_mirrored_get(obj));
172 _elm_theme_object_set(obj, wd->base, "dayselector", "base",
173 elm_widget_style_get(obj));
174
175 EINA_LIST_FOREACH(wd->items, l, it)
176 {
177 snprintf(buf, sizeof(buf), "dayselector/%s", elm_object_style_get(obj));
178 elm_object_style_set(VIEW(it), buf);
179 loc = (ELM_DAYSELECTOR_MAX - wd->week_start + it->day) % ELM_DAYSELECTOR_MAX;
180 snprintf(buf, sizeof(buf), "day%d,visible", loc);
181 edje_object_signal_emit(wd->base, buf, "elm");
182 snprintf(buf, sizeof(buf), "day%d", loc);
183 edje_object_part_swallow(wd->base, buf, VIEW(it));
184 }
185 _update_items(obj);
186 _sizing_eval(obj);
187}
188
189static void
190_item_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj,
191 void *event_info __UNUSED__)
192{
193 ELM_CHECK_WIDTYPE(data, widtype);
194 Eina_List *l;
195 Elm_Dayselector_Item *it;
196 char buf[1024];
197 unsigned int loc = 0;
198 Widget_Data *wd = elm_widget_data_get(data);
199 if (!wd) return;
200
201 EINA_LIST_FOREACH(wd->items, l, it)
202 {
203 if (obj == VIEW(it))
204 {
205 wd->items = eina_list_remove(wd->items, it);
206 eina_stringshare_del(it->day_style);
207 evas_object_smart_callback_del(VIEW(it), "changed", _item_clicked_cb);
208 evas_object_event_callback_del(VIEW(it), EVAS_CALLBACK_DEL, _item_del_cb);
209 edje_object_part_unswallow(wd->base, VIEW(it));
210 loc = (ELM_DAYSELECTOR_MAX - wd->week_start + it->day) % ELM_DAYSELECTOR_MAX;
211 snprintf(buf, sizeof(buf), "day%d,default", loc);
212 edje_object_signal_emit(wd->base, buf, "elm");
213 elm_widget_item_free(it);
214 _sizing_eval(obj);
215 break;
216 }
217 }
218}
219
220static void
221_signal_emit_cb(void *data, Evas_Object *obj, const char *emission, const char *source __UNUSED__)
222{
223 Eina_List *l;
224 Elm_Dayselector_Item *it;
225 Widget_Data *wd = elm_widget_data_get(data);
226 if (!wd) return;
227
228 EINA_LIST_FOREACH(wd->items, l, it)
229 {
230 if (obj == VIEW(it))
231 {
232 eina_stringshare_replace(&it->day_style, emission);
233 return ;
234 }
235 }
236}
237
238static void
239_item_text_set_hook(Evas_Object *obj, const char *item, const char *label)
240{
241 ELM_CHECK_WIDTYPE(obj, widtype);
242 Eina_List *l;
243 Elm_Dayselector_Item *it;
244 char buf[1024];
245 Widget_Data *wd = elm_widget_data_get(obj);
246 if (item && !strcmp(item, "default")) return;
247 if (!wd) return;
248
249 EINA_LIST_FOREACH(wd->items, l, it)
250 {
251 snprintf(buf, sizeof(buf), "day%d", it->day);
252 if (!strncmp(buf, item, sizeof(buf)))
253 {
254 elm_object_text_set(VIEW(it), label);
255 _sizing_eval(obj);
256 break;
257 }
258 }
259}
260
261static const char *
262_item_text_get_hook(const Evas_Object *obj, const char *item)
263{
264 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
265 Eina_List *l;
266 Elm_Dayselector_Item *it;
267 char buf[1024];
268 Widget_Data *wd = elm_widget_data_get(obj);
269 if (item && !strcmp(item, "default")) return NULL;
270 if (!wd) return NULL;
271
272 EINA_LIST_FOREACH(wd->items, l, it)
273 {
274 snprintf(buf, sizeof(buf), "day%d", it->day);
275 if (!strncmp(buf, item, sizeof(buf)))
276 return elm_object_text_get(VIEW(it));
277 }
278 return NULL;
279}
280
281static void
282_content_set_hook(Evas_Object *obj, const char *item, Evas_Object *content)
283{
284 ELM_CHECK_WIDTYPE(obj, widtype);
285 Eina_List *l;
286 Elm_Dayselector_Item *it;
287 char buf[1024];
288 unsigned int idx, loc;
289 Widget_Data *wd = elm_widget_data_get(obj);
290 if (!wd || !content) return;
291 if (item && !strcmp(item, "default")) return;
292 if (strcmp(elm_object_widget_type_get(content), "check")) return;
293
294 EINA_LIST_FOREACH(wd->items, l, it)
295 {
296 snprintf(buf, sizeof(buf), "day%d", it->day);
297 if (!strncmp(buf, item, sizeof(buf)))
298 {
299 if (VIEW(it)) evas_object_del(VIEW(it));
300 break;
301 }
302 }
303 for (idx = 0; idx < ELM_DAYSELECTOR_MAX; idx++)
304 {
305 snprintf(buf, sizeof(buf), "day%d", idx);
306 if (!strncmp(buf, item, sizeof(buf)))
307 {
308 it = elm_widget_item_new(obj, Elm_Dayselector_Item);
309 if (!it) continue;
310 VIEW(it) = content;
311 it->day = idx;
312 wd->items = eina_list_append(wd->items, it);
313 elm_widget_sub_object_add(obj, content);
314 loc = (ELM_DAYSELECTOR_MAX - wd->week_start + idx) % ELM_DAYSELECTOR_MAX;
315 snprintf(buf, sizeof(buf), "day%d", loc);
316 edje_object_part_swallow(wd->base, buf, VIEW(it));
317 snprintf(buf, sizeof(buf), "day%d,visible", loc);
318 edje_object_signal_emit(wd->base, buf, "elm");
319 evas_object_smart_callback_add(VIEW(it), "changed", _item_clicked_cb, obj);
320 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_DEL, _item_del_cb, obj);
321 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKDAY_DEFAULT, "", _signal_emit_cb, obj);
322 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKDAY_STYLE1, "", _signal_emit_cb, obj);
323 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKEND_DEFAULT, "", _signal_emit_cb, obj);
324 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKEND_STYLE1, "", _signal_emit_cb, obj);
325 _sizing_eval(obj);
326 _update_items(obj);
327 break;
328 }
329 }
330}
331
332static Evas_Object *
333_content_get_hook(const Evas_Object *obj, const char *item)
334{
335 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
336 Eina_List *l;
337 Elm_Dayselector_Item *it;
338 char buf[1024];
339 Widget_Data *wd = elm_widget_data_get(obj);
340 if (!wd) return NULL;
341 if (item && !strcmp(item, "default")) return NULL;
342
343 EINA_LIST_FOREACH(wd->items, l, it)
344 {
345 snprintf(buf, sizeof(buf), "day%d", it->day);
346 if (!strncmp(buf, item, sizeof(buf))) return VIEW(it);
347 }
348 return NULL;
349}
350
351static Evas_Object *
352_content_unset_hook(Evas_Object *obj, const char *item)
353{
354 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
355 Eina_List *l;
356 Elm_Dayselector_Item *it;
357 Evas_Object *content;
358 char buf[1024];
359 unsigned int loc;
360 Widget_Data *wd = elm_widget_data_get(obj);
361 if (!wd) return NULL;
362 if (item && !strcmp(item, "default")) return NULL;
363
364 EINA_LIST_FOREACH(wd->items, l, it)
365 {
366 snprintf(buf, sizeof(buf), "day%d", it->day);
367 if (!strncmp(buf, item, sizeof(buf)))
368 {
369 content = VIEW(it);
370 wd->items = eina_list_remove(wd->items, it);
371 elm_widget_sub_object_del(obj, VIEW(it));
372 evas_object_smart_callback_del(VIEW(it), "changed", _item_clicked_cb);
373 evas_object_event_callback_del(VIEW(it), EVAS_CALLBACK_DEL, _item_del_cb);
374 edje_object_part_unswallow(wd->base, VIEW(it));
375 loc = (ELM_DAYSELECTOR_MAX - wd->week_start + it->day) % ELM_DAYSELECTOR_MAX;
376 snprintf(buf, sizeof(buf), "day%d,default", loc);
377 edje_object_signal_emit(wd->base, buf, "elm");
378 _sizing_eval(obj);
379 return content;
380 }
381 }
382 return NULL;
383}
384
385static void
386_item_clicked_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
387{
388 Eina_List *l;
389 Elm_Dayselector_Item *it;
390 Widget_Data *wd = elm_widget_data_get(data);
391 if (!wd) return;
392
393 EINA_LIST_FOREACH(wd->items, l, it)
394 {
395 if (obj != VIEW(it)) continue;
396 evas_object_smart_callback_call(data, SIG_CHANGED, (void *)it->day);
397 return;
398 }
399}
400
401static Elm_Dayselector_Item *
402_item_find(const Evas_Object *obj, Elm_Dayselector_Day day)
403{
404 Eina_List *l;
405 Elm_Dayselector_Item *it;
406 Widget_Data* wd = elm_widget_data_get(obj);
407 if (!wd) return NULL;
408
409 EINA_LIST_FOREACH(wd->items, l, it)
410 if (day == it->day) return it;
411
412 return NULL;
413}
414
415static void
416_items_style_set(Evas_Object *obj)
417{
418 ELM_CHECK_WIDTYPE(obj, widtype);
419 Eina_List *l;
420 Elm_Dayselector_Item *it;
421 unsigned int weekend_last;
422 Widget_Data* wd = elm_widget_data_get(obj);
423 if (!wd) return;
424
425 weekend_last = wd->weekend_start + wd->weekend_len - 1;
426 if (weekend_last >= ELM_DAYSELECTOR_MAX)
427 weekend_last = weekend_last % ELM_DAYSELECTOR_MAX;
428
429 EINA_LIST_FOREACH(wd->items, l, it)
430 {
431 if (weekend_last >= wd->weekend_start)
432 {
433 if ((it->day >= wd->weekend_start) && (it->day <= weekend_last))
434 eina_stringshare_replace(&it->day_style,
435 ITEM_TYPE_WEEKEND_DEFAULT);
436 else
437 eina_stringshare_replace(&it->day_style,
438 ITEM_TYPE_WEEKDAY_DEFAULT);
439 }
440 else
441 {
442 if ((it->day >= wd->weekend_start) || (it->day <= weekend_last))
443 eina_stringshare_replace(&it->day_style,
444 ITEM_TYPE_WEEKEND_DEFAULT);
445 else
446 eina_stringshare_replace(&it->day_style,
447 ITEM_TYPE_WEEKDAY_DEFAULT);
448 }
449 }
450}
451
452static void
453_update_items(Evas_Object *obj)
454{
455 Eina_List *l;
456 Elm_Dayselector_Item *it;
457 unsigned int last_day;
458 Eina_Bool rtl;
459 Widget_Data* wd = elm_widget_data_get(obj);
460 if (!wd) return;
461
462 last_day = wd->week_start + ELM_DAYSELECTOR_MAX - 1;
463 if (last_day >= ELM_DAYSELECTOR_MAX)
464 last_day = last_day % ELM_DAYSELECTOR_MAX;
465
466 rtl = elm_widget_mirrored_get(obj);
467 EINA_LIST_FOREACH(wd->items, l, it)
468 {
469 elm_object_signal_emit(VIEW(it), it->day_style, "");
470 if (it->day == wd->week_start)
471 {
472 if (rtl) elm_object_signal_emit(VIEW(it), ITEM_POS_RIGHT, "elm");
473 else elm_object_signal_emit(VIEW(it), ITEM_POS_LEFT, "elm");
474 }
475 else if (it->day == last_day)
476 {
477 if (rtl) elm_object_signal_emit(VIEW(it), ITEM_POS_LEFT, "elm");
478 else elm_object_signal_emit(VIEW(it), ITEM_POS_RIGHT, "elm");
479 }
480 else
481 elm_object_signal_emit(VIEW(it), ITEM_POS_MIDDLE, "elm");
482 }
483}
484
485static void
486_create_items(Evas_Object *obj)
487{
488 Elm_Dayselector_Item *it;
489 struct tm time_daysel;
490 time_t t;
491 char buf[1024];
492 unsigned int idx, loc;
493 Widget_Data* wd = elm_widget_data_get(obj);
494 if (!wd) return;
495
496 t = time(NULL);
497 localtime_r(&t, &time_daysel);
498
499 for (idx = 0; idx < ELM_DAYSELECTOR_MAX; idx++)
500 {
501 it = elm_widget_item_new(obj, Elm_Dayselector_Item);
502 if (!it) continue;
503 VIEW(it) = elm_check_add(wd->base);
504 elm_widget_sub_object_add(obj, VIEW(it));
505 wd->items = eina_list_append(wd->items, it);
506 elm_object_style_set(VIEW(it), "dayselector/default");
507 time_daysel.tm_wday = idx;
508 strftime(buf, sizeof(buf), "%a", &time_daysel);
509 elm_object_text_set(VIEW(it), buf);
510 it->day = idx;
511 loc = (ELM_DAYSELECTOR_MAX - wd->week_start + idx) % ELM_DAYSELECTOR_MAX;
512 snprintf(buf, sizeof(buf), "day%d", loc);
513 edje_object_part_swallow(wd->base, buf, VIEW(it));
514 snprintf(buf, sizeof(buf), "day%d,visible", idx);
515 edje_object_signal_emit(wd->base, buf, "elm");
516 evas_object_smart_callback_add(VIEW(it), "changed", _item_clicked_cb,
517 obj);
518 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_DEL,
519 _item_del_cb, obj);
520 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKDAY_DEFAULT, "",
521 _signal_emit_cb, obj);
522 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKDAY_STYLE1, "",
523 _signal_emit_cb, obj);
524 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKEND_DEFAULT, "",
525 _signal_emit_cb, obj);
526 elm_object_signal_callback_add(VIEW(it), ITEM_TYPE_WEEKEND_STYLE1, "",
527 _signal_emit_cb, obj);
528 }
529 _items_style_set(obj);
530 _update_items(obj);
531}
532
533EAPI Evas_Object *
534elm_dayselector_add(Evas_Object *parent)
535{
536 Evas_Object *obj;
537 Evas *e;
538 Widget_Data *wd;
539
540 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
541
542 ELM_SET_WIDTYPE(widtype, "dayselector");
543 elm_widget_type_set(obj, widtype);
544 elm_widget_sub_object_add(parent, obj);
545 elm_widget_data_set(obj, wd);
546 elm_widget_del_hook_set(obj, _del_hook);
547 elm_widget_theme_hook_set(obj, _theme_hook);
548 elm_widget_disable_hook_set(obj, _disable_hook);
549 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
550 elm_widget_translate_hook_set(obj, _translate_hook);
551 elm_widget_text_set_hook_set(obj, _item_text_set_hook);
552 elm_widget_text_get_hook_set(obj, _item_text_get_hook);
553 elm_widget_content_set_hook_set(obj, _content_set_hook);
554 elm_widget_content_get_hook_set(obj, _content_get_hook);
555 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
556
557 wd->base = edje_object_add(e);
558 _elm_theme_object_set(obj, wd->base, "dayselector", "base", "default");
559 elm_object_style_set(wd->base, "dayselector");
560 elm_widget_resize_object_set(obj, wd->base);
561
562 wd->week_start = _elm_config->week_start;
563 wd->weekend_start = _elm_config->weekend_start;
564 wd->weekend_len = _elm_config->weekend_len;
565 printf("%d %d %d\n", wd->week_start, wd->weekend_start, wd->weekend_len);
566 _create_items(obj);
567
568 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
569 _dayselector_resize, obj);
570 evas_object_smart_callbacks_descriptions_set(obj, _signals);
571 _mirrored_set(obj, elm_widget_mirrored_get(obj));
572 _sizing_eval(obj);
573 return obj;
574}
575
576EAPI void
577elm_dayselector_day_selected_set(Evas_Object *obj, Elm_Dayselector_Day day, Eina_Bool selected)
578{
579 ELM_CHECK_WIDTYPE(obj, widtype);
580 Widget_Data* wd = elm_widget_data_get(obj);
581 if (!wd) return;
582
583 elm_check_state_set(VIEW(_item_find(obj, day)), selected);
584}
585
586EAPI Eina_Bool
587elm_dayselector_day_selected_get(const Evas_Object *obj, Elm_Dayselector_Day day)
588{
589 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
590 Widget_Data* wd = elm_widget_data_get(obj);
591 if (!wd) return EINA_FALSE;
592
593 return elm_check_state_get(VIEW(_item_find(obj, day)));
594}
595
596EAPI void
597elm_dayselector_week_start_set(Evas_Object *obj, Elm_Dayselector_Day day)
598{
599 ELM_CHECK_WIDTYPE(obj, widtype);
600 Eina_List *l;
601 Elm_Dayselector_Item *it;
602 char buf[1024];
603 unsigned int loc;
604 Widget_Data* wd = elm_widget_data_get(obj);
605 if (!wd) return;
606
607 wd->week_start = day;
608 EINA_LIST_FOREACH(wd->items, l, it)
609 {
610 loc = (ELM_DAYSELECTOR_MAX - wd->week_start + it->day) % ELM_DAYSELECTOR_MAX;
611 snprintf(buf, sizeof(buf), "day%d", loc);
612 edje_object_part_swallow(wd->base, buf, VIEW(it));
613 }
614 _update_items(obj);
615}
616
617EAPI Elm_Dayselector_Day
618elm_dayselector_week_start_get(const Evas_Object *obj)
619{
620 ELM_CHECK_WIDTYPE(obj, widtype) ELM_DAYSELECTOR_MAX;
621 Widget_Data* wd = elm_widget_data_get(obj);
622 if (!wd) return ELM_DAYSELECTOR_MAX;
623
624 return wd->week_start;
625}
626
627EAPI void
628elm_dayselector_weekend_start_set(Evas_Object *obj, Elm_Dayselector_Day day)
629{
630 ELM_CHECK_WIDTYPE(obj, widtype);
631 Widget_Data* wd = elm_widget_data_get(obj);
632 if (!wd) return;
633
634 wd->weekend_start = day;
635 _items_style_set(obj);
636 _update_items(obj);
637}
638
639EAPI Elm_Dayselector_Day
640elm_dayselector_weekend_start_get(const Evas_Object *obj)
641{
642 ELM_CHECK_WIDTYPE(obj, widtype) ELM_DAYSELECTOR_MAX;
643 Widget_Data* wd = elm_widget_data_get(obj);
644 if (!wd) return ELM_DAYSELECTOR_MAX;
645
646 return wd->weekend_start;
647}
648
649EAPI void
650elm_dayselector_weekend_length_set(Evas_Object *obj, unsigned int length)
651{
652 ELM_CHECK_WIDTYPE(obj, widtype);
653 Widget_Data* wd = elm_widget_data_get(obj);
654 if (!wd) return;
655
656 wd->weekend_len = length;
657 _items_style_set(obj);
658 _update_items(obj);
659}
660
661EAPI unsigned int
662elm_dayselector_weekend_length_get(const Evas_Object *obj)
663{
664 ELM_CHECK_WIDTYPE(obj, widtype) 0;
665 Widget_Data* wd = elm_widget_data_get(obj);
666 if (!wd) return 0;
667
668 return wd->weekend_len;
669}
diff --git a/libraries/elementary/src/lib/elc_dayselector.h b/libraries/elementary/src/lib/elc_dayselector.h
new file mode 100644
index 0000000..6b1497d
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_dayselector.h
@@ -0,0 +1,207 @@
1/**
2 * @defgroup Dayselector Dayselector
3 * @ingroup Elementary
4 *
5 * @image html img/widget/dayselector/preview-00.png
6 * @image latex img/widget/dayselector/preview-00.eps
7 *
8 * @brief <b>Dayselector widget:</b>
9 *
10 *"elm_dayselector" is a day selection widget. It displays all seven days of
11 * the week and allows the user to select multiple days.
12 *
13 * The selection can be toggle by just clicking on the day.
14 *
15 * Dayselector also provides the functionality to check whether a day is
16 * selected or not.
17 *
18 * First day of the week is taken from config settings by default. It can be
19 * altered by using the API elm_dayselector_week_start_set() API.
20 *
21 * APIs are provided for setting the duration of weekend
22 * elm_dayselector_weekend_start_set() and elm_dayselector_weekend_length_set()
23 * does this job.
24 *
25 * Two styles of weekdays and weekends are supported in Dayselector.
26 * Application can emit signals on individual check objects for setting the
27 * weekday, weekend styles.
28 *
29 * Once the weekend start day or weekend length changes, all the weekday &
30 * weekend styles will be reset to default style. It's the application's
31 * responsibility to set the styles again by sending corresponding signals.
32 *
33 * Supported elm_object_item common APIs.
34 *
35 * @li @ref elm_object_part_text_set,
36 * @li @ref elm_object_part_text_get,
37 * @li @ref elm_object_part_content_set,
38 * @li @ref elm_object_part_content_get,
39 * @li @ref elm_object_part_content_unset
40 *
41 * @li "day0" indicates Sunday, "day1" indicates Monday etc. continues and so,
42 * "day6" indicates the Saturday part name.
43 *
44 * Application can change individual day display string by using the API
45 * elm_object_part_text_set().
46 *
47 * elm_object_part_content_set() API sets the individual day object only if
48 * the passed one is a Check widget.
49 *
50 * Check object representing a day can be set/get by the application by using
51 * the elm_object_part_content_set/get APIs thus providing a way to handle
52 * the different check styles for individual days.
53 *
54 * The widget emits the following signals:
55 * @li "dayselector,changed" - when the user changes the state of a day.
56 * @li "language,changed" - the program's language changed
57 *
58 * Available styles for dayselector are:
59 * @li default
60 *
61 * This example shows the usage of the widget.
62 * @li @ref dayselector_example
63 *
64 */
65
66/**
67 * @addtogroup Dayselector
68 * @{
69 */
70
71/**
72 * Identifies the day of the week.
73 * API can call the selection/unselection of day with this as a parameter.
74 *
75 * @see elm_dayselector_day_selected_set()
76 * @see elm_dayselector_day_selected_get()
77 */
78typedef enum
79{
80 ELM_DAYSELECTOR_SUN = 0,/**< indicates Sunday */
81 ELM_DAYSELECTOR_MON, /**< indicates Monday */
82 ELM_DAYSELECTOR_TUE, /**< indicates Tuesday */
83 ELM_DAYSELECTOR_WED, /**< indicates Wednesday */
84 ELM_DAYSELECTOR_THU, /**< indicates Thursday */
85 ELM_DAYSELECTOR_FRI, /**< indicates Friday */
86 ELM_DAYSELECTOR_SAT, /**< indicates Saturday */
87 ELM_DAYSELECTOR_MAX /**< Sentinel value, @b don't use */
88} Elm_Dayselector_Day;
89
90/**
91 * Add the dayselector.
92 *
93 * @param parent Parent object
94 * @return New dayselector object or @c NULL, if it cannot be created
95 *
96 * @ingroup Dayselector
97 */
98EAPI Evas_Object *elm_dayselector_add(Evas_Object *parent);
99
100/**
101 * Set the state of given Dayselector_Day.
102 *
103 * @param obj Dayselector object
104 * @param day Dayselector_Day that the user want to set state.
105 * @param selected state of the day. @c EINA_TRUE is selected.
106 *
107 * @see Elm_Dayselector_Day
108 * @see elm_dayselector_day_selected_get()
109 *
110 * @ingroup Dayselector
111 */
112EAPI void elm_dayselector_day_selected_set(Evas_Object *obj, Elm_Dayselector_Day day, Eina_Bool selected);
113
114/**
115 * Get the state of given Dayselector_Day.
116 *
117 * @param obj Dayselector object
118 * @param day Dayselector_Day that the user want to know state.
119 * @return @c EINA_TRUE, if the Day is selected
120 *
121 * @see Elm_Dayselector_Day
122 * @see elm_dayselector_day_selected_set()
123 *
124 * @ingroup Dayselector
125 */
126EAPI Eina_Bool elm_dayselector_day_selected_get(const Evas_Object *obj, Elm_Dayselector_Day day);
127
128/**
129 * Set the starting day of Dayselector.
130 *
131 * @param obj Dayselector object
132 * @param day Dayselector_Day the first day that the user wants to display.
133 *
134 * @see Elm_Dayselector_Day
135 * @see elm_dayselector_week_start_get()
136 *
137 * @ingroup Dayselector
138 */
139EAPI void elm_dayselector_week_start_set(Evas_Object *obj, Elm_Dayselector_Day day);
140
141/**
142 * Get the starting day of Dayselector.
143 *
144 * @param obj Dayselector object
145 * @return Day from where Dayselector displays all the weekdays in order.
146 *
147 * @see Elm_Dayselector_Day
148 * @see elm_dayselector_week_start_set()
149 *
150 * @ingroup Dayselector
151 */
152EAPI Elm_Dayselector_Day elm_dayselector_week_start_get(const Evas_Object *obj);
153
154/**
155 * Set the weekend starting day of Dayselector.
156 *
157 * @param obj Dayselector object
158 * @param day Dayselector_Day the first day from where weekend starts.
159 *
160 * @see Elm_Dayselector_Day
161 * @see elm_dayselector_weekend_start_get()
162 *
163 * @ingroup Dayselector
164 */
165EAPI void elm_dayselector_weekend_start_set(Evas_Object *obj, Elm_Dayselector_Day day);
166
167/**
168 * Get the weekend starting day of Dayselector.
169 *
170 * @param obj Dayselector object
171 * @return Elm_Dayselector_Day Day from where weekend starts.
172 *
173 * @see Elm_Dayselector_Day
174 * @see elm_dayselector_weekend_start_set()
175 *
176 * @ingroup Dayselector
177 */
178EAPI Elm_Dayselector_Day elm_dayselector_weekend_start_get(const Evas_Object *obj);
179
180/**
181 * Set the weekend length of Dayselector.
182 *
183 * @param obj Dayselector object
184 * @param length Weekend length, number of days as an integer.
185 *
186 * @see elm_dayselector_weekend_length_get()
187 *
188 * @ingroup Dayselector
189 */
190EAPI void elm_dayselector_weekend_length_set(Evas_Object *obj, unsigned int length);
191
192/**
193 * Get the weekend length of Dayselector.
194 *
195 * @param obj Dayselector object
196 * @return Number of days marked as a weekend.
197 *
198 * @see Elm_Dayselector_Day
199 * @see elm_dayselector_weekend_length_set()
200 *
201 * @ingroup Dayselector
202 */
203EAPI unsigned int elm_dayselector_weekend_length_get(const Evas_Object *obj);
204
205/**
206 * @}
207 */
diff --git a/libraries/elementary/src/lib/elc_fileselector.c b/libraries/elementary/src/lib/elc_fileselector.c
new file mode 100644
index 0000000..148c73d
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_fileselector.c
@@ -0,0 +1,1249 @@
1/*
2 * TODO:
3 * - child elements focusing support
4 * - user defined icon/label cb
5 * - show/hide/add buttons ???
6 * - show/hide hidden files
7 * - double click to choose a file
8 * - multi-selection
9 * - make variable/function names that are sensible
10 * - Filter support
11 */
12
13#ifdef HAVE_CONFIG_H
14# include "elementary_config.h"
15#endif
16
17#ifdef HAVE_EIO
18# include <Eio.h>
19#endif
20
21#include <Elementary.h>
22#include "elm_priv.h"
23
24typedef struct _Widget_Data Widget_Data;
25
26struct _Widget_Data
27{
28 EINA_REFCOUNT;
29
30 Evas_Object *edje;
31 Evas_Object *filename_entry;
32 Evas_Object *path_entry;
33 Evas_Object *files_list;
34 Evas_Object *files_grid;
35 Evas_Object *up_button;
36 Evas_Object *home_button;
37
38 Evas_Object *ok_button;
39 Evas_Object *cancel_button;
40
41 const char *path;
42 const char *selection;
43 Ecore_Idler *sel_idler;
44
45 const char *path_separator;
46
47#ifdef HAVE_EIO
48 Eio_File *current;
49#endif
50
51 Elm_Fileselector_Mode mode;
52
53 Eina_Bool only_folder : 1;
54 Eina_Bool expand : 1;
55};
56
57struct sel_data
58{
59 Evas_Object *fs;
60 const char *path;
61};
62
63typedef struct _Widget_Request Widget_Request;
64struct _Widget_Request
65{
66 Widget_Data *wd;
67 Elm_Object_Item *parent;
68
69 Evas_Object *obj;
70 const char *path;
71 Eina_Bool first : 1;
72};
73
74typedef enum {
75 ELM_DIRECTORY = 0,
76 ELM_FILE_IMAGE = 1,
77 ELM_FILE_UNKNOW = 2,
78 ELM_FILE_LAST
79} Elm_Fileselector_Type;
80
81static Elm_Genlist_Item_Class *list_itc[ELM_FILE_LAST];
82static Elm_Gengrid_Item_Class *grid_itc[ELM_FILE_LAST];
83
84static const char *widtype = NULL;
85
86static const char SIG_DIRECTORY_OPEN[] = "directory,open";
87static const char SIG_DONE[] = "done";
88static const char SIG_SELECTED[] = "selected";
89static const Evas_Smart_Cb_Description _signals[] = {
90 {SIG_DIRECTORY_OPEN, "s"},
91 {SIG_DONE, "s"},
92 {SIG_SELECTED, "s"},
93 {NULL, NULL}
94};
95
96static void _populate(Evas_Object *obj,
97 const char *path,
98 Elm_Object_Item *parent);
99static void _do_anchors(Evas_Object *obj,
100 const char *path);
101
102/*** ELEMENTARY WIDGET ***/
103static void
104_widget_data_free(Widget_Data *wd)
105{
106 if (wd->path) eina_stringshare_del(wd->path);
107 if (wd->selection) eina_stringshare_del(wd->selection);
108 if (wd->sel_idler)
109 {
110 void *sd;
111
112 sd = ecore_idler_del(wd->sel_idler);
113 free(sd);
114 }
115 free(wd);
116}
117
118static void
119_del_hook(Evas_Object *obj)
120{
121 Widget_Data *wd;
122 int i;
123
124 wd = elm_widget_data_get(obj);
125 if (!wd) return;
126
127 for (i = 0; i < ELM_FILE_LAST; ++i)
128 {
129 elm_genlist_item_class_free(list_itc[i]);
130 elm_gengrid_item_class_free(grid_itc[i]);
131 }
132
133#ifdef HAVE_EIO
134 if (wd->current)
135 eio_file_cancel(wd->current);
136#endif
137
138 wd->files_list = NULL;
139 wd->files_grid = NULL;
140
141 EINA_REFCOUNT_UNREF(wd)
142 _widget_data_free(wd);
143}
144
145static void
146_sizing_eval(Evas_Object *obj)
147{
148 Widget_Data *wd = elm_widget_data_get(obj);
149 Evas_Coord minw = -1, minh = -1;
150 if (!wd) return;
151 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
152 edje_object_size_min_restricted_calc(wd->edje, &minw, &minh, minw, minh);
153 evas_object_size_hint_min_set(obj, minw, minh);
154}
155
156static void
157_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
158{
159 Widget_Data *wd = elm_widget_data_get(obj);
160 if (!wd) return;
161 elm_widget_mirrored_set(wd->cancel_button, rtl);
162 elm_widget_mirrored_set(wd->ok_button, rtl);
163 elm_widget_mirrored_set(wd->files_list, rtl);
164 elm_widget_mirrored_set(wd->up_button, rtl);
165 elm_widget_mirrored_set(wd->home_button, rtl);
166 edje_object_mirrored_set(wd->edje, rtl);
167}
168
169static void
170_theme_hook(Evas_Object *obj)
171{
172 Widget_Data *wd = elm_widget_data_get(obj);
173 const char *style = elm_widget_style_get(obj);
174 const char *data;
175 char buf[1024];
176
177 if (!wd) return;
178 _elm_widget_mirrored_reload(obj);
179
180 _elm_theme_object_set(obj, wd->edje, "fileselector", "base", style);
181
182 if (elm_object_disabled_get(obj))
183 edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm");
184
185 data = edje_object_data_get(wd->edje, "path_separator");
186 if (data)
187 wd->path_separator = data;
188 else
189 wd->path_separator = "/";
190
191 if (!style) style = "default";
192 snprintf(buf, sizeof(buf), "fileselector/%s", style);
193
194#define SWALLOW(part_name, object_ptn) \
195 if (object_ptn) \
196 { \
197 elm_widget_style_set(object_ptn, buf); \
198 if (edje_object_part_swallow(wd->edje, part_name, object_ptn)) \
199 evas_object_show(object_ptn); \
200 else \
201 evas_object_hide(object_ptn); \
202 }
203 SWALLOW("elm.swallow.up", wd->up_button);
204 SWALLOW("elm.swallow.home", wd->home_button);
205
206 if (wd->mode == ELM_FILESELECTOR_LIST)
207 {
208 if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
209 wd->files_list))
210 {
211 evas_object_show(wd->files_list);
212 evas_object_hide(wd->files_grid);
213 }
214 else
215 evas_object_hide(wd->files_list);
216 }
217 else
218 {
219 if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
220 wd->files_grid))
221 {
222 evas_object_show(wd->files_grid);
223 evas_object_hide(wd->files_list);
224 }
225 else
226 evas_object_hide(wd->files_grid);
227 }
228
229 SWALLOW("elm.swallow.filename", wd->filename_entry);
230 SWALLOW("elm.swallow.path", wd->path_entry);
231
232 snprintf(buf, sizeof(buf), "fileselector/actions/%s", style);
233 SWALLOW("elm.swallow.cancel", wd->cancel_button);
234 SWALLOW("elm.swallow.ok", wd->ok_button);
235#undef SWALLOW
236
237 edje_object_message_signal_process(wd->edje);
238 _mirrored_set(obj, elm_widget_mirrored_get(obj));
239 edje_object_scale_set
240 (wd->edje, elm_widget_scale_get(obj) * _elm_config->scale);
241 _sizing_eval(obj);
242}
243
244/*** GENLIST "MODEL" ***/
245static char *
246_itc_text_get(void *data,
247 Evas_Object *obj __UNUSED__,
248 const char *source __UNUSED__)
249{
250 return elm_entry_utf8_to_markup(ecore_file_file_get(data)); /* NOTE this will be
251 * free() by the
252 * caller */
253}
254
255static Evas_Object *
256_itc_icon_folder_get(void *data __UNUSED__,
257 Evas_Object *obj,
258 const char *source)
259{
260 Evas_Object *ic;
261
262 if (strcmp(source, "elm.swallow.icon")) return NULL;
263
264 ic = elm_icon_add(obj);
265 elm_icon_standard_set(ic, "folder");
266
267 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL,
268 1, 1);
269 return ic;
270}
271
272static Evas_Object *
273_itc_icon_image_get(void *data,
274 Evas_Object *obj,
275 const char *source)
276{
277 const char *filename = data;
278 Evas_Object *ic;
279
280 if (strcmp(source, "elm.swallow.icon")) return NULL;
281
282 ic = elm_icon_add(obj);
283 elm_icon_standard_set(ic, "image");
284 elm_icon_thumb_set(ic, filename, NULL);
285
286 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL,
287 1, 1);
288 return ic;
289}
290
291static Evas_Object *
292_itc_icon_file_get(void *data __UNUSED__,
293 Evas_Object *obj,
294 const char *source)
295{
296 Evas_Object *ic;
297
298 if (strcmp(source, "elm.swallow.icon")) return NULL;
299
300 ic = elm_icon_add(obj);
301 elm_icon_standard_set(ic, "file");
302
303 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL,
304 1, 1);
305 return ic;
306}
307
308static Eina_Bool
309_itc_state_get(void *data __UNUSED__,
310 Evas_Object *obj __UNUSED__,
311 const char *source __UNUSED__)
312{
313 return EINA_FALSE;
314}
315
316static void
317_itc_del(void *data,
318 Evas_Object *obj __UNUSED__)
319{
320 eina_stringshare_del(data);
321}
322
323static void
324_expand_done(void *data,
325 Evas_Object *obj __UNUSED__,
326 void *event_info)
327{
328 Elm_Object_Item *it = event_info;
329 const char *path = elm_object_item_data_get(it);
330 _populate(data, path, it);
331}
332
333static void
334_contract_done(void *data __UNUSED__,
335 Evas_Object *obj __UNUSED__,
336 void *event_info)
337{
338 Elm_Object_Item *it = event_info;
339 elm_genlist_item_subitems_clear(it);
340}
341
342static void
343_expand_req(void *data __UNUSED__,
344 Evas_Object *obj __UNUSED__,
345 void *event_info)
346{
347 Elm_Object_Item *it = event_info;
348 elm_genlist_item_expanded_set(it, EINA_TRUE);
349}
350
351static void
352_contract_req(void *data __UNUSED__,
353 Evas_Object *obj __UNUSED__,
354 void *event_info)
355{
356 Elm_Object_Item *it = event_info;
357 elm_genlist_item_expanded_set(it, EINA_FALSE);
358}
359
360/*** PRIVATES ***/
361static Eina_Bool
362_sel_do(void *data)
363{
364 struct sel_data *sd;
365 const char *path;
366 Widget_Data *wd;
367 const char *p;
368
369 sd = data;
370 wd = elm_widget_data_get(sd->fs);
371 path = sd->path;
372
373 if ((!wd->only_folder) && ecore_file_is_dir(path))
374 {
375 if (wd->expand && wd->mode == ELM_FILESELECTOR_LIST)
376 {
377 _do_anchors(sd->fs, path);
378 elm_object_text_set(wd->filename_entry, "");
379 }
380 else
381 {
382 /* keep a ref to path 'couse it will be destroyed by _populate */
383 p = eina_stringshare_add(path);
384 _populate(sd->fs, p, NULL);
385 eina_stringshare_del(p);
386 }
387 goto end;
388 }
389 else /* navigating through folders only or file is not a dir. */
390 {
391 char *s;
392
393 if (wd->expand && wd->mode == ELM_FILESELECTOR_LIST)
394 _do_anchors(sd->fs, path);
395 else if (wd->only_folder)
396 {
397 /* keep a ref to path 'couse it will be destroyed by _populate */
398 p = eina_stringshare_add(path);
399 _populate(sd->fs, p, NULL);
400 eina_stringshare_del(p);
401 }
402 s = elm_entry_utf8_to_markup(ecore_file_file_get(path));
403 if (s)
404 {
405 elm_object_text_set(wd->filename_entry, s);
406 free(s);
407 }
408 else
409 elm_object_text_set(wd->filename_entry, "");
410 }
411
412 evas_object_smart_callback_call(sd->fs, SIG_SELECTED, (void *)path);
413
414end:
415 wd->sel_idler = NULL;
416 free(sd);
417 return ECORE_CALLBACK_CANCEL;
418}
419
420static void
421_sel(void *data,
422 Evas_Object *obj __UNUSED__,
423 void *event_info)
424{
425 struct sel_data *sd;
426 Widget_Data *wd;
427 void *old_sd;
428 char *dir;
429 //This event_info could be a list or gengrid item
430 Elm_Object_Item *it = event_info;
431
432 wd = elm_widget_data_get(data);
433 if (!wd) return;
434
435 sd = malloc(sizeof(*sd));
436 sd->fs = data;
437 sd->path = elm_object_item_data_get(it);
438
439 if (!sd->path)
440 {
441 eina_stringshare_replace(&wd->path, "");
442 goto end;
443 }
444
445 dir = wd->only_folder ? strdup(sd->path) : ecore_file_dir_get(sd->path);
446 if (dir)
447 {
448 eina_stringshare_replace(&wd->path, dir);
449 free(dir);
450 }
451 else
452 {
453 eina_stringshare_replace(&wd->path, "");
454 }
455
456end:
457 if (wd->sel_idler)
458 {
459 old_sd = ecore_idler_del(wd->sel_idler);
460 free(old_sd);
461 }
462 wd->sel_idler = ecore_idler_add(_sel_do, sd);
463}
464
465static void
466_up(void *data,
467 Evas_Object *obj __UNUSED__,
468 void *event_info __UNUSED__)
469{
470 Evas_Object *fs = data;
471 char *parent;
472
473 Widget_Data *wd = elm_widget_data_get(fs);
474 if (!wd) return;
475 parent = ecore_file_dir_get(wd->path);
476 _populate(fs, parent, NULL);
477 free(parent);
478}
479
480static void
481_home(void *data,
482 Evas_Object *obj __UNUSED__,
483 void *event_info __UNUSED__)
484{
485 Evas_Object *fs = data;
486 _populate(fs, getenv("HOME"), NULL);
487}
488
489static void
490_ok(void *data,
491 Evas_Object *obj __UNUSED__,
492 void *event_info __UNUSED__)
493{
494 Evas_Object *fs = data;
495 evas_object_smart_callback_call(fs, SIG_DONE,
496 (void *)elm_fileselector_selected_get(fs));
497}
498
499static void
500_canc(void *data,
501 Evas_Object *obj __UNUSED__,
502 void *event_info __UNUSED__)
503{
504 Evas_Object *fs = data;
505 evas_object_smart_callback_call(fs, SIG_DONE, NULL);
506}
507
508static void
509_anchor_clicked(void *data,
510 Evas_Object *obj __UNUSED__,
511 void *event_info)
512{
513 Evas_Object *fs = data;
514 Widget_Data *wd = elm_widget_data_get(fs);
515 Elm_Entry_Anchor_Info *info = event_info;
516 const char *p;
517 if (!wd) return;
518 // keep a ref to path 'couse it will be destroyed by _populate
519 p = eina_stringshare_add(info->name);
520 _populate(fs, p, NULL);
521 evas_object_smart_callback_call(data, SIG_SELECTED, (void *)p);
522 eina_stringshare_del(p);
523}
524
525static void
526_do_anchors(Evas_Object *obj,
527 const char *path)
528{
529 Widget_Data *wd = elm_widget_data_get(obj);
530 char **tok, buf[PATH_MAX * 3], *s;
531 int i, j;
532
533 if (!wd) return;
534 s = elm_entry_utf8_to_markup(path);
535 if (!s) return;
536 buf[0] = '\0';
537 tok = eina_str_split(s, "/", 0);
538 free(s);
539 eina_strlcat(buf, "<a href=/>root</a>", sizeof(buf));
540 for (i = 0; tok[i]; i++)
541 {
542 if ((!tok[i]) || (!tok[i][0])) continue;
543 eina_strlcat(buf, wd->path_separator, sizeof(buf));
544 eina_strlcat(buf, "<a href=", sizeof(buf));
545 for (j = 0; j <= i; j++)
546 {
547 if (strlen(tok[j]) < 1) continue;
548 eina_strlcat(buf, "/", sizeof(buf));
549 eina_strlcat(buf, tok[j], sizeof(buf));
550 }
551 eina_strlcat(buf, ">", sizeof(buf));
552 eina_strlcat(buf, tok[i], sizeof(buf));
553 eina_strlcat(buf, "</a>", sizeof(buf));
554 }
555 free(tok[0]);
556 free(tok);
557
558 elm_object_text_set(wd->path_entry, buf);
559}
560
561#ifdef HAVE_EIO
562static Eina_Bool
563_filter_cb(void *data __UNUSED__, Eio_File *handler, const Eina_File_Direct_Info *info)
564{
565 const char *filename;
566
567 if (info->path[info->name_start] == '.')
568 return EINA_FALSE;
569
570 filename = eina_stringshare_add(info->path);
571 eio_file_associate_direct_add(handler, "filename", filename, EINA_FREE_CB(eina_stringshare_del));
572
573 if (info->type == EINA_FILE_DIR)
574 {
575 eio_file_associate_direct_add(handler, "type/grid", grid_itc[ELM_DIRECTORY], NULL);
576 eio_file_associate_direct_add(handler, "type/list", list_itc[ELM_DIRECTORY], NULL);
577 }
578 else
579 {
580 if (evas_object_image_extension_can_load_get(info->path + info->name_start))
581 {
582 eio_file_associate_direct_add(handler, "type/grid", grid_itc[ELM_FILE_IMAGE], NULL);
583 eio_file_associate_direct_add(handler, "type/list", list_itc[ELM_FILE_IMAGE], NULL);
584 }
585 else
586 {
587 eio_file_associate_direct_add(handler, "type/grid", grid_itc[ELM_FILE_UNKNOW], NULL);
588 eio_file_associate_direct_add(handler, "type/list", list_itc[ELM_FILE_UNKNOW], NULL);
589 }
590 }
591
592 return EINA_TRUE;
593}
594
595static int
596_file_grid_cmp(const void *a, const void *b)
597{
598 const Elm_Object_Item *ga = a;
599 const Elm_Object_Item *gb = b;
600 const Elm_Gengrid_Item_Class *ca = elm_gengrid_item_item_class_get(ga);
601 const Elm_Gengrid_Item_Class *cb = elm_gengrid_item_item_class_get(gb);
602
603 if (ca == grid_itc[ELM_DIRECTORY])
604 {
605 if (cb != grid_itc[ELM_DIRECTORY])
606 return -1;
607 }
608 else if (cb == grid_itc[ELM_DIRECTORY])
609 {
610 return 1;
611 }
612
613 return strcoll(elm_object_item_data_get(ga), elm_object_item_data_get(gb));
614}
615
616static int
617_file_list_cmp(const void *a, const void *b)
618{
619 const Elm_Object_Item *la = a;
620 const Elm_Object_Item *lb = b;
621 const Elm_Genlist_Item_Class *ca = elm_genlist_item_item_class_get(la);
622 const Elm_Genlist_Item_Class *cb = elm_genlist_item_item_class_get(lb);
623
624 if (ca == list_itc[ELM_DIRECTORY])
625 {
626 if (cb != list_itc[ELM_DIRECTORY])
627 return -1;
628 }
629 else if (cb == list_itc[ELM_DIRECTORY])
630 {
631 return 1;
632 }
633
634 return strcoll(elm_object_item_data_get(la), elm_object_item_data_get(lb));
635}
636
637static void
638_signal_first(Widget_Request *wr)
639{
640 if (!wr->first) return ;
641 evas_object_smart_callback_call(wr->obj, SIG_DIRECTORY_OPEN, (void *)wr->path);
642 if (!wr->parent)
643 {
644 elm_genlist_clear(wr->wd->files_list);
645 elm_gengrid_clear(wr->wd->files_grid);
646 eina_stringshare_replace(&wr->wd->path, wr->path);
647 _do_anchors(wr->obj, wr->path);
648 }
649
650 if (wr->wd->filename_entry) elm_object_text_set(wr->wd->filename_entry, "");
651
652 wr->first = EINA_FALSE;
653}
654
655static void
656_main_cb(void *data, Eio_File *handler, const Eina_File_Direct_Info *info __UNUSED__)
657{
658 Widget_Request *wr = data;
659
660 if (eio_file_check(handler))
661 return ;
662 if (!wr->wd->files_list || !wr->wd->files_grid || wr->wd->current != handler)
663 {
664 eio_file_cancel(handler);
665 return ;
666 }
667
668 _signal_first(wr);
669
670 if (wr->wd->mode == ELM_FILESELECTOR_LIST)
671 {
672 Eina_Bool is_dir = (eio_file_associate_find(handler, "type/list") == list_itc[ELM_DIRECTORY]);
673
674 elm_genlist_item_sorted_insert(wr->wd->files_list, eio_file_associate_find(handler, "type/list"),
675 eina_stringshare_ref(eio_file_associate_find(handler, "filename")),
676 wr->parent, wr->wd->expand && is_dir ? ELM_GENLIST_ITEM_TREE : ELM_GENLIST_ITEM_NONE,
677 _file_list_cmp, NULL, NULL);
678 }
679 else if (wr->wd->mode == ELM_FILESELECTOR_GRID)
680 elm_gengrid_item_sorted_insert(wr->wd->files_grid, eio_file_associate_find(handler, "type/grid"),
681 eina_stringshare_ref(eio_file_associate_find(handler, "filename")),
682 _file_grid_cmp, NULL, NULL);
683}
684
685static void
686_widget_request_cleanup(Widget_Request *wr)
687{
688 EINA_REFCOUNT_UNREF(wr->wd)
689 _widget_data_free(wr->wd);
690
691 eina_stringshare_del(wr->path);
692 free(wr);
693}
694
695static void
696_done_cb(void *data, Eio_File *handler __UNUSED__)
697{
698 Widget_Request *wr = data;
699
700 _signal_first(wr);
701
702 wr->wd->current = NULL;
703 _widget_request_cleanup(wr);
704}
705
706static void
707_error_cb(void *data, Eio_File *handler, int error __UNUSED__)
708{
709 Widget_Request *wr = data;
710
711 if (wr->wd->current == handler)
712 wr->wd->current = NULL;
713 _widget_request_cleanup(wr);
714}
715
716#endif
717
718static void
719_populate(Evas_Object *obj,
720 const char *path,
721 Elm_Object_Item *parent)
722{
723 Widget_Data *wd = elm_widget_data_get(obj);
724#ifdef HAVE_EIO
725 Widget_Request *wr;
726#else
727 Eina_File_Direct_Info *file;
728 Eina_Iterator *it;
729 const char *real;
730 Eina_List *files = NULL, *dirs = NULL;
731#endif
732
733 if (!wd) return;
734#ifndef HAVE_EIO
735 if (!ecore_file_is_dir(path)) return ;
736 it = eina_file_stat_ls(path);
737 if (!it) return ;
738 evas_object_smart_callback_call(obj, SIG_DIRECTORY_OPEN, (void *)path);
739 if (!parent)
740 {
741 elm_genlist_clear(wd->files_list);
742 elm_gengrid_clear(wd->files_grid);
743 eina_stringshare_replace(&wd->path, path);
744 _do_anchors(obj, path);
745 }
746
747 if (wd->filename_entry) elm_object_text_set(wd->filename_entry, "");
748 EINA_ITERATOR_FOREACH(it, file)
749 {
750 const char *filename;
751
752 if (file->path[file->name_start] == '.')
753 continue ;
754
755 filename = eina_stringshare_add(file->path);
756 if (file->type == EINA_FILE_DIR)
757 dirs = eina_list_append(dirs, filename);
758 else if (!wd->only_folder)
759 files = eina_list_append(files, filename);
760 }
761 eina_iterator_free(it);
762
763 files = eina_list_sort(files, eina_list_count(files),
764 EINA_COMPARE_CB(strcoll));
765 dirs = eina_list_sort(dirs, eina_list_count(dirs), EINA_COMPARE_CB(strcoll));
766 EINA_LIST_FREE(dirs, real)
767 {
768 if (wd->mode == ELM_FILESELECTOR_LIST)
769 elm_genlist_item_append(wd->files_list, list_itc[ELM_DIRECTORY],
770 real, /* item data */
771 parent,
772 wd->expand ? ELM_GENLIST_ITEM_TREE :
773 ELM_GENLIST_ITEM_NONE,
774 NULL, NULL);
775 else if (wd->mode == ELM_FILESELECTOR_GRID)
776 elm_gengrid_item_append(wd->files_grid, grid_itc[ELM_DIRECTORY],
777 real, /* item data */
778 NULL, NULL);
779 }
780
781 EINA_LIST_FREE(files, real)
782 {
783 Elm_Fileselector_Type type = evas_object_image_extension_can_load_fast_get(real) ?
784 ELM_FILE_IMAGE : ELM_FILE_UNKNOW;
785
786 if (wd->mode == ELM_FILESELECTOR_LIST)
787 elm_genlist_item_append(wd->files_list, list_itc[type],
788 real, /* item data */
789 parent, ELM_GENLIST_ITEM_NONE,
790 NULL, NULL);
791 else if (wd->mode == ELM_FILESELECTOR_GRID)
792 elm_gengrid_item_append(wd->files_grid, grid_itc[type],
793 real, /* item data */
794 NULL, NULL);
795 }
796#else
797 if (wd->expand && wd->current) return ;
798 if (wd->current)
799 eio_file_cancel(wd->current);
800 wr = malloc(sizeof (Widget_Request));
801 if (!wr) return ;
802 wr->wd = wd;
803 EINA_REFCOUNT_REF(wr->wd);
804 wr->parent = parent; /* FIXME: should we refcount the parent ? */
805 wr->obj = obj;
806 wr->path = eina_stringshare_add(path);
807 wr->first = EINA_TRUE;
808
809 wd->current = eio_file_stat_ls(path,
810 _filter_cb,
811 _main_cb,
812 _done_cb,
813 _error_cb,
814 wr);
815#endif
816}
817
818/*** API ***/
819
820EAPI Evas_Object *
821elm_fileselector_add(Evas_Object *parent)
822{
823 Evas *e;
824 Evas_Object *obj, *ic, *bt, *li, *en, *grid;
825 Widget_Data *wd;
826 unsigned int i;
827 int s;
828
829 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
830
831 EINA_REFCOUNT_INIT(wd);
832
833 ELM_SET_WIDTYPE(widtype, "fileselector");
834 elm_widget_type_set(obj, "fileselector");
835 elm_widget_sub_object_add(parent, obj);
836 elm_widget_data_set(obj, wd);
837 elm_widget_del_hook_set(obj, _del_hook);
838 elm_widget_theme_hook_set(obj, _theme_hook);
839 elm_widget_can_focus_set(obj, EINA_FALSE);
840
841 wd->expand = !!_elm_config->fileselector_expand_enable;
842
843 wd->edje = edje_object_add(e);
844 _elm_theme_object_set(obj, wd->edje, "fileselector", "base", "default");
845 elm_widget_resize_object_set(obj, wd->edje);
846
847 // up btn
848 ic = elm_icon_add(parent);
849 elm_icon_standard_set(ic, "arrow_up");
850 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
851 bt = elm_button_add(parent);
852 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
853 elm_object_part_content_set(bt, "icon", ic);
854 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Up"));
855 evas_object_size_hint_align_set(bt, 0.0, 0.0);
856
857 evas_object_smart_callback_add(bt, "clicked", _up, obj);
858
859 elm_widget_sub_object_add(obj, bt);
860 wd->up_button = bt;
861
862 // home btn
863 ic = elm_icon_add(parent);
864 elm_icon_standard_set(ic, "home");
865 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
866 bt = elm_button_add(parent);
867 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
868 elm_object_part_content_set(bt, "icon", ic);
869 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Home"));
870 evas_object_size_hint_align_set(bt, 0.0, 0.0);
871
872 evas_object_smart_callback_add(bt, "clicked", _home, obj);
873
874 elm_widget_sub_object_add(obj, bt);
875 wd->home_button = bt;
876
877 for (i = 0; i < ELM_FILE_LAST; ++i)
878 {
879 list_itc[i] = elm_genlist_item_class_new();
880 grid_itc[i] = elm_gengrid_item_class_new();
881
882 list_itc[i]->item_style = "default";
883 list_itc[i]->func.text_get = grid_itc[i]->func.text_get = _itc_text_get;
884 list_itc[i]->func.state_get = grid_itc[i]->func.state_get = _itc_state_get;
885 list_itc[i]->func.del = grid_itc[i]->func.del = _itc_del;
886 }
887
888 list_itc[ELM_DIRECTORY]->func.content_get =
889 grid_itc[ELM_DIRECTORY]->func.content_get = _itc_icon_folder_get;
890 list_itc[ELM_FILE_IMAGE]->func.content_get =
891 grid_itc[ELM_FILE_IMAGE]->func.content_get = _itc_icon_image_get;
892 list_itc[ELM_FILE_UNKNOW]->func.content_get =
893 grid_itc[ELM_FILE_UNKNOW]->func.content_get = _itc_icon_file_get;
894
895 li = elm_genlist_add(parent);
896 elm_widget_mirrored_automatic_set(li, EINA_FALSE);
897 evas_object_size_hint_align_set(li, EVAS_HINT_FILL, EVAS_HINT_FILL);
898 evas_object_size_hint_weight_set(li, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
899 evas_object_size_hint_min_set(li, 100, 100);
900
901 grid = elm_gengrid_add(parent);
902 elm_widget_mirrored_automatic_set(grid, EINA_FALSE);
903 evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
904 evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
905
906 // XXX: will fail for dynamic finger size changing
907 s = _elm_config->finger_size * 2;
908 elm_gengrid_item_size_set(grid, s, s);
909 elm_gengrid_align_set(grid, 0.0, 0.0);
910
911 evas_object_smart_callback_add(li, "selected", _sel, obj);
912 evas_object_smart_callback_add(li, "expand,request", _expand_req, obj);
913 evas_object_smart_callback_add(li, "contract,request", _contract_req, obj);
914 evas_object_smart_callback_add(li, "expanded", _expand_done, obj);
915 evas_object_smart_callback_add(li, "contracted", _contract_done, obj);
916
917 evas_object_smart_callback_add(grid, "selected", _sel, obj);
918
919 elm_widget_sub_object_add(obj, li);
920 elm_widget_sub_object_add(obj, grid);
921 wd->files_list = li;
922 wd->files_grid = grid;
923
924 // path entry
925 en = elm_entry_add(parent);
926 elm_entry_scrollable_set(en, EINA_TRUE);
927 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
928 elm_entry_editable_set(en, EINA_FALSE);
929 elm_entry_single_line_set(en, EINA_TRUE);
930 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
931 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
932 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
933
934 evas_object_smart_callback_add(en, "anchor,clicked", _anchor_clicked, obj);
935
936 elm_widget_sub_object_add(obj, en);
937 wd->path_entry = en;
938
939 // filename entry
940 en = elm_entry_add(parent);
941 elm_entry_scrollable_set(en, EINA_TRUE);
942 elm_widget_mirrored_automatic_set(en, EINA_FALSE);
943 elm_entry_editable_set(en, EINA_TRUE);
944 elm_entry_single_line_set(en, EINA_TRUE);
945 elm_entry_line_wrap_set(en, ELM_WRAP_CHAR);
946 evas_object_size_hint_weight_set(en, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
947 evas_object_size_hint_align_set(en, EVAS_HINT_FILL, EVAS_HINT_FILL);
948
949 elm_widget_sub_object_add(obj, en);
950 wd->filename_entry = en;
951
952 elm_fileselector_buttons_ok_cancel_set(obj, EINA_TRUE);
953 elm_fileselector_is_save_set(obj, EINA_FALSE);
954
955 _theme_hook(obj);
956
957 evas_object_smart_callbacks_descriptions_set(obj, _signals);
958 return obj;
959}
960
961EAPI void
962elm_fileselector_is_save_set(Evas_Object *obj,
963 Eina_Bool is_save)
964{
965 ELM_CHECK_WIDTYPE(obj, widtype);
966 Widget_Data *wd = elm_widget_data_get(obj);
967 if (!wd) return;
968
969 elm_object_disabled_set(wd->filename_entry, !is_save);
970
971 if (is_save)
972 edje_object_signal_emit(wd->edje, "elm,state,save,on", "elm");
973 else
974 edje_object_signal_emit(wd->edje, "elm,state,save,off", "elm");
975}
976
977EAPI Eina_Bool
978elm_fileselector_is_save_get(const Evas_Object *obj)
979{
980 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
981 Widget_Data *wd = elm_widget_data_get(obj);
982 if (!wd) return EINA_FALSE;
983 return !elm_object_disabled_get(wd->filename_entry);
984}
985
986EAPI void
987elm_fileselector_folder_only_set(Evas_Object *obj,
988 Eina_Bool only)
989{
990 ELM_CHECK_WIDTYPE(obj, widtype);
991 Widget_Data *wd = elm_widget_data_get(obj);
992 if (!wd) return;
993 if (wd->only_folder == only) return;
994 wd->only_folder = !!only;
995 if (wd->path) _populate(obj, wd->path, NULL);
996}
997
998EAPI Eina_Bool
999elm_fileselector_folder_only_get(const Evas_Object *obj)
1000{
1001 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1002 Widget_Data *wd = elm_widget_data_get(obj);
1003 if (!wd) return EINA_FALSE;
1004 return wd->only_folder;
1005}
1006
1007EAPI void
1008elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj,
1009 Eina_Bool visible)
1010{
1011 ELM_CHECK_WIDTYPE(obj, widtype);
1012 Widget_Data *wd = elm_widget_data_get(obj);
1013 Evas_Object *bt;
1014 if (!wd) return;
1015
1016 if (visible)
1017 {
1018 // cancel btn
1019 bt = elm_button_add(obj);
1020 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1021 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("Cancel"));
1022
1023 evas_object_smart_callback_add(bt, "clicked", _canc, obj);
1024
1025 elm_widget_sub_object_add(obj, bt);
1026 wd->cancel_button = bt;
1027
1028 // ok btn
1029 bt = elm_button_add(obj);
1030 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
1031 elm_object_domain_translatable_text_set(bt, PACKAGE, N_("OK"));
1032
1033 evas_object_smart_callback_add(bt, "clicked", _ok, obj);
1034
1035 elm_widget_sub_object_add(obj, bt);
1036 wd->ok_button = bt;
1037
1038 _theme_hook(obj);
1039 }
1040 else
1041 {
1042 evas_object_del(wd->cancel_button);
1043 wd->cancel_button = NULL;
1044 evas_object_del(wd->ok_button);
1045 wd->ok_button = NULL;
1046 }
1047}
1048
1049EAPI Eina_Bool
1050elm_fileselector_buttons_ok_cancel_get(const Evas_Object *obj)
1051{
1052 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1053 Widget_Data *wd = elm_widget_data_get(obj);
1054 if (!wd) return EINA_FALSE;
1055 return wd->ok_button ? EINA_TRUE : EINA_FALSE;
1056}
1057
1058EAPI void
1059elm_fileselector_expandable_set(Evas_Object *obj,
1060 Eina_Bool expand)
1061{
1062 ELM_CHECK_WIDTYPE(obj, widtype);
1063 Widget_Data *wd;
1064
1065 wd = elm_widget_data_get(obj);
1066 if (!wd) return;
1067
1068 wd->expand = !!expand;
1069
1070 if (wd->path) _populate(obj, wd->path, NULL);
1071}
1072
1073EAPI Eina_Bool
1074elm_fileselector_expandable_get(const Evas_Object *obj)
1075{
1076 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1077 Widget_Data *wd = elm_widget_data_get(obj);
1078 if (!wd) return EINA_FALSE;
1079 return wd->expand;
1080}
1081
1082EAPI void
1083elm_fileselector_path_set(Evas_Object *obj,
1084 const char *_path)
1085{
1086 ELM_CHECK_WIDTYPE(obj, widtype);
1087 char *path;
1088 path = ecore_file_realpath(_path);
1089 _populate(obj, path, NULL);
1090 free(path);
1091}
1092
1093EAPI const char *
1094elm_fileselector_path_get(const Evas_Object *obj)
1095{
1096 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1097 Widget_Data *wd = elm_widget_data_get(obj);
1098 if (!wd) return NULL;
1099 return wd->path;
1100}
1101
1102EAPI void
1103elm_fileselector_mode_set(Evas_Object *obj,
1104 Elm_Fileselector_Mode mode)
1105{
1106 ELM_CHECK_WIDTYPE(obj, widtype);
1107
1108 Widget_Data *wd = elm_widget_data_get(obj);
1109 if (!wd) return;
1110
1111 if (mode == wd->mode) return;
1112
1113 if (mode == ELM_FILESELECTOR_LIST)
1114 {
1115 if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
1116 wd->files_list))
1117 {
1118 evas_object_show(wd->files_list);
1119 evas_object_hide(wd->files_grid);
1120 }
1121 else
1122 evas_object_hide(wd->files_list);
1123 }
1124 else
1125 {
1126 if (edje_object_part_swallow(wd->edje, "elm.swallow.files",
1127 wd->files_grid))
1128 {
1129 evas_object_show(wd->files_grid);
1130 evas_object_hide(wd->files_list);
1131 }
1132 else
1133 evas_object_hide(wd->files_grid);
1134 }
1135
1136 wd->mode = mode;
1137
1138 _populate(obj, wd->path, NULL);
1139}
1140
1141EAPI Elm_Fileselector_Mode
1142elm_fileselector_mode_get(const Evas_Object *obj)
1143{
1144 ELM_CHECK_WIDTYPE(obj, widtype) ELM_FILESELECTOR_LAST;
1145
1146 Widget_Data *wd = elm_widget_data_get(obj);
1147 if (!wd) return ELM_FILESELECTOR_LAST;
1148
1149 return wd->mode;
1150}
1151
1152EAPI const char *
1153elm_fileselector_selected_get(const Evas_Object *obj)
1154{
1155 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1156 Widget_Data *wd = elm_widget_data_get(obj);
1157 if (!wd) return NULL;
1158
1159 if (!wd->path) return NULL;
1160
1161 if (wd->filename_entry)
1162 {
1163 const char *name;
1164 char buf[PATH_MAX];
1165 char *dir, *s;
1166
1167 dir = wd->only_folder ? ecore_file_dir_get(wd->path) : strdup(wd->path);
1168 name = elm_object_text_get(wd->filename_entry);
1169 if (name)
1170 {
1171 s = elm_entry_markup_to_utf8(name);
1172 if (s)
1173 {
1174 snprintf(buf, sizeof(buf), "%s/%s", dir, s);
1175 free(s);
1176 }
1177 else
1178 snprintf(buf, sizeof(buf), "%s", dir);
1179 }
1180 else
1181 {
1182 snprintf(buf, sizeof(buf), "%s", dir);
1183 }
1184 if (wd->only_folder && !ecore_file_is_dir(buf))
1185 eina_stringshare_replace(&wd->selection, ecore_file_dir_get(buf));
1186 else
1187 eina_stringshare_replace(&wd->selection, buf);
1188 if (dir) free(dir);
1189 return wd->selection;
1190 }
1191
1192 if (wd->mode == ELM_FILESELECTOR_LIST)
1193 {
1194 Elm_Object_Item *gl_it = elm_genlist_selected_item_get(wd->files_list);
1195 if (gl_it) return elm_object_item_data_get(gl_it);
1196 }
1197 else
1198 {
1199 Elm_Object_Item *gg_it = elm_gengrid_selected_item_get(wd->files_grid);
1200 if (gg_it) return elm_object_item_data_get(gg_it);
1201 }
1202
1203 return wd->path;
1204}
1205
1206EAPI Eina_Bool
1207elm_fileselector_selected_set(Evas_Object *obj,
1208 const char *_path)
1209{
1210 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1211 Widget_Data *wd = elm_widget_data_get(obj);
1212 if (!wd) return EINA_FALSE;
1213
1214 Eina_Bool ret = EINA_TRUE;
1215 char *path;
1216 path = ecore_file_realpath(_path);
1217
1218 if (ecore_file_is_dir(path))
1219 _populate(obj, path, NULL);
1220 else
1221 {
1222 if (!ecore_file_exists(path))
1223 {
1224 ret = EINA_FALSE;
1225 goto clean_up;
1226 }
1227
1228 _populate(obj, ecore_file_dir_get(path), NULL);
1229 if (wd->filename_entry)
1230 {
1231 char *s;
1232
1233 s = elm_entry_utf8_to_markup(ecore_file_file_get(path));
1234 if (s)
1235 {
1236 elm_object_text_set(wd->filename_entry, s);
1237 free(s);
1238 }
1239 else
1240 elm_object_text_set(wd->filename_entry, "");
1241 eina_stringshare_replace(&wd->selection, path);
1242 }
1243 }
1244
1245clean_up:
1246 free(path);
1247 return ret;
1248}
1249
diff --git a/libraries/elementary/src/lib/elc_fileselector.h b/libraries/elementary/src/lib/elc_fileselector.h
new file mode 100644
index 0000000..bf11c67
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_fileselector.h
@@ -0,0 +1,313 @@
1/**
2 * @defgroup Fileselector File Selector
3 * @ingroup Elementary
4 *
5 * @image html img/widget/fileselector/preview-00.png
6 * @image latex img/widget/fileselector/preview-00.eps
7 *
8 * A file selector is a widget that allows a user to navigate
9 * through a file system, reporting file selections back via its
10 * API.
11 *
12 * It contains shortcut buttons for home directory (@c ~) and to
13 * jump one directory upwards (..), as well as cancel/ok buttons to
14 * confirm/cancel a given selection. After either one of those two
15 * former actions, the file selector will issue its @c "done" smart
16 * callback.
17 *
18 * There's a text entry on it, too, showing the name of the current
19 * selection. There's the possibility of making it editable, so it
20 * is useful on file saving dialogs on applications, where one
21 * gives a file name to save contents to, in a given directory in
22 * the system. This custom file name will be reported on the @c
23 * "done" smart callback (explained in sequence).
24 *
25 * Finally, it has a view to display file system items into in two
26 * possible forms:
27 * - list
28 * - grid
29 *
30 * If Elementary is built with support of the Ethumb thumbnailing
31 * library, the second form of view will display preview thumbnails
32 * of files which it supports.
33 *
34 * Smart callbacks one can register to:
35 *
36 * - @c "selected" - the user has clicked on a file (when not in
37 * folders-only mode) or directory (when in folders-only mode)
38 * - @c "directory,open" - the list has been populated with new
39 * content (@c event_info is a pointer to the directory's
40 * path, a @b stringshared string)
41 * - @c "done" - the user has clicked on the "ok" or "cancel"
42 * buttons (@c event_info is a pointer to the selection's
43 * path, a @b stringshared string)
44 *
45 * Here is an example on its usage:
46 * @li @ref fileselector_example
47 */
48
49/**
50 * @addtogroup Fileselector
51 * @{
52 */
53
54/**
55 * Defines how a file selector widget is to layout its contents
56 * (file system entries).
57 */
58typedef enum
59{
60 ELM_FILESELECTOR_LIST = 0, /**< layout as a list */
61 ELM_FILESELECTOR_GRID, /**< layout as a grid */
62 ELM_FILESELECTOR_LAST /**< sentinel (helper) value, not used */
63} Elm_Fileselector_Mode;
64
65/**
66 * Add a new file selector widget to the given parent Elementary
67 * (container) object
68 *
69 * @param parent The parent object
70 * @return a new file selector widget handle or @c NULL, on errors
71 *
72 * This function inserts a new file selector widget on the canvas.
73 *
74 * @ingroup Fileselector
75 */
76EAPI Evas_Object *elm_fileselector_add(Evas_Object *parent);
77
78/**
79 * Enable/disable the file name entry box where the user can type
80 * in a name for a file, in a given file selector widget
81 *
82 * @param obj The file selector object
83 * @param is_save @c EINA_TRUE to make the file selector a "saving
84 * dialog", @c EINA_FALSE otherwise
85 *
86 * Having the entry editable is useful on file saving dialogs on
87 * applications, where one gives a file name to save contents to,
88 * in a given directory in the system. This custom file name will
89 * be reported on the @c "done" smart callback.
90 *
91 * @see elm_fileselector_is_save_get()
92 *
93 * @ingroup Fileselector
94 */
95EAPI void elm_fileselector_is_save_set(Evas_Object *obj, Eina_Bool is_save);
96
97/**
98 * Get whether the given file selector is in "saving dialog" mode
99 *
100 * @param obj The file selector object
101 * @return @c EINA_TRUE, if the file selector is in "saving dialog"
102 * mode, @c EINA_FALSE otherwise (and on errors)
103 *
104 * @see elm_fileselector_is_save_set() for more details
105 *
106 * @ingroup Fileselector
107 */
108EAPI Eina_Bool elm_fileselector_is_save_get(const Evas_Object *obj);
109
110/**
111 * Enable/disable folder-only view for a given file selector widget
112 *
113 * @param obj The file selector object
114 * @param only @c EINA_TRUE to make @p obj only display
115 * directories, @c EINA_FALSE to make files to be displayed in it
116 * too
117 *
118 * If enabled, the widget's view will only display folder items,
119 * naturally.
120 *
121 * @see elm_fileselector_folder_only_get()
122 *
123 * @ingroup Fileselector
124 */
125EAPI void elm_fileselector_folder_only_set(Evas_Object *obj, Eina_Bool only);
126
127/**
128 * Get whether folder-only view is set for a given file selector
129 * widget
130 *
131 * @param obj The file selector object
132 * @return only @c EINA_TRUE if @p obj is only displaying
133 * directories, @c EINA_FALSE if files are being displayed in it
134 * too (and on errors)
135 *
136 * @see elm_fileselector_folder_only_get()
137 *
138 * @ingroup Fileselector
139 */
140EAPI Eina_Bool elm_fileselector_folder_only_get(const Evas_Object *obj);
141
142/**
143 * Enable/disable the "ok" and "cancel" buttons on a given file
144 * selector widget
145 *
146 * @param obj The file selector object
147 * @param buttons @c EINA_TRUE to show buttons, @c EINA_FALSE to hide.
148 *
149 * @note A file selector without those buttons will never emit the
150 * @c "done" smart event, and is only usable if one is just hooking
151 * to the other two events.
152 *
153 * @see elm_fileselector_buttons_ok_cancel_get()
154 *
155 * @ingroup Fileselector
156 */
157EAPI void elm_fileselector_buttons_ok_cancel_set(Evas_Object *obj, Eina_Bool buttons);
158
159/**
160 * Get whether the "ok" and "cancel" buttons on a given file
161 * selector widget are being shown.
162 *
163 * @param obj The file selector object
164 * @return @c EINA_TRUE if they are being shown, @c EINA_FALSE
165 * otherwise (and on errors)
166 *
167 * @see elm_fileselector_buttons_ok_cancel_set() for more details
168 *
169 * @ingroup Fileselector
170 */
171EAPI Eina_Bool elm_fileselector_buttons_ok_cancel_get(const Evas_Object *obj);
172
173/**
174 * Enable/disable a tree view in the given file selector widget,
175 * <b>if it's in @c #ELM_FILESELECTOR_LIST mode</b>
176 *
177 * @param obj The file selector object
178 * @param expand @c EINA_TRUE to enable tree view, @c EINA_FALSE to
179 * disable
180 *
181 * In a tree view, arrows are created on the sides of directories,
182 * allowing them to expand in place.
183 *
184 * @note If it's in other mode, the changes made by this function
185 * will only be visible when one switches back to "list" mode.
186 *
187 * @see elm_fileselector_expandable_get()
188 *
189 * @ingroup Fileselector
190 */
191EAPI void elm_fileselector_expandable_set(Evas_Object *obj, Eina_Bool expand);
192
193/**
194 * Get whether tree view is enabled for the given file selector
195 * widget
196 *
197 * @param obj The file selector object
198 * @return @c EINA_TRUE if @p obj is in tree view, @c EINA_FALSE
199 * otherwise (and or errors)
200 *
201 * @see elm_fileselector_expandable_set() for more details
202 *
203 * @ingroup Fileselector
204 */
205EAPI Eina_Bool elm_fileselector_expandable_get(const Evas_Object *obj);
206
207/**
208 * Set, programmatically, the @b directory that a given file
209 * selector widget will display contents from
210 *
211 * @param obj The file selector object
212 * @param path The path to display in @p obj
213 *
214 * This will change the @b directory that @p obj is displaying. It
215 * will also clear the text entry area on the @p obj object, which
216 * displays select files' names.
217 *
218 * @see elm_fileselector_path_get()
219 *
220 * @ingroup Fileselector
221 */
222EAPI void elm_fileselector_path_set(Evas_Object *obj, const char *path);
223
224/**
225 * Get the parent directory's path that a given file selector
226 * widget is displaying
227 *
228 * @param obj The file selector object
229 * @return The (full) path of the directory the file selector is
230 * displaying, a @b stringshared string
231 *
232 * @see elm_fileselector_path_set()
233 *
234 * @ingroup Fileselector
235 */
236EAPI const char *elm_fileselector_path_get(const Evas_Object *obj);
237
238/**
239 * Set, programmatically, the currently selected file/directory in
240 * the given file selector widget
241 *
242 * @param obj The file selector object
243 * @param path The (full) path to a file or directory
244 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure. The
245 * latter case occurs if the directory or file pointed to do not
246 * exist.
247 *
248 * @see elm_fileselector_selected_get()
249 *
250 * @ingroup Fileselector
251 */
252EAPI Eina_Bool elm_fileselector_selected_set(Evas_Object *obj, const char *path);
253
254/**
255 * Get the currently selected item's (full) path, in the given file
256 * selector widget
257 *
258 * @param obj The file selector object
259 * @return The absolute path of the selected item, a @b
260 * stringshared string
261 *
262 * @note Custom editions on @p obj object's text entry, if made,
263 * will appear on the return string of this function, naturally.
264 *
265 * @see elm_fileselector_selected_set() for more details
266 *
267 * @ingroup Fileselector
268 */
269EAPI const char *elm_fileselector_selected_get(const Evas_Object *obj);
270
271/**
272 * Set the mode in which a given file selector widget will display
273 * (layout) file system entries in its view
274 *
275 * @param obj The file selector object
276 * @param mode The mode of the fileselector, being it one of
277 * #ELM_FILESELECTOR_LIST (default) or #ELM_FILESELECTOR_GRID. The
278 * first one, naturally, will display the files in a list. The
279 * latter will make the widget to display its entries in a grid
280 * form.
281 *
282 * @note By using elm_fileselector_expandable_set(), the user may
283 * trigger a tree view for that list.
284 *
285 * @note If Elementary is built with support of the Ethumb
286 * thumbnailing library, the second form of view will display
287 * preview thumbnails of files which it supports. You must have
288 * elm_need_ethumb() called in your Elementary for thumbnailing to
289 * work, though.
290 *
291 * @see elm_fileselector_expandable_set().
292 * @see elm_fileselector_mode_get().
293 *
294 * @ingroup Fileselector
295 */
296EAPI void elm_fileselector_mode_set(Evas_Object *obj, Elm_Fileselector_Mode mode);
297
298/**
299 * Get the mode in which a given file selector widget is displaying
300 * (layouting) file system entries in its view
301 *
302 * @param obj The fileselector object
303 * @return The mode in which the fileselector is at
304 *
305 * @see elm_fileselector_mode_set() for more details
306 *
307 * @ingroup Fileselector
308 */
309EAPI Elm_Fileselector_Mode elm_fileselector_mode_get(const Evas_Object *obj);
310
311/**
312 * @}
313 */
diff --git a/libraries/elementary/src/lib/elc_fileselector_button.c b/libraries/elementary/src/lib/elc_fileselector_button.c
new file mode 100644
index 0000000..452498d
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_fileselector_button.c
@@ -0,0 +1,520 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *self, *btn, *fs, *fsw;
9 const char *window_title;
10 Evas_Coord w, h;
11 struct
12 {
13 const char *path;
14 Eina_Bool expandable : 1;
15 Eina_Bool folder_only : 1;
16 Eina_Bool is_save : 1;
17 } fsd;
18 Eina_Bool inwin_mode : 1;
19};
20
21#define DEFAULT_WINDOW_TITLE "Select a file"
22
23static const char *widtype = NULL;
24
25static void _del_pre_hook(Evas_Object *obj);
26static void _del_hook(Evas_Object *obj);
27static void _theme_hook(Evas_Object *obj);
28static void _disable_hook(Evas_Object *obj);
29static void _sizing_eval(Evas_Object *obj);
30static void _changed_size_hints(void *data,
31 Evas *e,
32 Evas_Object *obj,
33 void *event_info);
34static void _button_clicked(void *data,
35 Evas_Object *obj,
36 void *event_info);
37static void _on_focus_hook(void *data,
38 Evas_Object *obj);
39static void _selection_done(void *data,
40 Evas_Object *obj,
41 void *event_info);
42static void _activate(Widget_Data *wd);
43
44static const char SIG_FILE_CHOSEN[] = "file,chosen";
45static const Evas_Smart_Cb_Description _signals[] = {
46 {SIG_FILE_CHOSEN, "s"},
47 {NULL, NULL}
48};
49
50static void
51_del_pre_hook(Evas_Object *obj)
52{
53 Widget_Data *wd = elm_widget_data_get(obj);
54 if (!wd) return;
55 evas_object_event_callback_del_full(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
56 _changed_size_hints, obj);
57 evas_object_smart_callback_del(wd->btn, "clicked", _button_clicked);
58}
59
60static void
61_del_hook(Evas_Object *obj)
62{
63 Evas_Object *win;
64 Widget_Data *wd;
65
66 wd = elm_widget_data_get(obj);
67 if (!wd) return;
68
69 if (wd->window_title) eina_stringshare_del(wd->window_title);
70 if (wd->fsd.path) eina_stringshare_del(wd->fsd.path);
71 if (wd->fs)
72 {
73 win = evas_object_data_del(obj, "win");
74 evas_object_del(win);
75 }
76 free(wd);
77}
78
79static void
80_on_focus_hook(void *data __UNUSED__,
81 Evas_Object *obj)
82{
83 Widget_Data *wd = elm_widget_data_get(obj);
84 if (!wd) return;
85 if (elm_widget_focus_get(obj))
86 elm_widget_focus_steal(wd->btn);
87}
88
89static void
90_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
91{
92 Widget_Data *wd = elm_widget_data_get(obj);
93 if (!wd) return;
94 elm_widget_mirrored_set(wd->btn, rtl);
95 elm_widget_mirrored_set(wd->fs, rtl);
96}
97
98static void
99_theme_hook(Evas_Object *obj)
100{
101 Widget_Data *wd = elm_widget_data_get(obj);
102 char buf[4096];
103 if (!wd) return;
104 _elm_widget_mirrored_reload(obj);
105 _mirrored_set(obj, elm_widget_mirrored_get(obj));
106
107 snprintf(buf, sizeof(buf), "fileselector_button/%s",
108 elm_widget_style_get(obj));
109 elm_object_style_set(wd->btn, buf);
110 _sizing_eval(obj);
111}
112
113static void
114_disable_hook(Evas_Object *obj)
115{
116 Widget_Data *wd = elm_widget_data_get(obj);
117 if (!wd) return;
118 elm_widget_disabled_set(wd->btn, elm_widget_disabled_get(obj));
119}
120
121static void
122_sizing_eval(Evas_Object *obj)
123{
124 Widget_Data *wd = elm_widget_data_get(obj);
125 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
126 if (!wd) return;
127 evas_object_size_hint_min_get(wd->btn, &minw, &minh);
128 evas_object_size_hint_max_get(wd->btn, &maxw, &maxh);
129 evas_object_size_hint_min_set(obj, minw, minh);
130 evas_object_size_hint_max_set(obj, maxw, maxh);
131}
132
133static void
134_changed_size_hints(void *data,
135 Evas *e __UNUSED__,
136 Evas_Object *obj __UNUSED__,
137 void *event_info __UNUSED__)
138{
139 Widget_Data *wd = elm_widget_data_get(data);
140 if (!wd) return;
141 _sizing_eval(data);
142}
143
144static void
145_activate_hook(Evas_Object *obj)
146{
147 Widget_Data *wd;
148 wd = elm_widget_data_get(obj);
149 if (!wd) return;
150 _activate(wd);
151}
152
153static void
154_button_clicked(void *data,
155 Evas_Object *obj __UNUSED__,
156 void *event_info __UNUSED__)
157{
158 _activate(data);
159}
160
161static Evas_Object *
162_parent_win_get(Evas_Object *obj)
163{
164 while ((obj) && (strcmp(elm_widget_type_get(obj), "win")))
165 obj = elm_object_parent_widget_get(obj);
166
167 return obj;
168}
169
170static Evas_Object *
171_new_window_add(Widget_Data *wd)
172{
173 Evas_Object *win, *bg;
174
175 win = elm_win_add(NULL, "fileselector_button", ELM_WIN_DIALOG_BASIC);
176 elm_win_title_set(win, wd->window_title);
177 elm_win_autodel_set(win, EINA_TRUE);
178
179 bg = elm_bg_add(win);
180 elm_win_resize_object_add(win, bg);
181 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
182 evas_object_show(bg);
183
184 evas_object_resize(win, wd->w, wd->h);
185 return win;
186}
187
188static void
189_activate(Widget_Data *wd)
190{
191 Eina_Bool is_inwin = EINA_FALSE;
192
193 if (wd->fs) return;
194
195 if (wd->inwin_mode)
196 {
197 wd->fsw = _parent_win_get(wd->self);
198
199 if (!wd->fsw)
200 wd->fsw = _new_window_add(wd);
201 else
202 {
203 wd->fsw = elm_win_inwin_add(wd->fsw);
204 is_inwin = EINA_TRUE;
205 }
206 }
207 else
208 wd->fsw = _new_window_add(wd);
209
210 wd->fs = elm_fileselector_add(wd->fsw);
211 elm_widget_mirrored_set(wd->fs, elm_widget_mirrored_get(wd->self));
212 elm_widget_mirrored_automatic_set(wd->fs, EINA_FALSE);
213 elm_fileselector_expandable_set(wd->fs, wd->fsd.expandable);
214 elm_fileselector_folder_only_set(wd->fs, wd->fsd.folder_only);
215 elm_fileselector_is_save_set(wd->fs, wd->fsd.is_save);
216 elm_fileselector_selected_set(wd->fs, wd->fsd.path);
217 evas_object_size_hint_weight_set(wd->fs, EVAS_HINT_EXPAND,
218 EVAS_HINT_EXPAND);
219 evas_object_size_hint_align_set(wd->fs, EVAS_HINT_FILL, EVAS_HINT_FILL);
220 evas_object_smart_callback_add(wd->fs, "done", _selection_done, wd);
221 evas_object_show(wd->fs);
222
223 if (is_inwin)
224 {
225 elm_win_inwin_content_set(wd->fsw, wd->fs);
226 elm_win_inwin_activate(wd->fsw);
227 }
228 else
229 {
230 elm_win_resize_object_add(wd->fsw, wd->fs);
231 evas_object_show(wd->fsw);
232 }
233}
234
235static void
236_selection_done(void *data,
237 Evas_Object *obj __UNUSED__,
238 void *event_info)
239{
240 const char *file = event_info;
241 Widget_Data *wd = data;
242 Evas_Object *del;
243 if (!wd) return;
244
245 if (file) eina_stringshare_replace(&wd->fsd.path, file);
246
247 del = wd->fsw;
248 wd->fs = NULL;
249 wd->fsw = NULL;
250 evas_object_del(del);
251
252 evas_object_smart_callback_call(wd->self, SIG_FILE_CHOSEN,
253 (void *)wd->fsd.path);
254}
255
256static void
257_elm_fileselector_button_label_set(Evas_Object *obj, const char *item,
258 const char *label)
259{
260 ELM_CHECK_WIDTYPE(obj, widtype);
261 if (item && strcmp(item, "default")) return;
262 Widget_Data *wd = elm_widget_data_get(obj);
263 if (!wd) return;
264 elm_object_text_set(wd->btn, label);
265}
266
267static const char *
268_elm_fileselector_button_label_get(const Evas_Object *obj, const char *item)
269{
270 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
271 Widget_Data *wd = elm_widget_data_get(obj);
272 if (item && strcmp(item, "default")) return NULL;
273 if (!wd) return NULL;
274 return elm_object_text_get(wd->btn);
275}
276
277static void
278_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
279{
280 ELM_CHECK_WIDTYPE(obj, widtype);
281 Widget_Data *wd = elm_widget_data_get(obj);
282 if (!wd) return;
283 elm_object_part_content_set(wd->btn, part, content);
284}
285
286static Evas_Object *
287_content_get_hook(const Evas_Object *obj, const char *part)
288{
289 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
290 Widget_Data *wd = elm_widget_data_get(obj);
291 if (!wd) return NULL;
292 return elm_object_part_content_get(wd->btn, part);
293}
294
295static Evas_Object *
296_content_unset_hook(Evas_Object *obj, const char *part)
297{
298 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
299 Widget_Data *wd = elm_widget_data_get(obj);
300 if (!wd) return NULL;
301 return elm_object_part_content_unset(wd->btn, part);
302}
303
304EAPI Evas_Object *
305elm_fileselector_button_add(Evas_Object *parent)
306{
307 Evas_Object *obj;
308 Evas *e;
309 Widget_Data *wd;
310
311 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
312
313 ELM_SET_WIDTYPE(widtype, "fileselector_button");
314 elm_widget_type_set(obj, "fileselector_button");
315 elm_widget_sub_object_add(parent, obj);
316 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
317 elm_widget_data_set(obj, wd);
318 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
319 elm_widget_del_hook_set(obj, _del_hook);
320 elm_widget_theme_hook_set(obj, _theme_hook);
321 elm_widget_disable_hook_set(obj, _disable_hook);
322 elm_widget_can_focus_set(obj, EINA_TRUE);
323 elm_widget_activate_hook_set(obj, _activate_hook);
324 elm_widget_text_set_hook_set(obj, _elm_fileselector_button_label_set);
325 elm_widget_text_get_hook_set(obj, _elm_fileselector_button_label_get);
326 elm_widget_content_set_hook_set(obj, _content_set_hook);
327 elm_widget_content_get_hook_set(obj, _content_get_hook);
328 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
329
330 wd->self = obj;
331 wd->window_title = eina_stringshare_add(DEFAULT_WINDOW_TITLE);
332 if (getenv("HOME")) wd->fsd.path = eina_stringshare_add(getenv("HOME"));
333 else wd->fsd.path = eina_stringshare_add("/");
334 wd->fsd.expandable = _elm_config->fileselector_expand_enable;
335 wd->inwin_mode = _elm_config->inwin_dialogs_enable;
336 wd->w = 400;
337 wd->h = 400;
338
339 wd->btn = elm_button_add(parent);
340 elm_widget_mirrored_automatic_set(wd->btn, EINA_FALSE);
341 elm_widget_resize_object_set(obj, wd->btn);
342 evas_object_event_callback_add(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
343 _changed_size_hints, obj);
344 evas_object_smart_callback_add(wd->btn, "clicked", _button_clicked, wd);
345 elm_widget_sub_object_add(obj, wd->btn);
346
347 _theme_hook(obj);
348 evas_object_smart_callbacks_descriptions_set(obj, _signals);
349 return obj;
350}
351
352
353EAPI void
354elm_fileselector_button_window_title_set(Evas_Object *obj,
355 const char *title)
356{
357 ELM_CHECK_WIDTYPE(obj, widtype);
358 Widget_Data *wd = elm_widget_data_get(obj);
359
360 if (!wd) return;
361 eina_stringshare_replace(&wd->window_title, title);
362
363 if (wd->fsw)
364 elm_win_title_set(wd->fsw, wd->window_title);
365}
366
367EAPI const char *
368elm_fileselector_button_window_title_get(const Evas_Object *obj)
369{
370 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
371 Widget_Data *wd = elm_widget_data_get(obj);
372
373 if (!wd) return NULL;
374 return wd->window_title;
375}
376
377EAPI void
378elm_fileselector_button_window_size_set(Evas_Object *obj,
379 Evas_Coord width,
380 Evas_Coord height)
381{
382 ELM_CHECK_WIDTYPE(obj, widtype);
383 Widget_Data *wd = elm_widget_data_get(obj);
384
385 if (!wd) return;
386 wd->w = width;
387 wd->h = height;
388
389 if (wd->fsw)
390 evas_object_resize(wd->fsw, wd->w, wd->h);
391}
392
393EAPI void
394elm_fileselector_button_window_size_get(const Evas_Object *obj,
395 Evas_Coord *width,
396 Evas_Coord *height)
397{
398 ELM_CHECK_WIDTYPE(obj, widtype);
399 Widget_Data *wd = elm_widget_data_get(obj);
400
401 if (!wd) return;
402 if (width) *width = wd->w;
403 if (height) *height = wd->h;
404}
405
406EAPI void
407elm_fileselector_button_path_set(Evas_Object *obj,
408 const char *path)
409{
410 ELM_CHECK_WIDTYPE(obj, widtype);
411 Widget_Data *wd = elm_widget_data_get(obj);
412
413 if (!wd) return;
414 eina_stringshare_replace(&wd->fsd.path, path);
415
416 if (wd->fs)
417 elm_fileselector_selected_set(wd->fs, wd->fsd.path);
418}
419
420EAPI const char *
421elm_fileselector_button_path_get(const Evas_Object *obj)
422{
423 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
424 Widget_Data *wd = elm_widget_data_get(obj);
425 if (!wd) return NULL;
426 return wd->fsd.path;
427}
428
429EAPI void
430elm_fileselector_button_expandable_set(Evas_Object *obj,
431 Eina_Bool value)
432{
433 ELM_CHECK_WIDTYPE(obj, widtype);
434 Widget_Data *wd = elm_widget_data_get(obj);
435
436 if (!wd) return;
437 wd->fsd.expandable = value;
438
439 if (wd->fs)
440 elm_fileselector_expandable_set(wd->fs, wd->fsd.expandable);
441}
442
443EAPI Eina_Bool
444elm_fileselector_button_expandable_get(const Evas_Object *obj)
445{
446 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
447 Widget_Data *wd = elm_widget_data_get(obj);
448
449 if (!wd) return EINA_FALSE;
450 return wd->fsd.expandable;
451}
452
453EAPI void
454elm_fileselector_button_folder_only_set(Evas_Object *obj,
455 Eina_Bool value)
456{
457 ELM_CHECK_WIDTYPE(obj, widtype);
458 Widget_Data *wd = elm_widget_data_get(obj);
459
460 if (!wd) return;
461 wd->fsd.folder_only = value;
462
463 if (wd->fs)
464 elm_fileselector_folder_only_set(wd->fs, wd->fsd.folder_only);
465}
466
467EAPI Eina_Bool
468elm_fileselector_button_folder_only_get(const Evas_Object *obj)
469{
470 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
471 Widget_Data *wd = elm_widget_data_get(obj);
472
473 if (!wd) return EINA_FALSE;
474 return wd->fsd.folder_only;
475}
476
477EAPI void
478elm_fileselector_button_is_save_set(Evas_Object *obj,
479 Eina_Bool value)
480{
481 ELM_CHECK_WIDTYPE(obj, widtype);
482 Widget_Data *wd = elm_widget_data_get(obj);
483
484 if (!wd) return;
485 wd->fsd.is_save = value;
486
487 if (wd->fs)
488 elm_fileselector_is_save_set(wd->fs, wd->fsd.is_save);
489}
490
491EAPI Eina_Bool
492elm_fileselector_button_is_save_get(const Evas_Object *obj)
493{
494 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
495 Widget_Data *wd = elm_widget_data_get(obj);
496
497 if (!wd) return EINA_FALSE;
498 return wd->fsd.is_save;
499}
500
501EAPI void
502elm_fileselector_button_inwin_mode_set(Evas_Object *obj,
503 Eina_Bool value)
504{
505 ELM_CHECK_WIDTYPE(obj, widtype);
506 Widget_Data *wd = elm_widget_data_get(obj);
507
508 if (!wd) return;
509 wd->inwin_mode = value;
510}
511
512EAPI Eina_Bool
513elm_fileselector_button_inwin_mode_get(const Evas_Object *obj)
514{
515 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
516 Widget_Data *wd = elm_widget_data_get(obj);
517
518 if (!wd) return EINA_FALSE;
519 return wd->inwin_mode;
520}
diff --git a/libraries/elementary/src/lib/elc_fileselector_button.h b/libraries/elementary/src/lib/elc_fileselector_button.h
new file mode 100644
index 0000000..3eab292
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_fileselector_button.h
@@ -0,0 +1,306 @@
1/**
2 * @defgroup File_Selector_Button File Selector Button
3 * @ingroup Elementary
4 *
5 * @image html img/widget/fileselector_button/preview-00.png
6 * @image latex img/widget/fileselector_button/preview-00.eps
7 * @image html img/widget/fileselector_button/preview-01.png
8 * @image latex img/widget/fileselector_button/preview-01.eps
9 * @image html img/widget/fileselector_button/preview-02.png
10 * @image latex img/widget/fileselector_button/preview-02.eps
11 *
12 * This is a button that, when clicked, creates an Elementary
13 * window (or inner window) <b> with a @ref Fileselector "file
14 * selector widget" within</b>. When a file is chosen, the (inner)
15 * window is closed and the button emits a signal having the
16 * selected file as it's @c event_info.
17 *
18 * This widget encapsulates operations on its internal file
19 * selector on its own API. There is less control over its file
20 * selector than that one would have instantiating one directly.
21 *
22 * The following styles are available for this button:
23 * @li @c "default"
24 * @li @c "anchor"
25 * @li @c "hoversel_vertical"
26 * @li @c "hoversel_vertical_entry"
27 *
28 * Smart callbacks one can register to:
29 * - @c "file,chosen" - the user has selected a path, whose string
30 * pointer comes as the @c event_info data (a stringshared
31 * string)
32 *
33 * Default text parts of the fileselector_button widget that you can use for
34 * are:
35 * @li "default" - Label of the fileselector_button
36 *
37 * Default content parts of the fileselector_button widget that you can use for
38 * are:
39 * @li "icon" - Icon of the fileselector_button
40 *
41 * Supported elm_object common APIs.
42 * @li @ref elm_object_part_text_set
43 * @li @ref elm_object_part_text_get
44 * @li @ref elm_object_part_content_set
45 * @li @ref elm_object_part_content_get
46 * @li @ref elm_object_part_content_unset
47 * @li @ref elm_object_disabled_set
48 * @li @ref elm_object_disabled_get
49 *
50 * Here is an example on its usage:
51 * @li @ref fileselector_button_example
52 *
53 * @see @ref File_Selector_Entry for a similar widget.
54 * @{
55 */
56
57/**
58 * Add a new file selector button widget to the given parent
59 * Elementary (container) object
60 *
61 * @param parent The parent object
62 * @return a new file selector button widget handle or @c NULL, on
63 * errors
64 *
65 * @ingroup File_Selector_Button
66 */
67EAPI Evas_Object *elm_fileselector_button_add(Evas_Object *parent);
68
69/**
70 * Set the title for a given file selector button widget's window
71 *
72 * @param obj The file selector button widget
73 * @param title The title string
74 *
75 * This will change the popup window's title, when the file selector pops
76 * out after a click on the button. Those windows have the default
77 * (unlocalized) value of @c "Select a file" as titles.
78 *
79 * @note It will only take effect if the file selector
80 * button widget is @b not under "inwin mode".
81 *
82 * @see elm_fileselector_button_window_title_get()
83 *
84 * @ingroup File_Selector_Button
85 */
86EAPI void elm_fileselector_button_window_title_set(Evas_Object *obj, const char *title);
87
88/**
89 * Get the title for a given file selector button widget's
90 * window
91 *
92 * @param obj The file selector button widget
93 * @return Title of the file selector button's window
94 *
95 * @see elm_fileselector_button_window_title_get() for more details
96 *
97 * @ingroup File_Selector_Button
98 */
99EAPI const char *elm_fileselector_button_window_title_get(const Evas_Object *obj);
100
101/**
102 * Set the size of a given file selector button widget's window,
103 * holding the file selector itself.
104 *
105 * @param obj The file selector button widget
106 * @param width The window's width
107 * @param height The window's height
108 *
109 * @note it will only take any effect if the file selector button
110 * widget is @b not under "inwin mode". The default size for the
111 * window (when applicable) is 400x400 pixels.
112 *
113 * @see elm_fileselector_button_window_size_get()
114 *
115 * @ingroup File_Selector_Button
116 */
117EAPI void elm_fileselector_button_window_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height);
118
119/**
120 * Get the size of a given file selector button widget's window,
121 * holding the file selector itself.
122 *
123 * @param obj The file selector button widget
124 * @param width Pointer into which to store the width value
125 * @param height Pointer into which to store the height value
126 *
127 * @note Use @c NULL pointers on the size values you're not
128 * interested in: they'll be ignored by the function.
129 *
130 * @see elm_fileselector_button_window_size_set(), for more details
131 *
132 * @ingroup File_Selector_Button
133 */
134EAPI void elm_fileselector_button_window_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height);
135
136/**
137 * Set the initial file system path for a given file selector
138 * button widget
139 *
140 * @param obj The file selector button widget
141 * @param path The path string
142 *
143 * It must be a <b>directory</b> path, which will have the contents
144 * displayed initially in the file selector's view, when invoked
145 * from @p obj. The default initial path is the @c "HOME"
146 * environment variable's value.
147 *
148 * @see elm_fileselector_button_path_get()
149 *
150 * @ingroup File_Selector_Button
151 */
152EAPI void elm_fileselector_button_path_set(Evas_Object *obj, const char *path);
153
154/**
155 * Get the initial file system path set for a given file selector
156 * button widget
157 *
158 * @param obj The file selector button widget
159 * @return path The path string
160 *
161 * @see elm_fileselector_button_path_set() for more details
162 *
163 * @ingroup File_Selector_Button
164 */
165EAPI const char *elm_fileselector_button_path_get(const Evas_Object *obj);
166
167/**
168 * Enable/disable a tree view in the given file selector button
169 * widget's internal file selector
170 *
171 * @param obj The file selector button widget
172 * @param value @c EINA_TRUE to enable tree view, @c EINA_FALSE to
173 * disable
174 *
175 * This has the same effect as elm_fileselector_expandable_set(),
176 * but now applied to a file selector button's internal file
177 * selector.
178 *
179 * @note There's no way to put a file selector button's internal
180 * file selector in "grid mode", as one may do with "pure" file
181 * selectors.
182 *
183 * @see elm_fileselector_expandable_get()
184 *
185 * @ingroup File_Selector_Button
186 */
187EAPI void elm_fileselector_button_expandable_set(Evas_Object *obj, Eina_Bool value);
188
189/**
190 * Get whether tree view is enabled for the given file selector
191 * button widget's internal file selector
192 *
193 * @param obj The file selector button widget
194 * @return @c EINA_TRUE if @p obj widget's internal file selector
195 * is in tree view, @c EINA_FALSE otherwise (and or errors)
196 *
197 * @see elm_fileselector_expandable_set() for more details
198 *
199 * @ingroup File_Selector_Button
200 */
201EAPI Eina_Bool elm_fileselector_button_expandable_get(const Evas_Object *obj);
202
203/**
204 * Set whether a given file selector button widget's internal file
205 * selector is to display folders only or the directory contents,
206 * as well.
207 *
208 * @param obj The file selector button widget
209 * @param value @c EINA_TRUE to make @p obj widget's internal file
210 * selector only display directories, @c EINA_FALSE to make files
211 * to be displayed in it too
212 *
213 * This has the same effect as elm_fileselector_folder_only_set(),
214 * but now applied to a file selector button's internal file
215 * selector.
216 *
217 * @see elm_fileselector_folder_only_get()
218 *
219 * @ingroup File_Selector_Button
220 */
221EAPI void elm_fileselector_button_folder_only_set(Evas_Object *obj, Eina_Bool value);
222
223/**
224 * Get whether a given file selector button widget's internal file
225 * selector is displaying folders only or the directory contents,
226 * as well.
227 *
228 * @param obj The file selector button widget
229 * @return @c EINA_TRUE if @p obj widget's internal file
230 * selector is only displaying directories, @c EINA_FALSE if files
231 * are being displayed in it too (and on errors)
232 *
233 * @see elm_fileselector_button_folder_only_set() for more details
234 *
235 * @ingroup File_Selector_Button
236 */
237EAPI Eina_Bool elm_fileselector_button_folder_only_get(const Evas_Object *obj);
238
239/**
240 * Enable/disable the file name entry box where the user can type
241 * in a name for a file, in a given file selector button widget's
242 * internal file selector.
243 *
244 * @param obj The file selector button widget
245 * @param value @c EINA_TRUE to make @p obj widget's internal
246 * file selector a "saving dialog", @c EINA_FALSE otherwise
247 *
248 * This has the same effect as elm_fileselector_is_save_set(),
249 * but now applied to a file selector button's internal file
250 * selector.
251 *
252 * @see elm_fileselector_is_save_get()
253 *
254 * @ingroup File_Selector_Button
255 */
256EAPI void elm_fileselector_button_is_save_set(Evas_Object *obj, Eina_Bool value);
257
258/**
259 * Get whether the given file selector button widget's internal
260 * file selector is in "saving dialog" mode
261 *
262 * @param obj The file selector button widget
263 * @return @c EINA_TRUE, if @p obj widget's internal file selector
264 * is in "saving dialog" mode, @c EINA_FALSE otherwise (and on
265 * errors)
266 *
267 * @see elm_fileselector_button_is_save_set() for more details
268 *
269 * @ingroup File_Selector_Button
270 */
271EAPI Eina_Bool elm_fileselector_button_is_save_get(const Evas_Object *obj);
272
273/**
274 * Set whether a given file selector button widget's internal file
275 * selector will raise an Elementary "inner window", instead of a
276 * dedicated Elementary window. By default, it won't.
277 *
278 * @param obj The file selector button widget
279 * @param value @c EINA_TRUE to make it use an inner window, @c
280 * EINA_TRUE to make it use a dedicated window
281 *
282 * @see elm_win_inwin_add() for more information on inner windows
283 * @see elm_fileselector_button_inwin_mode_get()
284 *
285 * @ingroup File_Selector_Button
286 */
287EAPI void elm_fileselector_button_inwin_mode_set(Evas_Object *obj, Eina_Bool value);
288
289/**
290 * Get whether a given file selector button widget's internal file
291 * selector will raise an Elementary "inner window", instead of a
292 * dedicated Elementary window.
293 *
294 * @param obj The file selector button widget
295 * @return @c EINA_TRUE if will use an inner window, @c EINA_TRUE
296 * if it will use a dedicated window
297 *
298 * @see elm_fileselector_button_inwin_mode_set() for more details
299 *
300 * @ingroup File_Selector_Button
301 */
302EAPI Eina_Bool elm_fileselector_button_inwin_mode_get(const Evas_Object *obj);
303
304/**
305 * @}
306 */
diff --git a/libraries/elementary/src/lib/elc_fileselector_entry.c b/libraries/elementary/src/lib/elc_fileselector_entry.c
new file mode 100644
index 0000000..7c78e2a
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_fileselector_entry.c
@@ -0,0 +1,508 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *edje;
9 Evas_Object *button;
10 Evas_Object *entry;
11 char *path;
12};
13
14static const char *widtype = NULL;
15
16static const char SIG_CHANGED[] = "changed";
17static const char SIG_ACTIVATED[] = "activated";
18static const char SIG_PRESS[] = "press";
19static const char SIG_LONGPRESSED[] = "longpressed";
20static const char SIG_CLICKED[] = "clicked";
21static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
22static const char SIG_FOCUSED[] = "focused";
23static const char SIG_UNFOCUSED[] = "unfocused";
24static const char SIG_SELECTION_PASTE[] = "selection,paste";
25static const char SIG_SELECTION_COPY[] = "selection,copy";
26static const char SIG_SELECTION_CUT[] = "selection,cut";
27static const char SIG_UNPRESSED[] = "unpressed";
28static const char SIG_FILE_CHOSEN[] = "file,chosen";
29static const Evas_Smart_Cb_Description _signals[] =
30{
31 {SIG_CHANGED, ""},
32 {SIG_ACTIVATED, ""},
33 {SIG_PRESS, ""},
34 {SIG_LONGPRESSED, ""},
35 {SIG_CLICKED, ""},
36 {SIG_CLICKED_DOUBLE, ""},
37 {SIG_FOCUSED, ""},
38 {SIG_UNFOCUSED, ""},
39 {SIG_SELECTION_PASTE, ""},
40 {SIG_SELECTION_COPY, ""},
41 {SIG_SELECTION_CUT, ""},
42 {SIG_UNPRESSED, ""},
43 {SIG_FILE_CHOSEN, "s"},
44 {NULL, NULL}
45};
46
47#define SIG_FWD(name) \
48static void \
49_##name##_fwd(void *data, Evas_Object *obj __UNUSED__, void *event_info) \
50{ \
51 evas_object_smart_callback_call(data, SIG_##name, event_info); \
52}
53SIG_FWD(CHANGED)
54SIG_FWD(PRESS)
55SIG_FWD(LONGPRESSED)
56SIG_FWD(CLICKED)
57SIG_FWD(CLICKED_DOUBLE)
58SIG_FWD(FOCUSED)
59SIG_FWD(UNFOCUSED)
60SIG_FWD(SELECTION_PASTE)
61SIG_FWD(SELECTION_COPY)
62SIG_FWD(SELECTION_CUT)
63SIG_FWD(UNPRESSED)
64#undef SIG_FWD
65
66static void _del_pre_hook(Evas_Object *obj);
67static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
68static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
69
70static void
71_FILE_CHOSEN_fwd(void *data, Evas_Object *obj __UNUSED__, void *event_info)
72{
73 Widget_Data *wd = elm_widget_data_get(data);
74 const char *file = event_info;
75 char *s;
76
77 s = elm_entry_utf8_to_markup(file);
78 if (!s) return;
79 elm_object_text_set(wd->entry, s);
80 free(s);
81 evas_object_smart_callback_call(data, SIG_FILE_CHOSEN, event_info);
82}
83
84static void
85_ACTIVATED_fwd(void *data, Evas_Object *obj __UNUSED__, void *event_info)
86{
87 Widget_Data *wd = elm_widget_data_get(data);
88 const char *file = elm_object_text_get(wd->entry);
89 elm_fileselector_button_path_set(wd->button, file);
90 evas_object_smart_callback_call(data, SIG_ACTIVATED, event_info);
91}
92
93static void
94_del_pre_hook(Evas_Object *obj)
95{
96 Widget_Data *wd = elm_widget_data_get(obj);
97 if (!wd) return;
98 evas_object_event_callback_del_full
99 (wd->button, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
100 evas_object_event_callback_del_full
101 (wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
102}
103
104static void
105_del_hook(Evas_Object *obj)
106{
107 Widget_Data *wd = elm_widget_data_get(obj);
108 if (wd->path) free(wd->path);
109 free(wd);
110}
111
112static void
113_sizing_eval(Evas_Object *obj)
114{
115 Widget_Data *wd = elm_widget_data_get(obj);
116 Evas_Coord minw = -1, minh = -1;
117 if (!wd) return;
118 edje_object_size_min_calc(wd->edje, &minw, &minh);
119 evas_object_size_hint_min_set(obj, minw, minh);
120 evas_object_size_hint_max_set(obj, -1, -1);
121}
122
123static Eina_Bool
124_elm_fileselector_entry_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
125{
126 Widget_Data *wd = elm_widget_data_get(obj);
127
128 if (!wd)
129 return EINA_FALSE;
130
131 Evas_Object *chain[2];
132
133 /* Direction */
134 if (dir == ELM_FOCUS_PREVIOUS)
135 {
136 chain[0] = wd->button;
137 chain[1] = wd->entry;
138 }
139 else if (dir == ELM_FOCUS_NEXT)
140 {
141 chain[0] = wd->entry;
142 chain[1] = wd->button;
143 }
144 else
145 return EINA_FALSE;
146
147 unsigned char i = elm_widget_focus_get(chain[1]);
148
149 if (elm_widget_focus_next_get(chain[i], dir, next))
150 return EINA_TRUE;
151
152 i = !i;
153
154 Evas_Object *to_focus;
155 if (elm_widget_focus_next_get(chain[i], dir, &to_focus))
156 {
157 *next = to_focus;
158 return !!i;
159 }
160
161 return EINA_FALSE;
162}
163
164static void
165_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
166{
167 Widget_Data *wd = elm_widget_data_get(obj);
168 if (!wd) return;
169 elm_widget_mirrored_set(wd->button, rtl);
170 edje_object_mirrored_set(wd->edje, rtl);
171}
172
173static void
174_theme_hook(Evas_Object *obj)
175{
176 Widget_Data *wd = elm_widget_data_get(obj);
177 const char *style = elm_widget_style_get(obj);
178 char buf[1024];
179
180 if (!wd) return;
181 _elm_widget_mirrored_reload(obj);
182 _mirrored_set(obj, elm_widget_mirrored_get(obj));
183
184 _elm_theme_object_set(obj, wd->edje, "fileselector_entry", "base", style);
185 if (elm_object_disabled_get(obj))
186 edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm");
187
188 if (!style) style = "default";
189 snprintf(buf, sizeof(buf), "fileselector_entry/%s", style);
190 elm_widget_style_set(wd->button, buf);
191 elm_widget_style_set(wd->entry, buf);
192
193 edje_object_part_swallow(obj, "elm.swallow.button", wd->button);
194 edje_object_part_swallow(obj, "elm.swallow.entry", wd->entry);
195
196 edje_object_message_signal_process(wd->edje);
197 edje_object_scale_set
198 (wd->edje, elm_widget_scale_get(obj) * _elm_config->scale);
199 _sizing_eval(obj);
200}
201
202static void
203_disable_hook(Evas_Object *obj)
204{
205 Widget_Data *wd = elm_widget_data_get(obj);
206 Eina_Bool val = elm_widget_disabled_get(obj);
207 if (!wd) return;
208 if (val)
209 edje_object_signal_emit(wd->edje, "elm,state,disabled", "elm");
210 else
211 edje_object_signal_emit(wd->edje, "elm,state,enabled", "elm");
212
213 elm_widget_disabled_set(wd->button, val);
214 elm_widget_disabled_set(wd->entry, val);
215}
216
217static void
218_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
219{
220 _sizing_eval(data);
221}
222
223static void
224_elm_fileselector_entry_button_label_set(Evas_Object *obj, const char *item, const char *label)
225{
226 ELM_CHECK_WIDTYPE(obj, widtype);
227 Widget_Data *wd = elm_widget_data_get(obj);
228 if (item && strcmp(item, "default")) return;
229 if (!wd) return;
230 elm_object_text_set(wd->button, label);
231}
232
233static const char *
234_elm_fileselector_entry_button_label_get(const Evas_Object *obj, const char *item)
235{
236 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
237 Widget_Data *wd = elm_widget_data_get(obj);
238 if (item && strcmp(item, "default")) return NULL;
239 if (!wd) return NULL;
240 return elm_object_text_get(wd->button);
241}
242
243static void
244_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
245{
246 ELM_CHECK_WIDTYPE(obj, widtype);
247 Widget_Data *wd = elm_widget_data_get(obj);
248 if (!wd) return;
249 if (part && strcmp(part, "button icon")) return;
250 elm_object_part_content_set(wd->button, NULL, content);
251}
252
253static Evas_Object *
254_content_get_hook(const Evas_Object *obj, const char *part)
255{
256 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
257 Widget_Data *wd = elm_widget_data_get(obj);
258 if (!wd) return NULL;
259 if (part && strcmp(part, "button icon")) return NULL;
260 return elm_object_part_content_get(wd->button, NULL);
261}
262
263static Evas_Object *
264_content_unset_hook(Evas_Object *obj, const char *part)
265{
266 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
267 Widget_Data *wd = elm_widget_data_get(obj);
268 if (!wd) return NULL;
269 if (part && strcmp(part, "button icon")) return NULL;
270 return elm_object_part_content_unset(wd->button, NULL);
271}
272
273EAPI Evas_Object *
274elm_fileselector_entry_add(Evas_Object *parent)
275{
276 Evas_Object *obj;
277 Evas *e;
278 Widget_Data *wd;
279
280 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
281
282 ELM_SET_WIDTYPE(widtype, "fileselector_entry");
283 elm_widget_type_set(obj, "fileselector_entry");
284 elm_widget_sub_object_add(parent, obj);
285 elm_widget_data_set(obj, wd);
286 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
287 elm_widget_del_hook_set(obj, _del_hook);
288 elm_widget_disable_hook_set(obj, _disable_hook);
289 elm_widget_focus_next_hook_set(obj, _elm_fileselector_entry_focus_next_hook);
290 elm_widget_can_focus_set(obj, EINA_FALSE);
291 elm_widget_theme_hook_set(obj, _theme_hook);
292 elm_widget_text_set_hook_set(obj, _elm_fileselector_entry_button_label_set);
293 elm_widget_text_get_hook_set(obj, _elm_fileselector_entry_button_label_get);
294 elm_widget_content_set_hook_set(obj, _content_set_hook);
295 elm_widget_content_get_hook_set(obj, _content_get_hook);
296 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
297
298 wd->edje = edje_object_add(e);
299 _elm_theme_object_set(obj, wd->edje, "fileselector_entry", "base", "default");
300 elm_widget_resize_object_set(obj, wd->edje);
301
302 wd->button = elm_fileselector_button_add(obj);
303 elm_widget_mirrored_automatic_set(wd->button, EINA_FALSE);
304 ELM_SET_WIDTYPE(widtype, "fileselector_entry");
305 elm_widget_style_set(wd->button, "fileselector_entry/default");
306 edje_object_part_swallow(wd->edje, "elm.swallow.button", wd->button);
307 elm_widget_sub_object_add(obj, wd->button);
308 evas_object_event_callback_add
309 (wd->button, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
310 elm_fileselector_button_expandable_set(wd->button,
311 _elm_config->fileselector_expand_enable);
312
313#define SIG_FWD(name) \
314 evas_object_smart_callback_add(wd->button, SIG_##name, _##name##_fwd, obj)
315 SIG_FWD(CLICKED);
316 SIG_FWD(UNPRESSED);
317 SIG_FWD(FILE_CHOSEN);
318#undef SIG_FWD
319
320 wd->entry = elm_entry_add(obj);
321 elm_entry_scrollable_set(wd->entry, EINA_TRUE);
322 elm_widget_mirrored_automatic_set(wd->entry, EINA_FALSE);
323 elm_widget_style_set(wd->entry, "fileselector_entry/default");
324 elm_entry_single_line_set(wd->entry, EINA_TRUE);
325 elm_entry_editable_set(wd->entry, EINA_TRUE);
326 edje_object_part_swallow(wd->edje, "elm.swallow.entry", wd->entry);
327 elm_widget_sub_object_add(obj, wd->entry);
328 evas_object_event_callback_add
329 (wd->entry, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
330
331#define SIG_FWD(name) \
332 evas_object_smart_callback_add(wd->entry, SIG_##name, _##name##_fwd, obj)
333 SIG_FWD(CHANGED);
334 SIG_FWD(ACTIVATED);
335 SIG_FWD(PRESS);
336 SIG_FWD(LONGPRESSED);
337 SIG_FWD(CLICKED);
338 SIG_FWD(CLICKED_DOUBLE);
339 SIG_FWD(FOCUSED);
340 SIG_FWD(UNFOCUSED);
341 SIG_FWD(SELECTION_PASTE);
342 SIG_FWD(SELECTION_COPY);
343 SIG_FWD(SELECTION_CUT);
344#undef SIG_FWD
345
346 _mirrored_set(obj, elm_widget_mirrored_get(obj));
347 _sizing_eval(obj);
348
349 // TODO: convert Elementary to subclassing of Evas_Smart_Class
350 // TODO: and save some bytes, making descriptions per-class and not instance!
351 evas_object_smart_callbacks_descriptions_set(obj, _signals);
352 return obj;
353}
354
355EAPI void
356elm_fileselector_entry_selected_set(Evas_Object *obj, const char *path)
357{
358 ELM_CHECK_WIDTYPE(obj, widtype);
359 Widget_Data *wd = elm_widget_data_get(obj);
360 if (!wd) return;
361 elm_fileselector_button_path_set(wd->button, path);
362}
363
364EAPI const char *
365elm_fileselector_entry_selected_get(const Evas_Object *obj)
366{
367 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
368 Widget_Data *wd = elm_widget_data_get(obj);
369 if (!wd) return NULL;
370 return elm_fileselector_button_path_get(wd->button);
371}
372
373EAPI void
374elm_fileselector_entry_window_title_set(Evas_Object *obj, const char *title)
375{
376 ELM_CHECK_WIDTYPE(obj, widtype);
377 Widget_Data *wd = elm_widget_data_get(obj);
378 if (!wd) return;
379 elm_fileselector_button_window_title_set(wd->button, title);
380}
381
382EAPI const char *
383elm_fileselector_entry_window_title_get(const Evas_Object *obj)
384{
385 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
386 Widget_Data *wd = elm_widget_data_get(obj);
387 if (!wd) return NULL;
388 return elm_fileselector_button_window_title_get(wd->button);
389}
390
391EAPI void
392elm_fileselector_entry_window_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height)
393{
394 ELM_CHECK_WIDTYPE(obj, widtype);
395 Widget_Data *wd = elm_widget_data_get(obj);
396 if (!wd) return;
397 elm_fileselector_button_window_size_set(wd->button, width, height);
398}
399
400EAPI void
401elm_fileselector_entry_window_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height)
402{
403 ELM_CHECK_WIDTYPE(obj, widtype);
404 Widget_Data *wd = elm_widget_data_get(obj);
405 if (!wd) return;
406 elm_fileselector_button_window_size_get(wd->button, width, height);
407}
408
409EAPI void
410elm_fileselector_entry_path_set(Evas_Object *obj, const char *path)
411{
412 ELM_CHECK_WIDTYPE(obj, widtype);
413 Widget_Data *wd = elm_widget_data_get(obj);
414 char *s;
415
416 if (!wd) return;
417 elm_fileselector_button_path_set(wd->button, path);
418 s = elm_entry_utf8_to_markup(path);
419 if (s)
420 {
421 elm_object_text_set(wd->entry, s);
422 free(s);
423 }
424}
425
426EAPI const char *
427elm_fileselector_entry_path_get(const Evas_Object *obj)
428{
429 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
430 Widget_Data *wd = elm_widget_data_get(obj);
431
432 if (!wd) return NULL;
433 if (wd->path) free(wd->path);
434 wd->path = elm_entry_markup_to_utf8(elm_object_text_get(wd->entry));
435 return wd->path;
436}
437
438EAPI void
439elm_fileselector_entry_expandable_set(Evas_Object *obj, Eina_Bool value)
440{
441 ELM_CHECK_WIDTYPE(obj, widtype);
442 Widget_Data *wd = elm_widget_data_get(obj);
443 if (!wd) return;
444 elm_fileselector_button_expandable_set(wd->button, value);
445}
446
447EAPI Eina_Bool
448elm_fileselector_entry_expandable_get(const Evas_Object *obj)
449{
450 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
451 Widget_Data *wd = elm_widget_data_get(obj);
452 if (!wd) return EINA_FALSE;
453 return elm_fileselector_button_expandable_get(wd->button);
454}
455
456EAPI void
457elm_fileselector_entry_folder_only_set(Evas_Object *obj, Eina_Bool value)
458{
459 ELM_CHECK_WIDTYPE(obj, widtype);
460 Widget_Data *wd = elm_widget_data_get(obj);
461 if (!wd) return;
462 elm_fileselector_button_folder_only_set(wd->button, value);
463}
464
465EAPI Eina_Bool
466elm_fileselector_entry_folder_only_get(const Evas_Object *obj)
467{
468 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
469 Widget_Data *wd = elm_widget_data_get(obj);
470 if (!wd) return EINA_FALSE;
471 return elm_fileselector_button_folder_only_get(wd->button);
472}
473
474EAPI void
475elm_fileselector_entry_is_save_set(Evas_Object *obj, Eina_Bool value)
476{
477 ELM_CHECK_WIDTYPE(obj, widtype);
478 Widget_Data *wd = elm_widget_data_get(obj);
479 if (!wd) return;
480 elm_fileselector_button_is_save_set(wd->button, value);
481}
482
483EAPI Eina_Bool
484elm_fileselector_entry_is_save_get(const Evas_Object *obj)
485{
486 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
487 Widget_Data *wd = elm_widget_data_get(obj);
488 if (!wd) return EINA_FALSE;
489 return elm_fileselector_button_is_save_get(wd->button);
490}
491
492EAPI void
493elm_fileselector_entry_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
494{
495 ELM_CHECK_WIDTYPE(obj, widtype);
496 Widget_Data *wd = elm_widget_data_get(obj);
497 if (!wd) return;
498 elm_fileselector_button_inwin_mode_set(wd->button, value);
499}
500
501EAPI Eina_Bool
502elm_fileselector_entry_inwin_mode_get(const Evas_Object *obj)
503{
504 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
505 Widget_Data *wd = elm_widget_data_get(obj);
506 if (!wd) return EINA_FALSE;
507 return elm_fileselector_button_inwin_mode_get(wd->button);
508}
diff --git a/libraries/elementary/src/lib/elc_fileselector_entry.h b/libraries/elementary/src/lib/elc_fileselector_entry.h
new file mode 100644
index 0000000..8703e42
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_fileselector_entry.h
@@ -0,0 +1,349 @@
1/**
2 * @defgroup File_Selector_Entry File Selector Entry
3 * @ingroup Elementary
4 *
5 * @image html img/widget/fileselector_entry/preview-00.png
6 * @image latex img/widget/fileselector_entry/preview-00.eps
7 *
8 * This is an entry made to be filled with or display a <b>file
9 * system path string</b>. Besides the entry itself, the widget has
10 * a @ref File_Selector_Button "file selector button" on its side,
11 * which will raise an internal @ref Fileselector "file selector widget",
12 * when clicked, for path selection aided by file system
13 * navigation.
14 *
15 * This file selector may appear in an Elementary window or in an
16 * inner window. When a file is chosen from it, the (inner) window
17 * is closed and the selected file's path string is exposed both as
18 * a smart event and as the new text on the entry.
19 *
20 * This widget encapsulates operations on its internal file
21 * selector on its own API. There is less control over its file
22 * selector than that one would have instantiating one directly.
23 *
24 * Smart callbacks one can register to:
25 * - @c "changed" - The text within the entry was changed
26 * - @c "activated" - The entry has had editing finished and
27 * changes are to be "committed"
28 * - @c "press" - The entry has been clicked
29 * - @c "longpressed" - The entry has been clicked (and held) for a
30 * couple seconds
31 * - @c "clicked" - The entry has been clicked
32 * - @c "clicked,double" - The entry has been double clicked
33 * - @c "focused" - The entry has received focus
34 * - @c "unfocused" - The entry has lost focus
35 * - @c "selection,paste" - A paste action has occurred on the
36 * entry
37 * - @c "selection,copy" - A copy action has occurred on the entry
38 * - @c "selection,cut" - A cut action has occurred on the entry
39 * - @c "unpressed" - The file selector entry's button was released
40 * after being pressed.
41 * - @c "file,chosen" - The user has selected a path via the file
42 * selector entry's internal file selector, whose string pointer
43 * comes as the @c event_info data (a stringshared string)
44 *
45 * Default text parts of the fileselector_button widget that you can use for
46 * are:
47 * @li "default" - Label of the fileselector_button
48 *
49 * Default content parts of the fileselector_entry widget that you can use for
50 * are:
51 * @li "button icon" - Button icon of the fileselector_entry
52 *
53 * Supported elm_object common APIs.
54 * @li @ref elm_object_part_text_set
55 * @li @ref elm_object_part_text_get
56 * @li @ref elm_object_part_content_set
57 * @li @ref elm_object_part_content_get
58 * @li @ref elm_object_part_content_unset
59 * @li @ref elm_object_disabled_set
60 * @li @ref elm_object_disabled_get
61 *
62 * Here is an example on its usage:
63 * @li @ref fileselector_entry_example
64 *
65 * @see @ref File_Selector_Button for a similar widget.
66 * @{
67 */
68
69/**
70 * Add a new file selector entry widget to the given parent
71 * Elementary (container) object
72 *
73 * @param parent The parent object
74 * @return a new file selector entry widget handle or @c NULL, on
75 * errors
76 *
77 * @ingroup File_Selector_Entry
78 */
79EAPI Evas_Object *elm_fileselector_entry_add(Evas_Object *parent);
80
81/**
82 * Set the title for a given file selector entry widget's window
83 *
84 * @param obj The file selector entry widget
85 * @param title The title string
86 *
87 * This will change the window's title, when the file selector pops
88 * out after a click on the entry's button. Those windows have the
89 * default (unlocalized) value of @c "Select a file" as titles.
90 *
91 * @note It will only take any effect if the file selector
92 * entry widget is @b not under "inwin mode".
93 *
94 * @see elm_fileselector_entry_window_title_get()
95 *
96 * @ingroup File_Selector_Entry
97 */
98EAPI void elm_fileselector_entry_window_title_set(Evas_Object *obj, const char *title);
99
100/**
101 * Get the title set for a given file selector entry widget's
102 * window
103 *
104 * @param obj The file selector entry widget
105 * @return Title of the file selector entry's window
106 *
107 * @see elm_fileselector_entry_window_title_get() for more details
108 *
109 * @ingroup File_Selector_Entry
110 */
111EAPI const char *elm_fileselector_entry_window_title_get(const Evas_Object *obj);
112
113/**
114 * Set the size of a given file selector entry widget's window,
115 * holding the file selector itself.
116 *
117 * @param obj The file selector entry widget
118 * @param width The window's width
119 * @param height The window's height
120 *
121 * @note it will only take any effect if the file selector entry
122 * widget is @b not under "inwin mode". The default size for the
123 * window (when applicable) is 400x400 pixels.
124 *
125 * @see elm_fileselector_entry_window_size_get()
126 *
127 * @ingroup File_Selector_Entry
128 */
129EAPI void elm_fileselector_entry_window_size_set(Evas_Object *obj, Evas_Coord width, Evas_Coord height);
130
131/**
132 * Get the size of a given file selector entry widget's window,
133 * holding the file selector itself.
134 *
135 * @param obj The file selector entry widget
136 * @param width Pointer into which to store the width value
137 * @param height Pointer into which to store the height value
138 *
139 * @note Use @c NULL pointers on the size values you're not
140 * interested in: they'll be ignored by the function.
141 *
142 * @see elm_fileselector_entry_window_size_set(), for more details
143 *
144 * @ingroup File_Selector_Entry
145 */
146EAPI void elm_fileselector_entry_window_size_get(const Evas_Object *obj, Evas_Coord *width, Evas_Coord *height);
147
148/**
149 * Set the initial file system path and the entry's path string for
150 * a given file selector entry widget
151 *
152 * @param obj The file selector entry widget
153 * @param path The path string
154 *
155 * It must be a <b>directory</b> path, which will have the contents
156 * displayed initially in the file selector's view, when invoked
157 * from @p obj. The default initial path is the @c "HOME"
158 * environment variable's value.
159 *
160 * @see elm_fileselector_entry_path_get()
161 *
162 * @ingroup File_Selector_Entry
163 */
164EAPI void elm_fileselector_entry_path_set(Evas_Object *obj, const char *path);
165
166/**
167 * Get the entry's path string for a given file selector entry
168 * widget
169 *
170 * @param obj The file selector entry widget
171 * @return path The path string
172 *
173 * @see elm_fileselector_entry_path_set() for more details
174 *
175 * @ingroup File_Selector_Entry
176 */
177EAPI const char *elm_fileselector_entry_path_get(const Evas_Object *obj);
178
179/**
180 * Enable/disable a tree view in the given file selector entry
181 * widget's internal file selector
182 *
183 * @param obj The file selector entry widget
184 * @param value @c EINA_TRUE to enable tree view, @c EINA_FALSE to disable
185 *
186 * This has the same effect as elm_fileselector_expandable_set(),
187 * but now applied to a file selector entry's internal file
188 * selector.
189 *
190 * @note There's no way to put a file selector entry's internal
191 * file selector in "grid mode", as one may do with "pure" file
192 * selectors.
193 *
194 * @see elm_fileselector_expandable_get()
195 *
196 * @ingroup File_Selector_Entry
197 */
198EAPI void elm_fileselector_entry_expandable_set(Evas_Object *obj, Eina_Bool value);
199
200/**
201 * Get whether tree view is enabled for the given file selector
202 * entry widget's internal file selector
203 *
204 * @param obj The file selector entry widget
205 * @return @c EINA_TRUE if @p obj widget's internal file selector
206 * is in tree view, @c EINA_FALSE otherwise (and or errors)
207 *
208 * @see elm_fileselector_expandable_set() for more details
209 *
210 * @ingroup File_Selector_Entry
211 */
212EAPI Eina_Bool elm_fileselector_entry_expandable_get(const Evas_Object *obj);
213
214/**
215 * Set whether a given file selector entry widget's internal file
216 * selector is to display folders only or the directory contents,
217 * as well.
218 *
219 * @param obj The file selector entry widget
220 * @param value @c EINA_TRUE to make @p obj widget's internal file
221 * selector only display directories, @c EINA_FALSE to make files
222 * to be displayed in it too
223 *
224 * This has the same effect as elm_fileselector_folder_only_set(),
225 * but now applied to a file selector entry's internal file
226 * selector.
227 *
228 * @see elm_fileselector_folder_only_get()
229 *
230 * @ingroup File_Selector_Entry
231 */
232EAPI void elm_fileselector_entry_folder_only_set(Evas_Object *obj, Eina_Bool value);
233
234/**
235 * Get whether a given file selector entry widget's internal file
236 * selector is displaying folders only or the directory contents,
237 * as well.
238 *
239 * @param obj The file selector entry widget
240 * @return @c EINA_TRUE if @p obj widget's internal file
241 * selector is only displaying directories, @c EINA_FALSE if files
242 * are being displayed in it too (and on errors)
243 *
244 * @see elm_fileselector_entry_folder_only_set() for more details
245 *
246 * @ingroup File_Selector_Entry
247 */
248EAPI Eina_Bool elm_fileselector_entry_folder_only_get(const Evas_Object *obj);
249
250/**
251 * Enable/disable the file name entry box where the user can type
252 * in a name for a file, in a given file selector entry widget's
253 * internal file selector.
254 *
255 * @param obj The file selector entry widget
256 * @param value @c EINA_TRUE to make @p obj widget's internal
257 * file selector a "saving dialog", @c EINA_FALSE otherwise
258 *
259 * This has the same effect as elm_fileselector_is_save_set(),
260 * but now applied to a file selector entry's internal file
261 * selector.
262 *
263 * @see elm_fileselector_is_save_get()
264 *
265 * @ingroup File_Selector_Entry
266 */
267EAPI void elm_fileselector_entry_is_save_set(Evas_Object *obj, Eina_Bool value);
268
269/**
270 * Get whether the given file selector entry widget's internal
271 * file selector is in "saving dialog" mode
272 *
273 * @param obj The file selector entry widget
274 * @return @c EINA_TRUE, if @p obj widget's internal file selector
275 * is in "saving dialog" mode, @c EINA_FALSE otherwise (and on
276 * errors)
277 *
278 * @see elm_fileselector_entry_is_save_set() for more details
279 *
280 * @ingroup File_Selector_Entry
281 */
282EAPI Eina_Bool elm_fileselector_entry_is_save_get(const Evas_Object *obj);
283
284/**
285 * Set whether a given file selector entry widget's internal file
286 * selector will raise an Elementary "inner window", instead of a
287 * dedicated Elementary window. By default, it won't.
288 *
289 * @param obj The file selector entry widget
290 * @param value @c EINA_TRUE to make it use an inner window, @c
291 * EINA_TRUE to make it use a dedicated window
292 *
293 * @see elm_win_inwin_add() for more information on inner windows
294 * @see elm_fileselector_entry_inwin_mode_get()
295 *
296 * @ingroup File_Selector_Entry
297 */
298EAPI void elm_fileselector_entry_inwin_mode_set(Evas_Object *obj, Eina_Bool value);
299
300/**
301 * Get whether a given file selector entry widget's internal file
302 * selector will raise an Elementary "inner window", instead of a
303 * dedicated Elementary window.
304 *
305 * @param obj The file selector entry widget
306 * @return @c EINA_TRUE if will use an inner window, @c EINA_TRUE
307 * if it will use a dedicated window
308 *
309 * @see elm_fileselector_entry_inwin_mode_set() for more details
310 *
311 * @ingroup File_Selector_Entry
312 */
313EAPI Eina_Bool elm_fileselector_entry_inwin_mode_get(const Evas_Object *obj);
314
315/**
316 * Set the initial file system path for a given file selector entry
317 * widget
318 *
319 * @param obj The file selector entry widget
320 * @param path The path string
321 *
322 * It must be a <b>directory</b> path, which will have the contents
323 * displayed initially in the file selector's view, when invoked
324 * from @p obj. The default initial path is the @c "HOME"
325 * environment variable's value.
326 *
327 * @see elm_fileselector_entry_path_get()
328 *
329 * @ingroup File_Selector_Entry
330 */
331EAPI void elm_fileselector_entry_selected_set(Evas_Object *obj, const char *path);
332
333/**
334 * Get the parent directory's path to the latest file selection on
335 * a given filer selector entry widget
336 *
337 * @param obj The file selector object
338 * @return The (full) path of the directory of the last selection
339 * on @p obj widget, a @b stringshared string
340 *
341 * @see elm_fileselector_entry_path_set()
342 *
343 * @ingroup File_Selector_Entry
344 */
345EAPI const char *elm_fileselector_entry_selected_get(const Evas_Object *obj);
346
347/**
348 * @}
349 */
diff --git a/libraries/elementary/src/lib/elc_hoversel.c b/libraries/elementary/src/lib/elc_hoversel.c
new file mode 100644
index 0000000..fb07d78
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_hoversel.c
@@ -0,0 +1,507 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Hoversel_Item Elm_Hoversel_Item;
6
7struct _Widget_Data
8{
9 Evas_Object *btn, *hover;
10 Evas_Object *hover_parent;
11 Eina_List *items;
12 Eina_Bool horizontal : 1;
13 Eina_Bool expanded : 1;
14};
15
16struct _Elm_Hoversel_Item
17{
18 ELM_WIDGET_ITEM;
19 const char *label;
20 const char *icon_file;
21 const char *icon_group;
22 Elm_Icon_Type icon_type;
23 Evas_Smart_Cb func;
24};
25
26static const char *widtype = NULL;
27static void _del_pre_hook(Evas_Object *obj);
28static void _del_hook(Evas_Object *obj);
29static void _activate(Evas_Object *obj);
30static void _activate_hook(Evas_Object *obj);
31static void _disable_hook(Evas_Object *obj);
32static void _sizing_eval(Evas_Object *obj);
33static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
34static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
35
36static const char SIG_CLICKED[] = "clicked";
37static const char SIG_SELECTED[] = "selected";
38static const char SIG_DISMISSED[] = "dismissed";
39
40static const Evas_Smart_Cb_Description _signals[] = {
41 {SIG_CLICKED, ""},
42 {SIG_SELECTED, ""},
43 {SIG_DISMISSED, ""},
44 {NULL, NULL}
45};
46
47static void
48_del_pre_hook(Evas_Object *obj)
49{
50 Elm_Hoversel_Item *item;
51 Widget_Data *wd = elm_widget_data_get(obj);
52 if (!wd) return;
53 evas_object_event_callback_del_full(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
54 _changed_size_hints, obj);
55 elm_hoversel_hover_end(obj);
56 elm_hoversel_hover_parent_set(obj, NULL);
57 EINA_LIST_FREE(wd->items, item)
58 {
59 eina_stringshare_del(item->label);
60 eina_stringshare_del(item->icon_file);
61 eina_stringshare_del(item->icon_group);
62 elm_widget_item_free(item);
63 }
64}
65
66static void
67_del_hook(Evas_Object *obj)
68{
69 Widget_Data *wd = elm_widget_data_get(obj);
70 if (!wd) return;
71 free(wd);
72}
73
74static void
75_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
76{
77 Widget_Data *wd = elm_widget_data_get(obj);
78 if (!wd) return;
79 elm_widget_mirrored_set(wd->btn, rtl);
80 elm_widget_mirrored_set(wd->hover, rtl);
81}
82
83static void
84_theme_hook(Evas_Object *obj)
85{
86 Widget_Data *wd = elm_widget_data_get(obj);
87 char buf[4096];
88 if (!wd) return;
89 _elm_widget_mirrored_reload(obj);
90
91 elm_hoversel_hover_end(obj);
92 if (wd->horizontal)
93 snprintf(buf, sizeof(buf), "hoversel_horizontal/%s", elm_widget_style_get(obj));
94 else
95 snprintf(buf, sizeof(buf), "hoversel_vertical/%s", elm_widget_style_get(obj));
96 elm_object_style_set(wd->btn, buf);
97 elm_object_disabled_set(wd->btn, elm_widget_disabled_get(obj));
98 _mirrored_set(obj, elm_widget_mirrored_get(obj));
99}
100
101static void
102_disable_hook(Evas_Object *obj)
103{
104 Widget_Data *wd = elm_widget_data_get(obj);
105 if (!wd) return;
106 elm_object_disabled_set(wd->btn, elm_widget_disabled_get(obj));
107}
108
109static void
110_sizing_eval(Evas_Object *obj)
111{
112 Widget_Data *wd = elm_widget_data_get(obj);
113 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
114 if (!wd) return;
115 evas_object_size_hint_min_get(wd->btn, &minw, &minh);
116 evas_object_size_hint_max_get(wd->btn, &maxw, &maxh);
117 evas_object_size_hint_min_set(obj, minw, minh);
118 evas_object_size_hint_max_set(obj, maxw, maxh);
119}
120
121static void
122_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
123{
124 Widget_Data *wd = elm_widget_data_get(obj);
125 if (!wd) return;
126 if (elm_widget_focus_get(obj))
127 elm_widget_focus_steal(wd->btn);
128}
129
130static void
131_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
132{
133 _sizing_eval(data);
134}
135
136static void
137_hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
138{
139 elm_hoversel_hover_end(data);
140}
141
142static void
143_item_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
144{
145 Elm_Hoversel_Item *item = data;
146 Evas_Object *obj2 = WIDGET(item);
147
148 elm_hoversel_hover_end(obj2);
149 if (item->func) item->func((void *)item->base.data, obj2, item);
150 evas_object_smart_callback_call(obj2, SIG_SELECTED, item);
151}
152
153static void
154_activate(Evas_Object *obj)
155{
156 Widget_Data *wd = elm_widget_data_get(obj);
157 Evas_Object *bt, *bx, *ic;
158 const Eina_List *l;
159 const Elm_Hoversel_Item *item;
160 char buf[4096];
161
162 if (!wd) return;
163 if (wd->expanded)
164 {
165 elm_hoversel_hover_end(obj);
166 return;
167 }
168 wd->expanded = EINA_TRUE;
169
170 if (elm_widget_disabled_get(obj)) return;
171 wd->hover = elm_hover_add(obj);
172 elm_widget_mirrored_automatic_set(wd->hover, EINA_FALSE);
173 if (wd->horizontal)
174 snprintf(buf, sizeof(buf), "hoversel_horizontal/%s", elm_widget_style_get(obj));
175 else
176 snprintf(buf, sizeof(buf), "hoversel_vertical/%s", elm_widget_style_get(obj));
177 elm_object_style_set(wd->hover, buf);
178 evas_object_smart_callback_add(wd->hover, "clicked", _hover_clicked, obj);
179 elm_hover_parent_set(wd->hover, wd->hover_parent);
180 elm_hover_target_set(wd->hover, wd->btn);
181
182 bx = elm_box_add(wd->hover);
183 elm_widget_mirrored_automatic_set(bx, EINA_FALSE);
184 elm_box_homogeneous_set(bx, 1);
185
186 elm_box_horizontal_set(bx, wd->horizontal);
187
188 if (wd->horizontal)
189 snprintf(buf, sizeof(buf), "hoversel_horizontal_entry/%s",
190 elm_widget_style_get(obj));
191 else
192 snprintf(buf, sizeof(buf), "hoversel_vertical_entry/%s",
193 elm_widget_style_get(obj));
194 EINA_LIST_FOREACH(wd->items, l, item)
195 {
196 bt = elm_button_add(wd->hover);
197 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
198 elm_widget_mirrored_set(bt, elm_widget_mirrored_get(obj));
199 elm_object_style_set(bt, buf);
200 elm_object_text_set(bt, item->label);
201 if (item->icon_file)
202 {
203 ic = elm_icon_add(obj);
204 elm_icon_resizable_set(ic, EINA_FALSE, EINA_TRUE);
205 if (item->icon_type == ELM_ICON_FILE)
206 elm_icon_file_set(ic, item->icon_file, item->icon_group);
207 else if (item->icon_type == ELM_ICON_STANDARD)
208 elm_icon_standard_set(ic, item->icon_file);
209 elm_object_part_content_set(bt, "icon", ic);
210 evas_object_show(ic);
211 }
212 evas_object_size_hint_weight_set(bt, EVAS_HINT_EXPAND, 0.0);
213 evas_object_size_hint_align_set(bt, EVAS_HINT_FILL, EVAS_HINT_FILL);
214 elm_box_pack_end(bx, bt);
215 evas_object_smart_callback_add(bt, "clicked", _item_clicked, item);
216 evas_object_show(bt);
217 }
218
219 if (wd->horizontal)
220 elm_object_part_content_set(wd->hover,
221 elm_hover_best_content_location_get(wd->hover,
222 ELM_HOVER_AXIS_HORIZONTAL),
223 bx);
224 else
225 elm_object_part_content_set(wd->hover,
226 elm_hover_best_content_location_get(wd->hover,
227 ELM_HOVER_AXIS_VERTICAL),
228 bx);
229 evas_object_show(bx);
230
231 evas_object_show(wd->hover);
232 evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
233
234 // if (wd->horizontal) evas_object_hide(wd->btn);
235}
236
237static void
238_activate_hook(Evas_Object *obj)
239{
240 _activate(obj);
241}
242
243static void
244_button_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
245{
246 _activate(data);
247}
248
249static void
250_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
251{
252 Widget_Data *wd = elm_widget_data_get(data);
253 if (!wd) return;
254 wd->hover_parent = NULL;
255}
256
257static void
258_elm_hoversel_label_set(Evas_Object *obj, const char *item, const char *label)
259{
260 ELM_CHECK_WIDTYPE(obj, widtype);
261 Widget_Data *wd = elm_widget_data_get(obj);
262 if (item && strcmp(item, "default")) return;
263 if (!wd) return;
264 elm_object_text_set(wd->btn, label);
265}
266
267static const char *
268_elm_hoversel_label_get(const Evas_Object *obj, const char *item)
269{
270 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
271 Widget_Data *wd = elm_widget_data_get(obj);
272 if (item && strcmp(item, "default")) return NULL;
273 if ((!wd) || (!wd->btn)) return NULL;
274 return elm_object_text_get(wd->btn);
275}
276
277static void
278_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
279{
280 ELM_CHECK_WIDTYPE(obj, widtype);
281 Widget_Data *wd = elm_widget_data_get(obj);
282 if (!wd) return;
283
284 elm_object_part_content_set(wd->btn, part, content);
285}
286
287static Evas_Object *
288_content_get_hook(const Evas_Object *obj, const char *part)
289{
290 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
291 Widget_Data *wd = elm_widget_data_get(obj);
292 if ((!wd) || (!wd->btn)) return NULL;
293 return elm_object_part_content_get(wd->btn, part);
294}
295
296static Evas_Object *
297_content_unset_hook(Evas_Object *obj, const char *part)
298{
299 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
300 Widget_Data *wd = elm_widget_data_get(obj);
301 if ((!wd) || (!wd->btn)) return NULL;
302 return elm_object_part_content_unset(wd->btn, part);
303}
304
305static const char *
306_item_text_get_hook(const Elm_Object_Item *it, const char *part)
307{
308 if (part && strcmp(part, "default")) return NULL;
309 return ((Elm_Hoversel_Item *)it)->label;
310}
311
312static Eina_Bool
313_item_del_pre_hook(Elm_Object_Item *it)
314{
315 Widget_Data *wd;
316 Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
317 wd = elm_widget_data_get(WIDGET(item));
318 if (!wd) return EINA_FALSE;
319 elm_hoversel_hover_end(WIDGET(item));
320 wd->items = eina_list_remove(wd->items, item);
321 eina_stringshare_del(item->label);
322 eina_stringshare_del(item->icon_file);
323 eina_stringshare_del(item->icon_group);
324
325 return EINA_TRUE;
326}
327
328EAPI Evas_Object *
329elm_hoversel_add(Evas_Object *parent)
330{
331 Evas_Object *obj;
332 Evas *e;
333 Widget_Data *wd;
334
335 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
336
337 ELM_SET_WIDTYPE(widtype, "hoversel");
338 elm_widget_type_set(obj, "hoversel");
339 elm_widget_sub_object_add(parent, obj);
340 elm_widget_data_set(obj, wd);
341 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
342 elm_widget_del_hook_set(obj, _del_hook);
343 elm_widget_theme_hook_set(obj, _theme_hook);
344 elm_widget_disable_hook_set(obj, _disable_hook);
345 elm_widget_activate_hook_set(obj, _activate_hook);
346 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
347 elm_widget_can_focus_set(obj, EINA_TRUE);
348 elm_widget_text_set_hook_set(obj, _elm_hoversel_label_set);
349 elm_widget_text_get_hook_set(obj, _elm_hoversel_label_get);
350 elm_widget_content_set_hook_set(obj, _content_set_hook);
351 elm_widget_content_get_hook_set(obj, _content_get_hook);
352 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
353
354 wd->btn = elm_button_add(parent);
355 elm_widget_mirrored_automatic_set(wd->btn, EINA_FALSE);
356 wd->expanded = EINA_FALSE;
357 elm_widget_resize_object_set(obj, wd->btn);
358 evas_object_event_callback_add(wd->btn, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
359 _changed_size_hints, obj);
360 evas_object_smart_callback_add(wd->btn, "clicked", _button_clicked, obj);
361 evas_object_smart_callbacks_descriptions_set(obj, _signals);
362
363 elm_widget_sub_object_add(obj, wd->btn);
364
365 elm_hoversel_hover_parent_set(obj, parent);
366 _theme_hook(obj);
367
368 return obj;
369}
370
371EAPI void
372elm_hoversel_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
373{
374 ELM_CHECK_WIDTYPE(obj, widtype);
375 Widget_Data *wd = elm_widget_data_get(obj);
376 if (!wd) return;
377 if (wd->hover_parent)
378 evas_object_event_callback_del_full(wd->hover_parent, EVAS_CALLBACK_DEL,
379 _parent_del, obj);
380 wd->hover_parent = parent;
381 if (wd->hover_parent)
382 evas_object_event_callback_add(wd->hover_parent, EVAS_CALLBACK_DEL,
383 _parent_del, obj);
384}
385
386EAPI Evas_Object *
387elm_hoversel_hover_parent_get(const Evas_Object *obj)
388{
389 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
390 Widget_Data *wd = elm_widget_data_get(obj);
391 if (!wd) return NULL;
392 return wd->hover_parent;
393}
394
395EAPI void
396elm_hoversel_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
397{
398 ELM_CHECK_WIDTYPE(obj, widtype);
399 Widget_Data *wd = elm_widget_data_get(obj);
400 if (!wd) return;
401 wd->horizontal = !!horizontal;
402}
403
404EAPI Eina_Bool
405elm_hoversel_horizontal_get(const Evas_Object *obj)
406{
407 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
408 Widget_Data *wd = elm_widget_data_get(obj);
409 if (!wd) return EINA_FALSE;
410 return wd->horizontal;
411}
412
413EAPI void
414elm_hoversel_hover_begin(Evas_Object *obj)
415{
416 ELM_CHECK_WIDTYPE(obj, widtype);
417 Widget_Data *wd = elm_widget_data_get(obj);
418 if (!wd) return;
419 if (wd->hover) return;
420 _activate(obj);
421}
422
423EAPI void
424elm_hoversel_hover_end(Evas_Object *obj)
425{
426 ELM_CHECK_WIDTYPE(obj, widtype);
427 Widget_Data *wd = elm_widget_data_get(obj);
428 if (!wd) return;
429 if (!wd->hover) return;
430 wd->expanded = EINA_FALSE;
431 evas_object_del(wd->hover);
432 wd->hover = NULL;
433 evas_object_smart_callback_call(obj, SIG_DISMISSED, NULL);
434}
435
436EAPI Eina_Bool
437elm_hoversel_expanded_get(const Evas_Object *obj)
438{
439 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
440 Widget_Data *wd = elm_widget_data_get(obj);
441 if (!wd) return EINA_FALSE;
442 return (wd->hover) ? EINA_TRUE : EINA_FALSE;
443}
444
445EAPI void
446elm_hoversel_clear(Evas_Object *obj)
447{
448 Elm_Object_Item *it;
449 Eina_List *l, *ll;
450 ELM_CHECK_WIDTYPE(obj, widtype);
451 Widget_Data *wd = elm_widget_data_get(obj);
452 if (!wd) return;
453 EINA_LIST_FOREACH_SAFE(wd->items, l, ll, it)
454 {
455 _item_del_pre_hook(it);
456 elm_widget_item_free(it);
457 }
458}
459
460EAPI const Eina_List *
461elm_hoversel_items_get(const Evas_Object *obj)
462{
463 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
464 Widget_Data *wd = elm_widget_data_get(obj);
465 if (!wd) return NULL;
466 return wd->items;
467}
468
469EAPI Elm_Object_Item *
470elm_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)
471{
472 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
473 Widget_Data *wd = elm_widget_data_get(obj);
474 if (!wd) return NULL;
475 Elm_Hoversel_Item *item = elm_widget_item_new(obj, Elm_Hoversel_Item);
476 if (!item) return NULL;
477 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
478 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
479 wd->items = eina_list_append(wd->items, item);
480 item->label = eina_stringshare_add(label);
481 item->icon_file = eina_stringshare_add(icon_file);
482 item->icon_type = icon_type;
483 item->func = func;
484 item->base.data = data;
485 return (Elm_Object_Item *)item;
486}
487
488EAPI void
489elm_hoversel_item_icon_set(Elm_Object_Item *it, const char *icon_file, const char *icon_group, Elm_Icon_Type icon_type)
490{
491 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
492 Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
493 eina_stringshare_replace(&item->icon_file, icon_file);
494 eina_stringshare_replace(&item->icon_group, icon_group);
495 item->icon_type = icon_type;
496}
497
498EAPI void
499elm_hoversel_item_icon_get(const Elm_Object_Item *it, const char **icon_file, const char **icon_group, Elm_Icon_Type *icon_type)
500{
501 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
502 Elm_Hoversel_Item *item = (Elm_Hoversel_Item *)it;
503 if (icon_file) *icon_file = item->icon_file;
504 if (icon_group) *icon_group = item->icon_group;
505 if (icon_type) *icon_type = item->icon_type;
506}
507
diff --git a/libraries/elementary/src/lib/elc_hoversel.h b/libraries/elementary/src/lib/elc_hoversel.h
new file mode 100644
index 0000000..1f60849
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_hoversel.h
@@ -0,0 +1,224 @@
1/**
2 * @defgroup Hoversel Hoversel
3 * @ingroup Elementary
4 *
5 * @image html img/widget/hoversel/preview-00.png
6 * @image latex img/widget/hoversel/preview-00.eps
7 *
8 * A hoversel is a button that pops up a list of items (automatically
9 * choosing the direction to display) that have a label and, optionally, an
10 * icon to select from. It is a convenience widget to avoid the need to do
11 * all the piecing together yourself. It is intended for a small number of
12 * items in the hoversel menu (no more than 8), though is capable of many
13 * more.
14 *
15 * Signals that you can add callbacks for are:
16 * "clicked" - the user clicked the hoversel button and popped up the sel
17 * "selected" - an item in the hoversel list is selected. event_info is the item
18 * "dismissed" - the hover is dismissed
19 *
20 * Default content parts of the hoversel widget that you can use for are:
21 * @li "icon" - An icon of the hoversel
22 *
23 * Default text parts of the hoversel widget that you can use for are:
24 * @li "default" - Label of the hoversel
25 *
26 * Supported elm_object common APIs.
27 * @li @ref elm_object_disabled_set
28 * @li @ref elm_object_disabled_get
29 * @li @ref elm_object_part_text_set
30 * @li @ref elm_object_part_text_get
31 * @li @ref elm_object_part_content_set
32 * @li @ref elm_object_part_content_unset
33 *
34 * Supported elm_object_item common APIs.
35 * @li elm_object_item_part_text_get
36 *
37 * See @ref tutorial_hoversel for an example.
38 * @{
39 */
40
41/**
42 * @brief Add a new Hoversel object
43 *
44 * @param parent The parent object
45 * @return The new object or NULL if it cannot be created
46 *
47 * @ingroup Hoversel
48 */
49EAPI Evas_Object *elm_hoversel_add(Evas_Object *parent);
50
51/**
52 * @brief This sets the hoversel to expand horizontally.
53 *
54 * @param obj The hoversel object
55 * @param horizontal If true, the hover will expand horizontally to the
56 * right.
57 *
58 * @note The initial button will display horizontally regardless of this
59 * setting.
60 *
61 * @ingroup Hoversel
62 */
63EAPI void elm_hoversel_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
64
65/**
66 * @brief This returns whether the hoversel is set to expand horizontally.
67 *
68 * @param obj The hoversel object
69 * @return If true, the hover will expand horizontally to the right.
70 *
71 * @see elm_hoversel_horizontal_set()
72 *
73 * @ingroup Hoversel
74 */
75EAPI Eina_Bool elm_hoversel_horizontal_get(const Evas_Object *obj);
76
77/**
78 * @brief Set the Hover parent
79 *
80 * @param obj The hoversel object
81 * @param parent The parent to use
82 *
83 * Sets the hover parent object, the area that will be darkened when the
84 * hoversel is clicked. Should probably be the window that the hoversel is
85 * in. See @ref Hover objects for more information.
86 *
87 * @ingroup Hoversel
88 */
89EAPI void elm_hoversel_hover_parent_set(Evas_Object *obj, Evas_Object *parent);
90
91/**
92 * @brief Get the Hover parent
93 *
94 * @param obj The hoversel object
95 * @return The used parent
96 *
97 * Gets the hover parent object.
98 *
99 * @see elm_hoversel_hover_parent_set()
100 *
101 * @ingroup Hoversel
102 */
103EAPI Evas_Object *elm_hoversel_hover_parent_get(const Evas_Object *obj);
104
105/**
106 * @brief This triggers the hoversel popup from code, the same as if the user
107 * had clicked the button.
108 *
109 * @param obj The hoversel object
110 *
111 * @ingroup Hoversel
112 */
113EAPI void elm_hoversel_hover_begin(Evas_Object *obj);
114
115/**
116 * @brief This dismisses the hoversel popup as if the user had clicked
117 * outside the hover.
118 *
119 * @param obj The hoversel object
120 *
121 * @ingroup Hoversel
122 */
123EAPI void elm_hoversel_hover_end(Evas_Object *obj);
124
125/**
126 * @brief Returns whether the hoversel is expanded.
127 *
128 * @param obj The hoversel object
129 * @return This will return EINA_TRUE if the hoversel is expanded or
130 * EINA_FALSE if it is not expanded.
131 *
132 * @ingroup Hoversel
133 */
134EAPI Eina_Bool elm_hoversel_expanded_get(const Evas_Object *obj);
135
136/**
137 * @brief This will remove all the children items from the hoversel.
138 *
139 * @param obj The hoversel object
140 *
141 * @warning Should @b not be called while the hoversel is active; use
142 * elm_hoversel_expanded_get() to check first.
143 *
144 * @see elm_object_item_del()
145 *
146 * @ingroup Hoversel
147 */
148EAPI void elm_hoversel_clear(Evas_Object *obj);
149
150/**
151 * @brief Get the list of items within the given hoversel.
152 *
153 * @param obj The hoversel object
154 * @return Returns a list of Elm_Object_Item*
155 *
156 * @see elm_hoversel_item_add()
157 *
158 * @ingroup Hoversel
159 */
160EAPI const Eina_List *elm_hoversel_items_get(const Evas_Object *obj);
161
162/**
163 * @brief Add an item to the hoversel button
164 *
165 * @param obj The hoversel object
166 * @param label The text label to use for the item (NULL if not desired)
167 * @param icon_file An image file path on disk to use for the icon or standard
168 * icon name (NULL if not desired)
169 * @param icon_type The icon type if relevant
170 * @param func Convenience function to call when this item is selected
171 * @param data Data to pass to item-related functions
172 * @return A handle to the item added.
173 *
174 * This adds an item to the hoversel to show when it is clicked. Note: if you
175 * need to use an icon from an edje file then use
176 * elm_hoversel_item_icon_set() right after this function, and set
177 * icon_file to NULL here.
178 *
179 * For more information on what @p icon_file and @p icon_type are, see the
180 * @ref Icon "icon documentation".
181 *
182 * @ingroup Hoversel
183 */
184EAPI Elm_Object_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);
185
186/**
187 * @brief This sets the icon for the given hoversel item.
188 *
189 * @param it The item to set the icon
190 * @param icon_file An image file path on disk to use for the icon or standard
191 * icon name
192 * @param icon_group The edje group to use if @p icon_file is an edje file. Set this
193 * to NULL if the icon is not an edje file
194 * @param icon_type The icon type
195 *
196 * The icon can be loaded from the standard set, from an image file, or from
197 * an edje file.
198 *
199 * @see elm_hoversel_item_add()
200 *
201 * @ingroup Hoversel
202 */
203EAPI void elm_hoversel_item_icon_set(Elm_Object_Item *it, const char *icon_file, const char *icon_group, Elm_Icon_Type icon_type);
204
205/**
206 * @brief Get the icon object of the hoversel item
207 *
208 * @param it The item to get the icon from
209 * @param icon_file The image file path on disk used for the icon or standard
210 * icon name
211 * @param icon_group The edje group used if @p icon_file is an edje file. NULL
212 * if the icon is not an edje file
213 * @param icon_type The icon type
214 *
215 * @see elm_hoversel_item_icon_set()
216 * @see elm_hoversel_item_add()
217 *
218 * @ingroup Hoversel
219 */
220EAPI void elm_hoversel_item_icon_get(const Elm_Object_Item *it, const char **icon_file, const char **icon_group, Elm_Icon_Type *icon_type);
221
222/**
223 * @}
224 */
diff --git a/libraries/elementary/src/lib/elc_multibuttonentry.c b/libraries/elementary/src/lib/elc_multibuttonentry.c
new file mode 100644
index 0000000..c9ab83c
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_multibuttonentry.c
@@ -0,0 +1,1742 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define MAX_STR 256
5#define MIN_W_ENTRY 10
6
7typedef enum _Multibuttonentry_Pos
8 {
9 MULTIBUTTONENTRY_POS_START,
10 MULTIBUTTONENTRY_POS_END,
11 MULTIBUTTONENTRY_POS_BEFORE,
12 MULTIBUTTONENTRY_POS_AFTER,
13 } Multibuttonentry_Pos;
14
15typedef enum _Multibuttonentry_Button_State
16 {
17 MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT,
18 MULTIBUTTONENTRY_BUTTON_STATE_SELECTED,
19 } Multibuttonentry_Button_State;
20
21
22typedef enum _MultiButtonEntry_Closed_Button_Type
23 {
24 MULTIBUTTONENTRY_CLOSED_IMAGE,
25 MULTIBUTTONENTRY_CLOSED_LABEL
26 } MultiButtonEntry_Closed_Button_Type;
27
28typedef enum _Multibuttonentry_View_State
29 {
30 MULTIBUTTONENTRY_VIEW_NONE,
31 MULTIBUTTONENTRY_VIEW_GUIDETEXT,
32 MULTIBUTTONENTRY_VIEW_ENTRY,
33 MULTIBUTTONENTRY_VIEW_SHRINK
34 } Multibuttonentry_View_State;
35
36typedef struct _Widget_Data Widget_Data;
37typedef struct _Multibuttonentry_Item Elm_Multibuttonentry_Item;
38
39struct _Multibuttonentry_Item
40 {
41 ELM_WIDGET_ITEM;
42 Evas_Object *button;
43 Evas_Coord vw, rw; // vw: visual width, real width
44 Eina_Bool visible: 1;
45 Evas_Smart_Cb func;
46 };
47
48typedef struct _Elm_Multibuttonentry_Item_Filter
49 {
50 Elm_Multibuttonentry_Item_Filter_Cb callback_func;
51 void *data;
52 } Elm_Multibuttonentry_Item_Filter;
53
54struct _Widget_Data
55 {
56 Evas_Object *base;
57 Evas_Object *box;
58 Evas_Object *entry;
59 Evas_Object *label;
60 Evas_Object *guidetext;
61 Evas_Object *end; // used to represent the total number of invisible buttons
62
63 Evas_Object *rect_for_end;
64 MultiButtonEntry_Closed_Button_Type end_type;
65
66 Eina_List *items;
67 Eina_List *filter_list;
68 Elm_Object_Item *selected_it; /* selected item */
69
70 const char *labeltxt, *guidetexttxt;
71
72 int n_str;
73 Multibuttonentry_View_State view_state;
74
75 Evas_Coord w_box, h_box;
76 int shrink;
77 Eina_Bool focused: 1;
78 Eina_Bool last_btn_select: 1;
79 Elm_Multibuttonentry_Item_Filter_Cb add_callback;
80 void *add_callback_data;
81 };
82
83static void _del_hook(Evas_Object *obj);
84static void _theme_hook(Evas_Object *obj);
85static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
86static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info);
87static void _sizing_eval(Evas_Object *obj);
88static void _changed_size_hint_cb(void *data, Evas *evas, Evas_Object *obj, void *event);
89static void _resize_cb(void *data, Evas *evas, Evas_Object *obj, void *event);
90static void _event_init(Evas_Object *obj);
91static void _shrink_mode_set(Evas_Object *obj, Eina_Bool shrink);
92static void _view_update(Evas_Object *obj);
93static void _set_label(Evas_Object *obj, const char *str);
94static void _change_current_button_state(Evas_Object *obj, Multibuttonentry_Button_State state);
95static void _change_current_button(Evas_Object *obj, Evas_Object *btn);
96static void _button_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
97static void _del_button_obj(Evas_Object *obj, Evas_Object *btn);
98static void _del_button_item(Elm_Multibuttonentry_Item *item);
99static void _select_button(Evas_Object *obj, Evas_Object *btn);
100static Elm_Object_Item *_add_button_item(Evas_Object *obj, const char *str, Multibuttonentry_Pos pos, const void *ref, Evas_Smart_Cb func, void *data);
101static void _evas_mbe_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
102static void _entry_changed_cb(void *data, Evas_Object *obj, void *event_info);
103static void _entry_key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
104static void _entry_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
105static void _entry_resized_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
106static void _entry_focus_in_cb(void *data, Evas_Object *obj, void *event_info);
107static void _entry_focus_out_cb(void *data, Evas_Object *obj, void *event_info);
108static void _entry_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__);
109static void _view_init(Evas_Object *obj);
110static void _set_vis_guidetext(Evas_Object *obj);
111static void _calculate_box_min_size(Evas_Object *box, Evas_Object_Box_Data *priv);
112static Evas_Coord _calculate_item_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index);
113static void _box_layout_cb(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
114static void _item_text_set_hook(Elm_Object_Item *it,
115 const char *part,
116 const char *label);
117static const char *_item_text_get_hook(const Elm_Object_Item *it,
118 const char *part);
119
120static const char *widtype = NULL;
121
122//widget signals
123static const char SIG_ITEM_SELECTED[] = "item,selected";
124static const char SIG_ITEM_ADDED[] = "item,added";
125static const char SIG_ITEM_DELETED[] = "item,deleted";
126static const char SIG_ITEM_CLICKED[] = "item,clicked";
127static const char SIG_CLICKED[] = "clicked";
128static const char SIG_FOCUSED[] = "focused";
129static const char SIG_UNFOCUSED[] = "unfocused";
130static const char SIG_EXPANDED[] = "expanded";
131static const char SIG_CONTRACTED[] = "contracted";
132static const char SIG_EXPAND_STATE_CHANGED[] = "expand,state,changed";
133
134static const Evas_Smart_Cb_Description _signals[] = {
135 {SIG_ITEM_SELECTED, ""},
136 {SIG_ITEM_ADDED, ""},
137 {SIG_ITEM_DELETED, ""},
138 {SIG_ITEM_CLICKED, ""},
139 {SIG_CLICKED, ""},
140 {SIG_FOCUSED, ""},
141 {SIG_UNFOCUSED, ""},
142 {SIG_EXPANDED, ""},
143 {SIG_CONTRACTED, ""},
144 {SIG_EXPAND_STATE_CHANGED, ""},
145 {NULL, NULL}
146};
147
148static void
149_del_hook(Evas_Object *obj)
150{
151 Widget_Data *wd = elm_widget_data_get(obj);
152
153 if (!wd) return;
154 if (wd->items)
155 {
156 Elm_Multibuttonentry_Item *item;
157 EINA_LIST_FREE(wd->items, item)
158 {
159 _del_button_obj(obj, item->button);
160 free(item);
161 }
162 wd->items = NULL;
163 }
164 wd->selected_it = NULL;
165
166 if (wd->labeltxt) eina_stringshare_del(wd->labeltxt);
167 if (wd->guidetexttxt) eina_stringshare_del(wd->guidetexttxt);
168 if (wd->entry) evas_object_del(wd->entry);
169 if (wd->label) evas_object_del(wd->label);
170 if (wd->guidetext) evas_object_del(wd->guidetext);
171 if (wd->end) evas_object_del(wd->end);
172 if (wd->rect_for_end) evas_object_del(wd->rect_for_end);
173}
174
175static void
176_theme_hook(Evas_Object *obj)
177{
178 Widget_Data *wd = elm_widget_data_get(obj);
179 Eina_List *l;
180 Elm_Multibuttonentry_Item *item;
181
182 if (!wd) return;
183
184 _elm_theme_object_set(obj, wd->base, "multibuttonentry", "base", elm_widget_style_get(obj));
185 if (wd->box) edje_object_part_swallow(wd->base, "box.swallow", wd->box);
186 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
187
188 EINA_LIST_FOREACH(wd->items, l, item)
189 {
190 if (item->button)
191 _elm_theme_object_set(obj, item->button, "multibuttonentry", "btn", elm_widget_style_get(obj));
192 edje_object_scale_set(item->button, elm_widget_scale_get(obj) * _elm_config->scale);
193 }
194
195 _sizing_eval(obj);
196}
197
198static void
199_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
200{
201 Widget_Data *wd = elm_widget_data_get(obj);
202
203 if (!wd) return;
204
205 if (elm_widget_focus_get(obj))
206 {
207 if ((wd->selected_it))
208 {
209 elm_entry_input_panel_show(wd->entry);
210 }
211 else if (((!wd->selected_it) || (!eina_list_count(wd->items))))
212 {
213 if (wd->entry) elm_entry_cursor_end_set(wd->entry);
214 _view_update(obj);
215 elm_entry_input_panel_show(wd->entry);
216 }
217 wd->focused = EINA_TRUE;
218 evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
219 }
220 else
221 {
222 wd->focused = EINA_FALSE;
223 _view_update(obj);
224
225 elm_entry_input_panel_hide(wd->entry);
226 evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
227 }
228}
229
230static Eina_Bool
231_event_hook(Evas_Object *obj __UNUSED__, Evas_Object *src __UNUSED__, Evas_Callback_Type type __UNUSED__, void *event_info __UNUSED__)
232{
233 return EINA_TRUE;
234}
235
236static void
237_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
238{
239 Widget_Data *wd = elm_widget_data_get(obj);
240
241 if (!wd) return;
242 edje_object_signal_emit(wd->base, emission, source);
243}
244
245static void
246_sizing_eval(Evas_Object *obj)
247{
248 Widget_Data *wd = elm_widget_data_get(obj);
249 Evas_Coord minw = -1, minh = -1;
250 Evas_Coord left, right, top, bottom;
251
252 if (!wd) return;
253 evas_object_size_hint_min_get(wd->box, &minw, &minh);
254 edje_object_part_geometry_get(wd->base, "top.left.pad", NULL, NULL, &left, &top);
255 edje_object_part_geometry_get(wd->base, "bottom.right.pad", NULL, NULL, &right, &bottom);
256
257 minw += (left + right);
258 minh += (top + bottom);
259
260 evas_object_size_hint_min_set(obj, minw, minh);
261}
262
263static void
264_signal_mouse_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
265{
266 Widget_Data *wd = elm_widget_data_get(data);
267
268 if (!wd || !wd->base) return;
269 wd->focused = EINA_TRUE;
270 _view_update(data);
271
272 elm_entry_input_panel_show(wd->entry);
273
274 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
275}
276
277static void
278_changed_size_hint_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
279{
280 Evas_Object *eo = (Evas_Object *)data;
281 Widget_Data *wd = elm_widget_data_get(data);
282
283 if (!wd) return;
284 _sizing_eval(eo);
285}
286
287static void
288_resize_cb(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
289{
290 Widget_Data *wd = elm_widget_data_get(data);
291 Evas_Coord w, h;
292
293 if (!wd) return;
294 evas_object_geometry_get(wd->box, NULL, NULL, &w, &h);
295
296 if (wd->h_box < h) evas_object_smart_callback_call(data, SIG_EXPANDED, NULL);
297 else if (wd->h_box > h)
298 evas_object_smart_callback_call(data, SIG_CONTRACTED, NULL);
299
300 wd->w_box = w;
301 wd->h_box = h;
302
303 _view_update(data);
304}
305
306static void
307_event_init(Evas_Object *obj)
308{
309 Widget_Data *wd = elm_widget_data_get(obj);
310
311 if (!wd || !wd->base) return;
312 if (wd->base)
313 {
314 edje_object_signal_callback_add(wd->base, "mouse,clicked,1", "*", _signal_mouse_clicked, obj);
315 evas_object_event_callback_add(wd->base, EVAS_CALLBACK_KEY_UP, _evas_mbe_key_up_cb, obj);
316 }
317
318 if (wd->box)
319 {
320 evas_object_event_callback_add(wd->box, EVAS_CALLBACK_RESIZE, _resize_cb, obj);
321 evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hint_cb, obj);
322 }
323
324 if (wd->entry)
325 {
326 evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_KEY_UP, _entry_key_up_cb, obj);
327 evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_KEY_DOWN, _entry_key_down_cb, obj);
328 evas_object_event_callback_add(wd->entry, EVAS_CALLBACK_RESIZE, _entry_resized_cb, obj);
329 evas_object_smart_callback_add(wd->entry, "changed", _entry_changed_cb, obj);
330 evas_object_smart_callback_add(wd->entry, "focused", _entry_focus_in_cb, obj);
331 evas_object_smart_callback_add(wd->entry, "unfocused", _entry_focus_out_cb, obj);
332 evas_object_smart_callback_add(wd->entry, "clicked", _entry_clicked_cb, obj);
333 }
334}
335
336static void
337_set_vis_guidetext(Evas_Object *obj)
338{
339 Widget_Data *wd = elm_widget_data_get(obj);
340
341 if (!wd) return;
342 elm_box_unpack(wd->box, wd->guidetext);
343 elm_box_unpack(wd->box, wd->entry);
344 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) return;
345
346 if (!wd->focused)
347 elm_object_focus_set(wd->entry, EINA_FALSE);
348
349 if (wd && (!eina_list_count(wd->items)) && wd->guidetext
350 && (!elm_widget_focus_get(obj)) && (!wd->focused) && (!wd->n_str))
351 {
352 evas_object_hide(wd->entry);
353 elm_box_pack_end(wd->box, wd->guidetext);
354 evas_object_show(wd->guidetext);
355 wd->view_state = MULTIBUTTONENTRY_VIEW_GUIDETEXT;
356 }
357 else
358 {
359 evas_object_hide(wd->guidetext);
360 elm_box_pack_end(wd->box, wd->entry);
361 evas_object_show(wd->entry);
362 if (elm_widget_focus_get(obj) || wd->focused)
363 if (!wd->selected_it)
364 elm_object_focus_set(wd->entry, EINA_TRUE);
365 wd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
366 }
367}
368
369static void
370_shrink_mode_set(Evas_Object *obj, Eina_Bool shrink)
371{
372 Widget_Data *wd = elm_widget_data_get(obj);
373 Eina_List *l;
374 Elm_Multibuttonentry_Item *item;
375
376 if (!wd || !wd->box) return;
377 if (wd->view_state == MULTIBUTTONENTRY_VIEW_ENTRY)
378 evas_object_hide(wd->entry);
379 else if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
380 evas_object_hide(wd->guidetext);
381 else if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
382 {
383 evas_object_hide(wd->rect_for_end);
384 evas_object_hide(wd->end);
385 wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
386 }
387
388 if (shrink == EINA_TRUE)
389 {
390 Evas_Coord w = 0, w_tmp = 0;
391 Evas_Coord box_inner_item_width_padding = 0;
392
393 elm_box_padding_get(wd->box, &box_inner_item_width_padding, NULL);
394 // unpack all items and entry
395 elm_box_unpack_all(wd->box);
396 EINA_LIST_FOREACH(wd->items, l, item)
397 {
398 if (item)
399 {
400 evas_object_hide(item->button);
401 item->visible = EINA_FALSE;
402 }
403 }
404 // pack buttons only 1line
405 w = wd->w_box;
406
407 if (wd->label)
408 {
409 elm_box_pack_end(wd->box, wd->label);
410 evas_object_size_hint_min_get(wd->label, &w_tmp, NULL);
411 w -= w_tmp;
412 w -= box_inner_item_width_padding;
413 }
414
415 item = NULL;
416 int count = eina_list_count(wd->items);
417 Evas_Coord button_min_width = 0;
418 /* Evas_Coord button_min_height = 0; */
419 if (wd->end_type == MULTIBUTTONENTRY_CLOSED_IMAGE)
420 {
421 const char *size_str;
422 size_str = edje_object_data_get(wd->end, "closed_button_width");
423 if (size_str) button_min_width = (Evas_Coord)atoi(size_str);
424 /* it use for later
425 size_str = edje_object_data_get(wd->end, "closed_button_height");
426 if (size_str) button_min_width = (Evas_Coord)atoi(size_str);
427 */
428 }
429
430 EINA_LIST_FOREACH(wd->items, l, item)
431 {
432 if (item)
433 {
434 int w_label_count = 0;
435 char buf[MAX_STR];
436
437 elm_box_pack_end(wd->box, item->button);
438 evas_object_show(item->button);
439 item->visible = EINA_TRUE;
440
441 w -= item->vw;
442 w -= box_inner_item_width_padding;
443 count--;
444
445 if (wd->end_type == MULTIBUTTONENTRY_CLOSED_LABEL)
446 {
447 if (count > 0)
448 {
449 snprintf(buf, sizeof(buf), "... + %d", count);
450 elm_object_text_set(wd->end, buf);
451 evas_object_size_hint_min_get(wd->end, &w_label_count, NULL);
452 }
453
454 if (w < 0 || w < w_label_count)
455 {
456 elm_box_unpack(wd->box, item->button);
457 evas_object_hide(item->button);
458 item->visible = EINA_FALSE;
459
460 count++;
461 snprintf(buf, sizeof(buf), "... + %d", count);
462 elm_object_text_set(wd->end, buf);
463 evas_object_size_hint_min_get(wd->end, &w_label_count, NULL);
464
465 elm_box_pack_end(wd->box, wd->end);
466 evas_object_show(wd->end);
467
468 wd->view_state = MULTIBUTTONENTRY_VIEW_SHRINK;
469 evas_object_smart_callback_call(obj, SIG_EXPAND_STATE_CHANGED, (void *)1);
470 break;
471 }
472 }
473 else if (wd->end_type == MULTIBUTTONENTRY_CLOSED_IMAGE)
474 {
475 if (w < button_min_width)
476 {
477 Evas_Coord rectSize;
478 Evas_Coord closed_height = 0;
479 const char *height_str = edje_object_data_get(wd->base, "closed_height");
480
481 if (height_str) closed_height = (Evas_Coord)atoi(height_str);
482 elm_box_unpack(wd->box, item->button);
483 evas_object_hide(item->button);
484 item->visible = EINA_FALSE;
485
486 w += item->vw;
487 rectSize = w - button_min_width;
488 if (!wd->rect_for_end)
489 {
490 Evas *e = evas_object_evas_get(obj);
491 wd->rect_for_end = evas_object_rectangle_add(e);
492 evas_object_color_set(wd->rect_for_end, 0, 0, 0, 0);
493 }
494 evas_object_size_hint_min_set(wd->rect_for_end, rectSize, closed_height * _elm_config->scale);
495 elm_box_pack_end(wd->box, wd->rect_for_end);
496 evas_object_show(wd->rect_for_end);
497
498 elm_box_pack_end(wd->box, wd->end);
499 evas_object_show(wd->end);
500
501 wd->view_state = MULTIBUTTONENTRY_VIEW_SHRINK;
502 evas_object_smart_callback_call(obj, SIG_EXPAND_STATE_CHANGED, (void *)0);
503 break;
504 }
505 }
506 }
507 }
508 }
509 else
510 {
511 // unpack all items and entry
512 elm_box_unpack_all(wd->box);
513 EINA_LIST_FOREACH(wd->items, l, item)
514 {
515 if (item)
516 {
517 evas_object_hide(item->button);
518 item->visible = EINA_FALSE;
519 }
520 }
521 evas_object_hide(wd->end);
522
523 if (wd->rect_for_end) evas_object_hide(wd->rect_for_end);
524
525 // pack buttons only 1line
526
527 if (wd->label) elm_box_pack_end(wd->box, wd->label);
528
529 // pack remain btns
530 item = NULL;
531 EINA_LIST_FOREACH(wd->items, l, item)
532 {
533 if (item)
534 {
535 elm_box_pack_end(wd->box, item->button);
536 evas_object_show(item->button);
537 item->visible = EINA_TRUE;
538 }
539 }
540
541 wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
542 evas_object_smart_callback_call(obj, SIG_EXPAND_STATE_CHANGED,
543 (void *)(long)wd->shrink);
544 }
545 if (wd->view_state != MULTIBUTTONENTRY_VIEW_SHRINK)
546 {
547 _set_vis_guidetext(obj);
548 }
549}
550
551static void
552_view_update(Evas_Object *obj)
553{
554 Evas_Coord width = 1, height = 1;
555 Widget_Data *wd = elm_widget_data_get(obj);
556
557 if (!wd || !wd->box || !wd->entry || !(wd->w_box > 0)) return;
558
559 // update label
560 if (wd->label)
561 {
562 elm_box_unpack(wd->box, wd->label);
563 elm_box_pack_start(wd->box, wd->label);
564 evas_object_size_hint_min_get(wd->label, &width, &height);
565 }
566
567 if (wd->guidetext)
568 {
569 Evas_Coord guide_text_width = wd->w_box - width;
570 evas_object_size_hint_min_set(wd->guidetext, guide_text_width, height);
571 }
572
573 // update buttons in shrink mode
574 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
575 _shrink_mode_set(obj, EINA_TRUE);
576
577 // update guidetext
578 _set_vis_guidetext(obj);
579}
580
581static void
582_set_label(Evas_Object *obj, const char *str)
583{
584 Widget_Data *wd = elm_widget_data_get(obj);
585
586 if (!wd || !str) return;
587 eina_stringshare_replace(&wd->labeltxt, str);
588 if (wd->label)
589 {
590 Evas_Coord width, height, sum_width = 0;
591 evas_object_size_hint_min_set(wd->label, 0, 0);
592 evas_object_resize(wd->label, 0, 0);
593 edje_object_part_text_escaped_set(wd->label, "mbe.label", str);
594
595 if (!strcmp(str, ""))
596 {
597 /* FIXME: not work yet */
598 edje_object_signal_emit(wd->label, "elm,mbe,clear_text", "");
599 edje_object_part_geometry_get(wd->label, "mbe.label", NULL, NULL, &width, &height);
600 sum_width += width;
601 }
602 else
603 {
604 edje_object_signal_emit(wd->label, "elm,mbe,set_text", "");
605 edje_object_part_geometry_get(wd->label, "mbe.label", NULL, NULL, &width, &height);
606
607 sum_width += width;
608
609 edje_object_part_geometry_get(wd->label, "mbe.label.left.padding", NULL, NULL, &width, NULL);
610 sum_width += width;
611
612 edje_object_part_geometry_get(wd->label, "mbe.label.right.padding", NULL, NULL, &width, NULL);
613 sum_width += width;
614 }
615 evas_object_size_hint_min_set(wd->label, sum_width, height);
616 }
617 evas_object_show(wd->label);
618 _view_update(obj);
619}
620
621static void
622_set_guidetext(Evas_Object *obj, const char *str)
623{
624 Widget_Data *wd = elm_widget_data_get(obj);
625
626 if (!wd || !str) return;
627
628 eina_stringshare_replace(&wd->guidetexttxt, str);
629 if (wd->guidetext == NULL)
630 wd->guidetext = edje_object_add(evas_object_evas_get(obj));
631
632 if (wd->guidetext)
633 {
634 _elm_theme_object_set(obj, wd->guidetext, "multibuttonentry",
635 "guidetext", elm_widget_style_get(obj));
636 evas_object_size_hint_weight_set(wd->guidetext, 0.0, EVAS_HINT_EXPAND);
637 evas_object_size_hint_align_set(wd->guidetext, EVAS_HINT_FILL,
638 EVAS_HINT_FILL);
639 edje_object_part_text_escaped_set(wd->guidetext, "elm.text", str);
640 _view_update(obj);
641 }
642}
643
644static void
645_change_current_button_state(Evas_Object *obj, Multibuttonentry_Button_State state)
646{
647 Widget_Data *wd = elm_widget_data_get(obj);
648 Elm_Multibuttonentry_Item *item = NULL;
649
650 if (!wd) return;
651 item = (Elm_Multibuttonentry_Item *)wd->selected_it;
652
653 if (item && item->button)
654 {
655 switch (state)
656 {
657 case MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT:
658 edje_object_signal_emit(item->button, "default", "");
659 wd->selected_it = NULL;
660 break;
661 case MULTIBUTTONENTRY_BUTTON_STATE_SELECTED:
662 edje_object_signal_emit(item->button, "focused", "");
663 evas_object_smart_callback_call(obj, SIG_ITEM_SELECTED, item);
664 break;
665 default:
666 edje_object_signal_emit(item->button, "default", "");
667 wd->selected_it = NULL;
668 break;
669 }
670 }
671}
672
673static void
674_change_current_button(Evas_Object *obj, Evas_Object *btn)
675{
676 Widget_Data *wd = elm_widget_data_get(obj);
677 Eina_List *l;
678 Elm_Multibuttonentry_Item *item;
679
680 if (!wd) return;
681
682 // change the state of previous button to "default"
683 _change_current_button_state(obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
684
685 // change the current
686 EINA_LIST_FOREACH(wd->items, l, item)
687 {
688 if (item->button == btn)
689 {
690 wd->selected_it = (Elm_Object_Item *)item;
691 break;
692 }
693 }
694 // change the state of current button to "focused"
695 _change_current_button_state(obj, MULTIBUTTONENTRY_BUTTON_STATE_SELECTED);
696}
697
698static void
699_button_clicked(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
700{
701 Widget_Data *wd = elm_widget_data_get(data);
702
703 Elm_Multibuttonentry_Item *item = NULL;
704 if (!wd || wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) return;
705
706 _change_current_button(data, obj);
707
708 if (wd->selected_it)
709 if ((item = (Elm_Multibuttonentry_Item *)wd->selected_it) != NULL)
710 {
711 evas_object_smart_callback_call(data, SIG_ITEM_CLICKED, item);
712 _select_button(data, item->button);
713 }
714}
715
716static void
717_del_button_obj(Evas_Object *obj, Evas_Object *btn)
718{
719 Widget_Data *wd = elm_widget_data_get(obj);
720
721 if (!wd || !btn) return;
722 if (btn)
723 evas_object_del(btn);
724}
725
726static void
727_del_button_item(Elm_Multibuttonentry_Item *item)
728{
729 Eina_List *l;
730 Elm_Multibuttonentry_Item *_item;
731 if (!item) return;
732 Widget_Data *wd;
733
734 Evas_Object *obj = WIDGET(item);
735 wd = elm_widget_data_get(obj);
736 if (!wd) return;
737 EINA_LIST_FOREACH(wd->items, l, _item)
738 {
739 if (_item == item)
740 {
741 wd->items = eina_list_remove(wd->items, _item);
742 elm_box_unpack(wd->box, _item->button);
743
744 evas_object_smart_callback_call(obj, SIG_ITEM_DELETED, _item);
745
746 _del_button_obj(obj, _item->button);
747
748 if (wd->selected_it == (Elm_Object_Item *)_item)
749 wd->selected_it = NULL;
750 break;
751 }
752 }
753 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
754 _shrink_mode_set(obj, EINA_TRUE);
755
756 if (!eina_list_count(wd->items))
757 _set_vis_guidetext(obj);
758}
759
760static void
761_select_button(Evas_Object *obj, Evas_Object *btn)
762{
763 Widget_Data *wd = elm_widget_data_get(obj);
764
765 if (!wd) return;
766 if (btn)
767 {
768 _change_current_button(obj, btn);
769 if (elm_widget_focus_get(obj))
770 {
771 elm_object_focus_set(wd->entry, EINA_FALSE);
772 evas_object_focus_set(btn, EINA_TRUE);
773 }
774 }
775 else
776 {
777 _change_current_button_state(obj, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
778 if (elm_widget_focus_get(obj))
779 elm_object_focus_set(wd->entry, EINA_TRUE);
780 }
781}
782
783static void
784_resize_button(Evas_Object *btn, Evas_Coord *realw, Evas_Coord *vieww)
785{
786 Evas_Coord rw, vw;
787 Evas_Coord w_text, h_btn, padding_outer = 0;
788 Evas_Coord w_btn = 0, button_max_width = 0;
789 const char *size_str;
790
791 size_str = edje_object_data_get(btn, "button_max_size");
792 if (size_str) button_max_width = (Evas_Coord)atoi(size_str);
793
794 // decide the size of button
795 edje_object_part_geometry_get(btn, "elm.base", NULL, NULL, NULL, &h_btn);
796 edje_object_part_geometry_get(btn, "elm.btn.text", NULL, NULL, &w_text, NULL);
797 edje_object_part_geometry_get(btn, "right.padding", NULL, NULL, &padding_outer, NULL);
798 w_btn = w_text + (2 * padding_outer);
799
800 rw = w_btn;
801
802 if (button_max_width < w_btn)
803 vw = button_max_width;
804 else
805 vw = w_btn;
806
807 //resize btn
808 evas_object_resize(btn, vw, h_btn);
809 evas_object_size_hint_min_set(btn, vw, h_btn);
810
811 if (realw) *realw = rw;
812 if (vieww) *vieww = vw;
813}
814
815static Eina_Bool
816_item_del_pre_hook(Elm_Object_Item *it)
817{
818 _del_button_item((Elm_Multibuttonentry_Item *)it);
819 return EINA_TRUE;
820}
821
822static Elm_Object_Item*
823_add_button_item(Evas_Object *obj, const char *str, Multibuttonentry_Pos pos, const void *ref, Evas_Smart_Cb func, void *data)
824{
825 Elm_Multibuttonentry_Item *item;
826 Elm_Multibuttonentry_Item_Filter *item_filter;
827 Elm_Multibuttonentry_Item *reference = (Elm_Multibuttonentry_Item *)ref;
828 Eina_List *l;
829 Evas_Object *btn;
830 Evas_Coord width = -1, height = -1;
831 char *str_utf8 = NULL;
832 Widget_Data *wd = elm_widget_data_get(obj);
833
834 if (!wd || !wd->box || !wd->entry) return NULL;
835 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
836 if (!str) return NULL;
837
838 EINA_LIST_FOREACH(wd->filter_list, l, item_filter)
839 {
840 if (!(item_filter->callback_func(obj, str, data, item_filter->data)))
841 return NULL;
842 }
843 // add button
844 btn = edje_object_add(evas_object_evas_get(obj));
845 str_utf8 = elm_entry_markup_to_utf8(str);
846
847 //entry is cleared when text is made to button
848 elm_object_text_set(wd->entry, "");
849
850 _elm_theme_object_set(obj, btn, "multibuttonentry", "btn", elm_widget_style_get(obj));
851 edje_object_part_text_escaped_set(btn, "elm.btn.text", str_utf8);
852 edje_object_part_geometry_get(btn, "elm.btn.text", NULL, NULL, &width, &height);
853
854 evas_object_size_hint_min_set(btn, width, height);
855
856 edje_object_signal_callback_add(btn, "mouse,clicked,1", "*", _button_clicked, obj);
857 evas_object_size_hint_weight_set(btn, 0.0, 0.0);
858 evas_object_show(btn);
859
860 // append item list
861 item = elm_widget_item_new(obj, Elm_Multibuttonentry_Item);
862 if (item)
863 {
864 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
865 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
866 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
867 elm_widget_item_data_set(item, data);
868 Evas_Coord rw, vw;
869 _resize_button(btn, &rw, &vw);
870 item->button = btn;
871 item->rw = rw;
872 item->vw = vw;
873 item->visible = EINA_TRUE;
874
875 if (func)
876 {
877 item->func = func;
878 }
879
880 switch (pos)
881 {
882 case MULTIBUTTONENTRY_POS_START:
883 wd->items = eina_list_prepend(wd->items, item);
884 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
885 {
886 elm_widget_sub_object_add(obj, btn);
887 _shrink_mode_set(obj, EINA_TRUE);
888 }
889 else
890 {
891 if (wd->label)
892 elm_box_pack_after(wd->box, btn, wd->label);
893 else
894 elm_box_pack_start(wd->box, btn);
895 if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
896 _set_vis_guidetext(obj);
897 }
898 break;
899 case MULTIBUTTONENTRY_POS_END:
900 wd->items = eina_list_append(wd->items, item);
901 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
902 {
903 elm_widget_sub_object_add(obj, btn);
904 evas_object_hide(btn);
905 }
906 else
907 {
908 if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
909 _set_vis_guidetext(obj);
910 if (wd->entry)
911 elm_box_pack_before(wd->box, btn, wd->entry);
912 else
913 elm_box_pack_end(wd->box, btn);
914 }
915 break;
916 case MULTIBUTTONENTRY_POS_BEFORE:
917 if (reference)
918 wd->items = eina_list_prepend_relative(wd->items, item, reference);
919 else
920 wd->items = eina_list_append(wd->items, item);
921 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
922 {
923 elm_widget_sub_object_add(obj, btn);
924 evas_object_hide(btn);
925 _shrink_mode_set(obj, EINA_TRUE);
926 }
927 else
928 {
929 if (reference)
930 elm_box_pack_before(wd->box, btn, reference->button);
931 else
932 {
933 if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
934 _set_vis_guidetext(obj);
935 if (wd->entry)
936 elm_box_pack_before(wd->box, btn, wd->entry);
937 else
938 elm_box_pack_end(wd->box, btn);
939 }
940 }
941 break;
942 case MULTIBUTTONENTRY_POS_AFTER:
943 if (reference)
944 wd->items = eina_list_append_relative(wd->items, item, reference);
945 else
946 wd->items = eina_list_append(wd->items, item);
947 if (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK)
948 {
949 elm_widget_sub_object_add(obj, btn);
950 _shrink_mode_set(obj, EINA_TRUE);
951 }
952 else
953 {
954 if (reference)
955 elm_box_pack_after(wd->box, btn, reference->button);
956 else
957 {
958 if (wd->view_state == MULTIBUTTONENTRY_VIEW_GUIDETEXT)
959 _set_vis_guidetext(obj);
960 if (wd->entry)
961 elm_box_pack_before(wd->box, btn, wd->entry);
962 else
963 elm_box_pack_end(wd->box, btn);
964 }
965 }
966 break;
967 default:
968 break;
969 }
970 }
971 evas_object_smart_callback_call(obj, SIG_ITEM_ADDED, item);
972
973 free(str_utf8);
974
975 return (Elm_Object_Item *)item;
976}
977
978static Elm_Multibuttonentry_Item_Filter*
979_filter_new(Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
980{
981 Elm_Multibuttonentry_Item_Filter *item_filter = ELM_NEW(Elm_Multibuttonentry_Item_Filter);
982 if (!item_filter) return NULL;
983
984 item_filter->callback_func= func;
985 item_filter->data = data;
986
987 return item_filter;
988}
989
990static void
991_filter_free(Elm_Multibuttonentry_Item_Filter *item_filter)
992{
993 free(item_filter);
994}
995
996static void
997_evas_mbe_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
998{
999 Widget_Data *wd = elm_widget_data_get(data);
1000 Elm_Multibuttonentry_Item *item = NULL;
1001
1002 if (!wd || !wd->base || !wd->box) return;
1003
1004 Evas_Event_Key_Up *ev = (Evas_Event_Key_Up*)event_info;
1005
1006 if (wd->last_btn_select)
1007 {
1008 if (wd->selected_it &&
1009 ((strcmp(ev->keyname, "BackSpace") == 0) ||
1010 (strcmp(ev->keyname, "Delete") == 0)))
1011 {
1012 item = (Elm_Multibuttonentry_Item *)wd->selected_it;
1013 if (item)
1014 {
1015 _del_button_item(item);
1016 elm_widget_item_free(item);
1017 elm_object_focus_set(wd->entry, EINA_TRUE);
1018 }
1019 }
1020 else if (((!wd->selected_it && (wd->n_str == 0) &&
1021 (strcmp(ev->keyname, "BackSpace") == 0)) ||
1022 (strcmp(ev->keyname, "Delete") == 0)))
1023 {
1024 item = eina_list_data_get(eina_list_last(wd->items));
1025 if (item)
1026 _select_button(data, item->button);
1027 }
1028 }
1029 else
1030 wd->last_btn_select = EINA_TRUE;
1031}
1032
1033static void
1034_entry_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1035{
1036 Widget_Data *wd = elm_widget_data_get(data);
1037 Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event_info;
1038
1039 if (!wd) return;
1040
1041 if ((wd->n_str == 1) && (strcmp(ev->keyname, "BackSpace") == 0 || (strcmp(ev->keyname, "Delete") == 0 )))
1042 wd->last_btn_select = EINA_FALSE;
1043}
1044
1045static void
1046_entry_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1047{
1048 Widget_Data *wd = elm_widget_data_get(data);
1049 Evas_Event_Key_Up *ev = (Evas_Event_Key_Up *) event_info;
1050 const char *str;
1051
1052 if (!wd || !wd->base || !wd->box) return;
1053
1054 str = elm_object_text_get(wd->entry);
1055
1056 if ((strcmp(str, "") != 0) && (strcmp(ev->keyname, "KP_Enter") == 0 || strcmp(ev->keyname, "Return") == 0 ))
1057 {
1058 _add_button_item(data, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL);
1059 wd->n_str = 0;
1060 }
1061}
1062
1063static void
1064_entry_clicked_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1065{
1066 Widget_Data *wd = elm_widget_data_get(data);
1067 if (!wd) return;
1068
1069 _change_current_button_state(data, MULTIBUTTONENTRY_BUTTON_STATE_DEFAULT);
1070 elm_object_focus_set(wd->entry, EINA_TRUE);
1071}
1072
1073static void
1074_entry_focus_in_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1075{
1076 Widget_Data *wd = elm_widget_data_get(data);
1077 Elm_Multibuttonentry_Item *item = NULL;
1078
1079 if (!wd) return;
1080
1081 if (wd->selected_it)
1082 {
1083 item = (Elm_Multibuttonentry_Item *)wd->selected_it;
1084 elm_object_focus_set(wd->entry, EINA_FALSE);
1085 evas_object_focus_set(item->button, EINA_TRUE);
1086 }
1087}
1088
1089static void
1090_entry_focus_out_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1091{
1092 Widget_Data *wd = elm_widget_data_get(data);
1093 const char *str;
1094
1095 if (!wd) return;
1096
1097 str = elm_object_text_get(wd->entry);
1098 if (strlen(str))
1099 _add_button_item(data, str, MULTIBUTTONENTRY_POS_END, NULL, NULL, NULL);
1100}
1101
1102static void
1103_entry_changed_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1104{
1105 Widget_Data *wd = elm_widget_data_get(data);
1106 const char *str;
1107
1108 if (!wd) return;
1109
1110 str = elm_object_text_get(wd->entry);
1111 wd->n_str = strlen(str);
1112}
1113
1114static void
1115_entry_resized_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1116{
1117 Evas_Coord en_x, en_y, en_w, en_h;
1118 Evas_Coord bx_x, bx_y;
1119
1120 Widget_Data *wd = elm_widget_data_get(data);
1121 if (!wd) return;
1122
1123 evas_object_geometry_get(wd->entry, &en_x, &en_y, &en_w, &en_h);
1124 evas_object_geometry_get(wd->box, &bx_x, &bx_y, NULL, NULL);
1125
1126 if (wd->focused)
1127 elm_widget_show_region_set(wd->box, en_x - bx_x, en_y - bx_y, en_w,
1128 en_h, EINA_TRUE);
1129}
1130
1131static void
1132_view_init(Evas_Object *obj)
1133{
1134 Widget_Data *wd = elm_widget_data_get(obj);
1135
1136 if (!wd) return;
1137
1138 if (!wd->box)
1139 {
1140 wd->box = elm_box_add(obj);
1141 if (!wd->box) return;
1142 elm_widget_sub_object_add(obj, wd->box);
1143 elm_box_layout_set(wd->box, _box_layout_cb, NULL, NULL);
1144 elm_box_homogeneous_set(wd->box, EINA_FALSE);
1145 edje_object_part_swallow(wd->base, "box.swallow", wd->box);
1146 }
1147 if (!wd->label)
1148 {
1149 wd->label = edje_object_add(evas_object_evas_get(obj));
1150 if (!wd->label) return;
1151 _elm_theme_object_set(obj, wd->label, "multibuttonentry", "label", elm_widget_style_get(obj));
1152 _set_label(obj, "");
1153 elm_widget_sub_object_add(obj, wd->label);
1154 }
1155
1156 if (!wd->entry)
1157 {
1158 wd->entry = elm_entry_add(obj);
1159 if (!wd->entry) return;
1160 elm_entry_single_line_set(wd->entry, EINA_TRUE);
1161 elm_object_text_set(wd->entry, "");
1162 elm_entry_input_panel_enabled_set(wd->entry, EINA_FALSE);
1163 evas_object_size_hint_min_set(wd->entry, MIN_W_ENTRY, 0);
1164 evas_object_size_hint_weight_set(wd->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1165 evas_object_size_hint_align_set(wd->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
1166 if (wd->box) elm_box_pack_end(wd->box, wd->entry);
1167 evas_object_show(wd->entry);
1168 wd->view_state = MULTIBUTTONENTRY_VIEW_ENTRY;
1169 }
1170
1171 if (!wd->end)
1172 {
1173 const char *end_type;
1174
1175 end_type = edje_object_data_get(wd->base, "closed_button_type");
1176 if (!end_type || !strcmp(end_type, "label"))
1177 {
1178 wd->end = elm_label_add(obj);
1179 if (!wd->end) return;
1180 elm_object_style_set(wd->end, "extended/multibuttonentry_default");
1181 wd->end_type = MULTIBUTTONENTRY_CLOSED_LABEL;
1182 }
1183 else
1184 {
1185 const char *size_str;
1186 wd->end = edje_object_add(evas_object_evas_get(obj));
1187 if (!wd->end) return;
1188 _elm_theme_object_set(obj, wd->end, "multibuttonentry", "closedbutton", elm_widget_style_get(obj));
1189 Evas_Coord button_min_width = 0;
1190 Evas_Coord button_min_height = 0;
1191
1192 size_str = edje_object_data_get(wd->end, "closed_button_width");
1193 if (size_str) button_min_width = (Evas_Coord)atoi(size_str);
1194 size_str = edje_object_data_get(wd->end, "closed_button_height");
1195 if (size_str) button_min_height = (Evas_Coord)atoi(size_str);
1196
1197 wd->end_type = MULTIBUTTONENTRY_CLOSED_IMAGE;
1198 evas_object_size_hint_min_set(wd->end,
1199 button_min_width * _elm_config->scale,
1200 button_min_height * _elm_config->scale);
1201 elm_widget_sub_object_add(obj, wd->end);
1202 }
1203 }
1204}
1205
1206static void
1207_calculate_box_min_size(Evas_Object *box, Evas_Object_Box_Data *priv)
1208{
1209 Evas_Coord minw, minh, mnw, mnh, ww;
1210 Evas_Coord w, cw = 0, cmaxh = 0;
1211 const Eina_List *l;
1212 Evas_Object_Box_Option *opt;
1213 double wx;
1214
1215 /* FIXME: need to calc max */
1216 minw = 0;
1217 minh = 0;
1218
1219 evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1220 evas_object_size_hint_min_get(box, &minw, NULL);
1221
1222 EINA_LIST_FOREACH(priv->children, l, opt)
1223 {
1224 evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1225 evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1226
1227 if (wx)
1228 {
1229 if (mnw != -1 && (w - cw) >= mnw)
1230 ww = w - cw;
1231 else
1232 ww = w;
1233 }
1234 else
1235 ww = mnw;
1236
1237 if ((cw + mnw) > w)
1238 {
1239 minh += cmaxh;
1240 cw = 0;
1241 cmaxh = 0;
1242 }
1243 cw += ww;
1244 if (cmaxh < mnh) cmaxh = mnh;
1245 }
1246
1247 minh += cmaxh;
1248
1249 evas_object_size_hint_min_set(box, minw, minh);
1250}
1251
1252static Evas_Coord
1253_calculate_item_max_height(Evas_Object *box, Evas_Object_Box_Data *priv, int obj_index)
1254{
1255 Evas_Coord mnw, mnh, cw = 0, cmaxh = 0, w, ww;
1256 const Eina_List *l;
1257 Evas_Object_Box_Option *opt;
1258 int local_index = 0;
1259 double wx;
1260
1261 evas_object_geometry_get(box, NULL, NULL, &w, NULL);
1262
1263 EINA_LIST_FOREACH(priv->children, l, opt)
1264 {
1265 evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
1266 evas_object_size_hint_weight_get(opt->obj, &wx, NULL);
1267
1268 if (wx)
1269 {
1270 if (mnw != -1 && (w - cw) >= mnw)
1271 ww = w - cw;
1272 else
1273 ww = w;
1274 }
1275 else
1276 ww = mnw;
1277
1278 if ((cw + ww) > w)
1279 {
1280 if (local_index > obj_index) return cmaxh;
1281 cw = 0;
1282 cmaxh = 0;
1283 }
1284
1285 cw += ww;
1286 if (cmaxh < mnh) cmaxh = mnh;
1287
1288 local_index++;
1289 }
1290
1291 return cmaxh;
1292}
1293
1294static void
1295_box_layout_cb(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1296{
1297 Evas_Coord x, y, w, h, xx, yy;
1298 const Eina_List *l;
1299 Evas_Object *obj;
1300 Evas_Coord minw, minh;
1301 double ax, ay;
1302 Evas_Object_Box_Option *opt;
1303
1304 _calculate_box_min_size(o, priv);
1305
1306 evas_object_geometry_get(o, &x, &y, &w, &h);
1307
1308 evas_object_size_hint_min_get(o, &minw, &minh);
1309 evas_object_size_hint_align_get(o, &ax, &ay);
1310 if (w < minw)
1311 {
1312 x = x + ((w - minw) * (1.0 - ax));
1313 w = minw;
1314 }
1315 if (h < minh)
1316 {
1317 y = y + ((h - minh) * (1.0 - ay));
1318 h = minh;
1319 }
1320
1321 xx = x;
1322 yy = y;
1323
1324 Evas_Coord cw = 0, ch = 0, cmaxh = 0, obj_index = 0;
1325
1326 EINA_LIST_FOREACH(priv->children, l, opt)
1327 {
1328 Evas_Coord mnw, mnh, mxw, mxh;
1329 double wx, wy;
1330 int fw, fh;
1331
1332 obj = opt->obj;
1333 evas_object_size_hint_align_get(obj, &ax, &ay);
1334 evas_object_size_hint_weight_get(obj, &wx, &wy);
1335 evas_object_size_hint_min_get(obj, &mnw, &mnh);
1336 evas_object_size_hint_max_get(obj, &mxw, &mxh);
1337 fw = fh = 0;
1338 if (ax == -1.0) {fw = 1; ax = 0.5;}
1339 if (ay == -1.0) {fh = 1; ay = 0.5;}
1340 Evas_Coord ww, hh, ow, oh;
1341
1342 if (wx)
1343 {
1344 if (mnw != -1 && (w - cw) >= mnw)
1345 ww = w - cw;
1346 else
1347 ww = w;
1348 }
1349 else
1350 ww = mnw;
1351 hh = _calculate_item_max_height(o, priv, obj_index);
1352
1353 ow = mnw;
1354 if (fw) ow = ww;
1355 if ((mxw >= 0) && (mxw < ow)) ow = mxw;
1356 oh = mnh;
1357 if (fh) oh = hh;
1358 if ((mxh >= 0) && (mxh < oh)) oh = mxh;
1359
1360 if ((cw + ww) > w)
1361 {
1362 ch += cmaxh;
1363 cw = 0;
1364 cmaxh = 0;
1365 }
1366
1367 evas_object_move(obj,
1368 xx + cw + (Evas_Coord)(((double)(ww - ow)) * ax),
1369 yy + ch + (Evas_Coord)(((double)(hh - oh)) * ay));
1370 evas_object_resize(obj, ow, oh);
1371
1372 cw += ww;
1373 if (cmaxh < hh) cmaxh = hh;
1374
1375 obj_index++;
1376 }
1377}
1378
1379static void
1380_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1381{
1382 Elm_Multibuttonentry_Item *item;
1383 if (part && strcmp(part, "default")) return;
1384 if (!label) return;
1385 item = (Elm_Multibuttonentry_Item *)it;
1386 edje_object_part_text_escaped_set(item->button, "elm.btn.text", label);
1387 _resize_button(item->button, &item->rw, &item->vw);
1388}
1389
1390static const char *
1391_item_text_get_hook(const Elm_Object_Item *it, const char *part)
1392{
1393 Elm_Multibuttonentry_Item *item;
1394 if (part && strcmp(part, "default")) return NULL;
1395 item = (Elm_Multibuttonentry_Item *)it;
1396 return edje_object_part_text_get(item->button, "elm.btn.text");
1397}
1398
1399static void
1400_text_set_hook(Evas_Object *obj, const char *part, const char *label)
1401{
1402 ELM_CHECK_WIDTYPE(obj, widtype);
1403 if (!part || !strcmp(part, "default"))
1404 {
1405 if (label) _set_label(obj, label);
1406 else _set_label(obj, "");
1407 }
1408 else if (!strcmp(part, "guide"))
1409 {
1410 if (label) _set_guidetext(obj, label);
1411 else _set_guidetext(obj, "");
1412 }
1413}
1414
1415static const char *
1416_text_get_hook(const Evas_Object *obj, const char *part)
1417{
1418 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1419 Widget_Data *wd = elm_widget_data_get(obj);
1420 if (!wd) return NULL;
1421
1422 if (!part || !strcmp(part, "default"))
1423 {
1424 return wd->labeltxt;
1425 }
1426 else if (!strcmp(part, "guide"))
1427 {
1428 return wd->guidetexttxt;
1429 }
1430 return NULL;
1431}
1432
1433EAPI Evas_Object *
1434elm_multibuttonentry_add(Evas_Object *parent)
1435{
1436 Evas_Object *obj;
1437 Evas *e;
1438 Widget_Data *wd;
1439
1440 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1441
1442 ELM_SET_WIDTYPE(widtype, "multibuttonentry");
1443 elm_widget_type_set(obj, "multibuttonentry");
1444 elm_widget_sub_object_add(parent, obj);
1445 elm_widget_data_set(obj, wd);
1446
1447 elm_widget_del_hook_set(obj, _del_hook);
1448 elm_widget_theme_hook_set(obj, _theme_hook);
1449 elm_widget_event_hook_set(obj, _event_hook);
1450 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1451 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1452 elm_widget_text_set_hook_set(obj, _text_set_hook);
1453 elm_widget_text_get_hook_set(obj, _text_get_hook);
1454
1455 wd->base = edje_object_add(e);
1456 _elm_theme_object_set(obj, wd->base, "multibuttonentry", "base", "default");
1457 elm_widget_resize_object_set(obj, wd->base);
1458 elm_widget_can_focus_set(obj, EINA_TRUE);
1459
1460 wd->view_state = MULTIBUTTONENTRY_VIEW_NONE;
1461 wd->focused = EINA_FALSE;
1462 wd->last_btn_select = EINA_TRUE;
1463 wd->n_str = 0;
1464 wd->rect_for_end = NULL;
1465 wd->add_callback = NULL;
1466 wd->add_callback_data = NULL;
1467
1468 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1469
1470 _view_init(obj);
1471 _event_init(obj);
1472
1473 return obj;
1474}
1475
1476EAPI Evas_Object *
1477elm_multibuttonentry_entry_get(const Evas_Object *obj)
1478{
1479 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1480 Widget_Data *wd = elm_widget_data_get(obj);
1481
1482 if (!wd) return NULL;
1483
1484 return wd->entry;
1485}
1486
1487EAPI Eina_Bool
1488elm_multibuttonentry_expanded_get(const Evas_Object *obj)
1489{
1490 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1491 Widget_Data *wd = elm_widget_data_get(obj);
1492
1493 if (!wd) return -1;
1494 return (wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK ? EINA_FALSE : EINA_TRUE);
1495}
1496
1497EAPI void
1498elm_multibuttonentry_expanded_set(Evas_Object *obj, Eina_Bool expanded)
1499{
1500 ELM_CHECK_WIDTYPE(obj, widtype);
1501 Widget_Data *wd = elm_widget_data_get(obj);
1502
1503 if (!wd || !wd->box ||
1504 ((wd->view_state == MULTIBUTTONENTRY_VIEW_SHRINK) ? EINA_FALSE : EINA_TRUE) == expanded) return;
1505
1506 if (expanded)
1507 _shrink_mode_set(obj, EINA_FALSE);
1508 else
1509 _shrink_mode_set(obj, EINA_TRUE);
1510
1511}
1512
1513EAPI Elm_Object_Item *
1514elm_multibuttonentry_item_prepend(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data)
1515{
1516 return _add_button_item(obj, label, MULTIBUTTONENTRY_POS_START, NULL, func, data);
1517}
1518
1519EAPI Elm_Object_Item *
1520elm_multibuttonentry_item_append(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data)
1521{
1522 return _add_button_item(obj, label, MULTIBUTTONENTRY_POS_END, NULL, func, data);
1523}
1524
1525EAPI Elm_Object_Item *
1526elm_multibuttonentry_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *label, Evas_Smart_Cb func, void *data)
1527{
1528 return _add_button_item(obj, label, MULTIBUTTONENTRY_POS_BEFORE, before, func, data);
1529}
1530
1531EAPI Elm_Object_Item *
1532elm_multibuttonentry_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *label, Evas_Smart_Cb func, void *data)
1533{
1534 return _add_button_item(obj, label, MULTIBUTTONENTRY_POS_AFTER, after, func, data);
1535}
1536
1537EAPI const Eina_List *
1538elm_multibuttonentry_items_get(const Evas_Object *obj)
1539{
1540 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1541 Widget_Data *wd = elm_widget_data_get(obj);
1542 if (!wd) return NULL;
1543 return wd->items;
1544}
1545
1546EAPI Elm_Object_Item *
1547elm_multibuttonentry_first_item_get(const Evas_Object *obj)
1548{
1549 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1550 Widget_Data *wd = elm_widget_data_get(obj);
1551 if (!wd) return NULL;
1552 return eina_list_data_get(wd->items);
1553}
1554
1555EAPI Elm_Object_Item *
1556elm_multibuttonentry_last_item_get(const Evas_Object *obj)
1557{
1558 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1559 Widget_Data *wd = elm_widget_data_get(obj);
1560 if (!wd) return NULL;
1561 return eina_list_data_get(eina_list_last(wd->items));
1562}
1563
1564EAPI Elm_Object_Item *
1565elm_multibuttonentry_selected_item_get(const Evas_Object *obj)
1566{
1567 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1568 Widget_Data *wd = elm_widget_data_get(obj);
1569 if (!wd) return NULL;
1570 return wd->selected_it;
1571}
1572
1573EAPI void
1574elm_multibuttonentry_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
1575{
1576 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1577 Elm_Multibuttonentry_Item *item = (Elm_Multibuttonentry_Item *)it;
1578 if (selected) _select_button(WIDGET(item), item->button);
1579 else _select_button(WIDGET(item), NULL);
1580}
1581
1582EAPI Eina_Bool
1583elm_multibuttonentry_item_selected_get(const Elm_Object_Item *it)
1584{
1585 //TODO : To be implemented.
1586 if (!it) return EINA_FALSE;
1587 return EINA_TRUE;
1588}
1589
1590EAPI void
1591elm_multibuttonentry_clear(Evas_Object *obj)
1592{
1593 ELM_CHECK_WIDTYPE(obj, widtype);
1594 Elm_Multibuttonentry_Item *item;
1595 Widget_Data *wd = elm_widget_data_get(obj);
1596 if (!wd) return;
1597
1598 if (wd->items)
1599 {
1600 EINA_LIST_FREE(wd->items, item)
1601 {
1602 elm_box_unpack(wd->box, item->button);
1603 _del_button_obj(obj, item->button);
1604 free(item);
1605 }
1606 wd->items = NULL;
1607 }
1608 wd->selected_it = NULL;
1609 _view_update(obj);
1610}
1611
1612EAPI Elm_Object_Item *
1613elm_multibuttonentry_item_prev_get(const Elm_Object_Item *it)
1614{
1615 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1616 Widget_Data *wd;
1617 Eina_List *l;
1618 Elm_Multibuttonentry_Item *_item;
1619
1620 wd = elm_widget_data_get(WIDGET(it));
1621 if (!wd) return NULL;
1622
1623 EINA_LIST_FOREACH(wd->items, l, _item)
1624 {
1625 if (_item == (Elm_Multibuttonentry_Item *)it)
1626 {
1627 l = eina_list_prev(l);
1628 if (!l) return NULL;
1629 return eina_list_data_get(l);
1630 }
1631 }
1632 return NULL;
1633}
1634
1635EAPI Elm_Object_Item *
1636elm_multibuttonentry_item_next_get(const Elm_Object_Item *it)
1637{
1638 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1639 Widget_Data *wd;
1640 Eina_List *l;
1641 Elm_Multibuttonentry_Item *_item;
1642 wd = elm_widget_data_get(WIDGET(it));
1643 if (!wd) return NULL;
1644
1645 EINA_LIST_FOREACH(wd->items, l, _item)
1646 {
1647 if (_item == (Elm_Multibuttonentry_Item *)it)
1648 {
1649 l = eina_list_next(l);
1650 if (!l) return NULL;
1651 return eina_list_data_get(l);
1652 }
1653 }
1654 return NULL;
1655}
1656
1657EINA_DEPRECATED EAPI void *
1658elm_multibuttonentry_item_data_get(const Elm_Object_Item *it)
1659{
1660 return elm_widget_item_data_get(it);
1661}
1662
1663EINA_DEPRECATED EAPI void
1664elm_multibuttonentry_item_data_set(Elm_Object_Item *it, void *data)
1665{
1666 return elm_widget_item_data_set(it, data);
1667}
1668
1669EAPI void
1670elm_multibuttonentry_item_filter_append(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
1671{
1672 Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL;
1673 Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1674 Eina_List *l;
1675
1676 Widget_Data *wd = elm_widget_data_get(obj);
1677 if (!wd) return;
1678
1679 ELM_CHECK_WIDTYPE(obj, widtype);
1680 EINA_SAFETY_ON_NULL_RETURN(func);
1681
1682 new_item_filter= _filter_new(func, data);
1683 if (!new_item_filter) return;
1684
1685 EINA_LIST_FOREACH(wd->filter_list, l, _item_filter)
1686 {
1687 if (_item_filter && ((_item_filter->callback_func == func) && (_item_filter->data == data)))
1688 {
1689 printf("Already Registered this item filter!!!!\n");
1690 return;
1691 }
1692 }
1693 wd->filter_list = eina_list_append(wd->filter_list, new_item_filter);
1694}
1695
1696EAPI void
1697elm_multibuttonentry_item_filter_prepend(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
1698{
1699 Elm_Multibuttonentry_Item_Filter *new_item_filter = NULL;
1700 Elm_Multibuttonentry_Item_Filter *_item_filter = NULL;
1701 Eina_List *l;
1702 Widget_Data *wd = elm_widget_data_get(obj);
1703 if (!wd) return;
1704
1705 ELM_CHECK_WIDTYPE(obj, widtype);
1706 EINA_SAFETY_ON_NULL_RETURN(func);
1707
1708 new_item_filter = _filter_new(func, data);
1709 if (!new_item_filter) return;
1710
1711 EINA_LIST_FOREACH(wd->filter_list, l, _item_filter)
1712 {
1713 if (_item_filter && ((_item_filter->callback_func == func) && (_item_filter->data == data)))
1714 {
1715 printf("Already Registered this item filter!!!!\n");
1716 return;
1717 }
1718 }
1719 wd->filter_list = eina_list_prepend(wd->filter_list, new_item_filter);
1720}
1721
1722EAPI void
1723elm_multibuttonentry_item_filter_remove(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_Cb func, void *data)
1724{
1725 Widget_Data *wd;
1726 Eina_List *l;
1727 Elm_Multibuttonentry_Item_Filter *item_filter;
1728
1729 wd = elm_widget_data_get(obj);
1730
1731 EINA_SAFETY_ON_NULL_RETURN(func);
1732
1733 EINA_LIST_FOREACH(wd->filter_list, l, item_filter)
1734 {
1735 if ((item_filter->callback_func == func) && ((!data) || (item_filter->data == data)))
1736 {
1737 wd->filter_list = eina_list_remove_list(wd->filter_list, l);
1738 _filter_free(item_filter);
1739 return;
1740 }
1741 }
1742}
diff --git a/libraries/elementary/src/lib/elc_multibuttonentry.h b/libraries/elementary/src/lib/elc_multibuttonentry.h
new file mode 100644
index 0000000..af3ce87
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_multibuttonentry.h
@@ -0,0 +1,318 @@
1/**
2 * @defgroup Multibuttonentry Multibuttonentry
3 * @ingroup Elementary
4 *
5 * A Multibuttonentry is a widget to allow a user enter text and manage it as a number
6 * of buttons. Each text button is inserted by pressing the "return" key.
7 * If there is no space in the current row, a new button is added to the next row.
8 * When a text button is pressed, it will become focused.
9 * Backspace removes the focus.
10 * When the Multibuttonentry loses focus items longer than one line are shrunk
11 * to one line.
12 *
13 * Typical use case of multibuttonentry is, composing emails/messages to a group
14 * of addresses, each of which is an item that can be clicked for further actions.
15 *
16 * Smart callbacks one can register:
17 * - @c "item,selected" - this is called when an item is selected by api, user
18 * interaction, and etc. this is also called when a user press back space
19 * while cursor is on the first field of entry.
20 * - @c "item,added" - when a new multibuttonentry item is added.
21 * - @c "item,deleted" - when a multibuttonentry item is deleted.
22 * - @c "item,clicked" - this is called when an item is clicked by user
23 * interaction. Both "item,selected" and "item,clicked" are needed.
24 * - @c "clicked" - when multibuttonentry is clicked.
25 * - @c "focused" - when multibuttonentry is focused.
26 * - @c "unfocused" - when multibuttonentry is unfocused.
27 * - @c "expanded" - when multibuttonentry is expanded.
28 * - @c "contracted" - when multibuttonentry is contracted.
29 * - @c "expand,state,changed" - when shrink mode state of multibuttonentry is changed.
30 *
31 * Default text parts of the multibuttonentry widget that you can use for are:
32 * @li "default" - A label of the multibuttonentry
33 *
34 * Default text parts of the multibuttonentry items that you can use for are:
35 * @li "default" - A label of the multibuttonentry item
36 *
37 * Supported elm_object common APIs.
38 * @li @ref elm_object_signal_emit
39 * @li @ref elm_object_part_text_set
40 * @li @ref elm_object_part_text_get
41 *
42 * Supported elm_object_item common APIs.
43 * @li @ref elm_object_item_part_text_set
44 * @li @ref elm_object_item_part_text_get
45 *
46 */
47
48/**
49 * @addtogroup Multibuttonentry
50 * @{
51 */
52
53/**
54 * @brief Callback to be invoked when an item is added to the multibuttonentry.
55 *
56 * @param obj The parent object
57 * @param item_label The label corresponding to the added item.
58 * @param item_data data specific to this item.
59 * @param data data specific to the multibuttonentry.
60 *
61 * @return EINA_TRUE
62 * EINA_FALSE otherwise.
63 *
64 * @ingroup Multibuttonentry
65 */
66typedef Eina_Bool (*Elm_Multibuttonentry_Item_Filter_Cb)(Evas_Object *obj, const char *item_label, void *item_data, void *data);
67
68/**
69 * @brief Add a new multibuttonentry to the parent
70 *
71 * @param parent The parent object
72 * @return The new object or NULL if it cannot be created
73 *
74 *
75 * @ingroup Multibuttonentry
76 */
77EAPI Evas_Object *elm_multibuttonentry_add(Evas_Object *parent);
78
79
80/**
81 * Get the entry of the multibuttonentry object
82 *
83 * @param obj The multibuttonentry object
84 * @return The entry object, or NULL if none
85 *
86 * @ingroup Multibuttonentry
87 */
88EAPI Evas_Object *elm_multibuttonentry_entry_get(const Evas_Object *obj);
89
90/**
91 * Get the value of expanded state.
92 * In expanded state, the complete entry will be displayed.
93 * Otherwise, only single line of the entry will be displayed.
94 *
95 * @param obj The multibuttonentry object
96 * @return EINA_TRUE if the widget is in expanded state. EINA_FALSE if not.
97 *
98 * @ingroup Multibuttonentry
99 */
100EAPI Eina_Bool elm_multibuttonentry_expanded_get(const Evas_Object *obj);
101
102/**
103 * Set/Unset the multibuttonentry to expanded state.
104 * In expanded state, the complete entry will be displayed.
105 * Otherwise, only single line of the entry will be displayed.
106 *
107 * @param obj The multibuttonentry object
108 * @param expanded the value of expanded state.
109 * Set this to EINA_TRUE for expanded state.
110 * Set this to EINA_FALSE for single line state.
111 *
112 * @ingroup Multibuttonentry
113 */
114EAPI void elm_multibuttonentry_expanded_set(Evas_Object *obj, Eina_Bool expanded);
115
116/**
117 * Prepend a new item to the multibuttonentry
118 *
119 * @param obj The multibuttonentry object
120 * @param label The label of new item
121 * @param func The callback function to be invoked when this item is pressed.
122 * @param data The pointer to the data to be attached
123 * @return A handle to the item added or NULL if not possible
124 *
125 * @see Use elm_object_item_del() to delete the item.
126 *
127 * @ingroup Multibuttonentry
128 */
129EAPI Elm_Object_Item *elm_multibuttonentry_item_prepend(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data);
130
131/**
132 * Append a new item to the multibuttonentry
133 *
134 * @param obj The multibuttonentry object
135 * @param label The label of new item
136 * @param func The callback function to be invoked when this item is pressed.
137 * @param data The pointer to the data to be attached
138 * @return A handle to the item added or NULL if not possible
139 *
140 * @see Use elm_object_item_del() to delete the item.
141 *
142 * @ingroup Multibuttonentry
143 */
144EAPI Elm_Object_Item *elm_multibuttonentry_item_append(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data);
145
146/**
147 * Add a new item to the multibuttonentry before the indicated object
148 *
149 * reference.
150 * @param obj The multibuttonentry object
151 * @param before The item before which to add it
152 * @param label The label of new item
153 * @param func The callback function to be invoked when this item is pressed.
154 * @param data The pointer to the data to be attached
155 * @return A handle to the item added or NULL if not possible
156 *
157 * @see Use elm_object_item_del() to delete the item.
158 *
159 * @ingroup Multibuttonentry
160 */
161EAPI Elm_Object_Item *elm_multibuttonentry_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *label, Evas_Smart_Cb func, void *data);
162
163/**
164 * Add a new item to the multibuttonentry after the indicated object
165 *
166 * @param obj The multibuttonentry object
167 * @param after The item after which to add it
168 * @param label The label of new item
169 * @param func The callback function to be invoked when this item is pressed.
170 * @param data The pointer to the data to be attached
171 * @return A handle to the item added or NULL if not possible
172 *
173 * @see Use elm_object_item_del() to delete the item.
174 *
175 * @ingroup Multibuttonentry
176 */
177EAPI Elm_Object_Item *elm_multibuttonentry_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *label, Evas_Smart_Cb func, void *data);
178
179/**
180 * Get a list of items in the multibuttonentry
181 *
182 * @param obj The multibuttonentry object
183 * @return The list of items, or NULL if none
184 *
185 * @ingroup Multibuttonentry
186 */
187EAPI const Eina_List *elm_multibuttonentry_items_get(const Evas_Object *obj);
188
189/**
190 * Get the first item in the multibuttonentry
191 *
192 * @param obj The multibuttonentry object
193 * @return The first item, or NULL if none
194 *
195 * @ingroup Multibuttonentry
196 */
197EAPI Elm_Object_Item *elm_multibuttonentry_first_item_get(const Evas_Object *obj);
198
199/**
200 * Get the last item in the multibuttonentry
201 *
202 * @param obj The multibuttonentry object
203 * @return The last item, or NULL if none
204 *
205 * @ingroup Multibuttonentry
206 */
207EAPI Elm_Object_Item *elm_multibuttonentry_last_item_get(const Evas_Object *obj);
208
209/**
210 * Get the selected item in the multibuttonentry
211 *
212 * @param obj The multibuttonentry object
213 * @return The selected item, or NULL if none
214 *
215 * @ingroup Multibuttonentry
216 */
217EAPI Elm_Object_Item *elm_multibuttonentry_selected_item_get(const Evas_Object *obj);
218
219/**
220 * Set the selected state of an item
221 *
222 * @param it The item
223 * @param selected if it's EINA_TRUE, select the item otherwise, unselect the item
224 *
225 * @ingroup Multibuttonentry
226 */
227EAPI void elm_multibuttonentry_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
228
229
230/**
231 * Get the selected state of an item
232 *
233 * @param it The item
234 * @return EINA_TRUE if the item is selected, EINA_FALSE otherwise.
235 *
236 * @ingroup Multibuttonentry
237 */
238EAPI Eina_Bool elm_multibuttonentry_item_selected_get(const Elm_Object_Item *it);
239
240/**
241 * Remove all items in the multibuttonentry.
242 *
243 * @param obj The multibuttonentry object
244 *
245 * @ingroup Multibuttonentry
246 */
247EAPI void elm_multibuttonentry_clear(Evas_Object *obj);
248
249/**
250 * Get the previous item in the multibuttonentry
251 *
252 * @param it The item
253 * @return The item before the item @p it
254 *
255 * @ingroup Multibuttonentry
256 */
257EAPI Elm_Object_Item *elm_multibuttonentry_item_prev_get(const Elm_Object_Item *it);
258
259/**
260 * Get the next item in the multibuttonentry
261 *
262 * @param it The item
263 * @return The item after the item @p it
264 *
265 * @ingroup Multibuttonentry
266 */
267EAPI Elm_Object_Item *elm_multibuttonentry_item_next_get(const Elm_Object_Item *it);
268
269/**
270 * Append an item filter function for text inserted in the Multibuttonentry
271 *
272 * Append the given callback to the list. This functions will be called
273 * whenever any text is inserted into the Multibuttonentry, with the text to be inserted
274 * as a parameter. The callback function is free to alter the text in any way
275 * it wants, but it must remember to free the given pointer and update it.
276 * If the new text is to be discarded, the function can free it and set it text
277 * parameter to NULL. This will also prevent any following filters from being
278 * called.
279 *
280 * @param obj The multibuttonentry object
281 * @param func The function to use as item filter
282 * @param data User data to pass to @p func
283 *
284 * @ingroup Multibuttonentry
285 */
286EAPI void elm_multibuttonentry_item_filter_append(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_Cb func, void *data);
287
288/**
289 * Prepend a filter function for text inserted in the Multibuttonentry
290 *
291 * Prepend the given callback to the list. See elm_multibuttonentry_item_filter_append()
292 * for more information
293 *
294 * @param obj The multibuttonentry object
295 * @param func The function to use as text filter
296 * @param data User data to pass to @p func
297 *
298 * @ingroup Multibuttonentry
299 */
300EAPI void elm_multibuttonentry_item_filter_prepend(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_Cb func, void *data);
301
302/**
303 * Remove a filter from the list
304 *
305 * Removes the given callback from the filter list. See elm_multibuttonentry_item_filter_append()
306 * for more information.
307 *
308 * @param obj The multibuttonentry object
309 * @param func The filter function to remove
310 * @param data The user data passed when adding the function
311 *
312 * @ingroup Multibuttonentry
313 */
314EAPI void elm_multibuttonentry_item_filter_remove(Evas_Object *obj, Elm_Multibuttonentry_Item_Filter_Cb func, void *data);
315
316/**
317 * @}
318 */
diff --git a/libraries/elementary/src/lib/elc_naviframe.c b/libraries/elementary/src/lib/elc_naviframe.c
new file mode 100644
index 0000000..49e838e
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_naviframe.c
@@ -0,0 +1,1530 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Naviframe_Item Elm_Naviframe_Item;
6typedef struct _Elm_Naviframe_Content_Item_Pair Elm_Naviframe_Content_Item_Pair;
7typedef struct _Elm_Naviframe_Text_Item_Pair Elm_Naviframe_Text_Item_Pair;
8
9struct _Widget_Data
10{
11 Eina_Inlist *stack;
12 Evas_Object *base;
13 Eina_Bool preserve: 1;
14 Eina_Bool auto_pushed: 1;
15 Eina_Bool freeze_events: 1;
16};
17
18struct _Elm_Naviframe_Content_Item_Pair
19{
20 EINA_INLIST;
21 const char *part;
22 Elm_Naviframe_Item *it;
23};
24
25struct _Elm_Naviframe_Text_Item_Pair
26{
27 EINA_INLIST;
28 const char *part;
29};
30
31struct _Elm_Naviframe_Item
32{
33 ELM_WIDGET_ITEM;
34 EINA_INLIST;
35 Eina_Inlist *content_list;
36 Eina_Inlist *text_list;
37 Evas_Object *content;
38 Evas_Object *title_prev_btn;
39 Evas_Object *title_next_btn;
40 Evas_Object *title_icon;
41 const char *style;
42 Evas_Coord minw;
43 Evas_Coord minh;
44 Eina_Bool back_btn: 1;
45 Eina_Bool title_visible: 1;
46 Eina_Bool content_unfocusable : 1;
47};
48
49static const char *widtype = NULL;
50
51//widget signals
52static const char SIG_TRANSITION_FINISHED[] = "transition,finished";
53static const char SIG_TITLE_CLICKED[] = "title,clicked";
54
55static const Evas_Smart_Cb_Description _signals[] = {
56 {SIG_TRANSITION_FINISHED, ""},
57 {SIG_TITLE_CLICKED, ""},
58 {NULL, NULL}
59};
60
61static void _text_set_hook(Evas_Object *obj,
62 const char *part,
63 const char *label);
64static const char *_text_get_hook(const Evas_Object *obj, const char *part);
65static void _content_set_hook(Evas_Object *obj,
66 const char *part,
67 Evas_Object *content);
68static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
69static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
70static void _del_hook(Evas_Object *obj);
71static void _theme_hook(Evas_Object *obj);
72static void _emit_hook(Evas_Object *obj,
73 const char *emission,
74 const char *source);
75static void _disable_hook(Evas_Object *obj);
76static void _item_text_set_hook(Elm_Object_Item *it,
77 const char *part,
78 const char *label);
79static const char *_item_text_get_hook(const Elm_Object_Item *it,
80 const char *part);
81static void _item_content_set_hook(Elm_Object_Item *it,
82 const char *part,
83 Evas_Object *content);
84static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
85 const char *part);
86static Evas_Object *_item_content_unset_hook(Elm_Object_Item *it,
87 const char *part);
88static void _item_signal_emit_hook(Elm_Object_Item *it,
89 const char *emission,
90 const char *source);
91static void _item_title_visible_update(Elm_Naviframe_Item *navi_it);
92static void _sizing_eval(Evas_Object *obj);
93static void _move(void *data, Evas *e, Evas_Object *obj, void *event_info);
94static void _resize(void *data,
95 Evas *e,
96 Evas_Object *obj,
97 void *event_info);
98static void _title_clicked(void *data, Evas_Object *obj,
99 const char *emission,
100 const char *source);
101static void _back_btn_clicked(void *data,
102 Evas_Object *obj,
103 void *event_info);
104static Evas_Object *_back_btn_new(Evas_Object *obj);
105static void _item_content_del(void *data,
106 Evas *e,
107 Evas_Object *obj,
108 void *event_info);
109static void _title_content_del(void *data,
110 Evas *e,
111 Evas_Object *obj,
112 void *event_info);
113static void _title_prev_btn_del(void *data,
114 Evas *e,
115 Evas_Object *obj,
116 void *event_info);
117static void _title_next_btn_del(void *data,
118 Evas *e,
119 Evas_Object *obj,
120 void *event_info);
121static void _title_icon_del(void *data,
122 Evas *e,
123 Evas_Object *obj,
124 void *event_info);
125static void _title_content_set(Elm_Naviframe_Item *it,
126 const char *part,
127 Evas_Object *content);
128static void _title_prev_btn_set(Elm_Naviframe_Item *it,
129 Evas_Object *btn,
130 Eina_Bool back_btn);
131static void _title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn);
132static void _title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon);
133static Evas_Object * _item_content_unset(Elm_Naviframe_Item *it);
134static Evas_Object * _title_prev_btn_unset(Elm_Naviframe_Item *it);
135static Evas_Object * _title_next_btn_unset(Elm_Naviframe_Item *it);
136static Evas_Object * _title_icon_unset(Elm_Naviframe_Item *it);
137static Evas_Object * _title_content_unset(Elm_Naviframe_Item *it,
138 const char *part);
139static void _item_del(Elm_Naviframe_Item *it);
140static Eina_Bool _item_del_pre_hook(Elm_Object_Item *it);
141static void _pushed_finished(void *data,
142 Evas_Object *obj,
143 const char *emission,
144 const char *source);
145static void _popped_finished(void *data,
146 Evas_Object *obj,
147 const char *emission,
148 const char *source);
149static void _show_finished(void *data,
150 Evas_Object *obj,
151 const char *emission,
152 const char *source);
153static void _changed_size_hints(void *data,
154 Evas *e,
155 Evas_Object *obj,
156 void *event_info);
157static void _item_content_set(Elm_Naviframe_Item *navi_it,
158 Evas_Object *content);
159static void _item_style_set(Elm_Naviframe_Item *navi_it,
160 const char *item_style);
161static Elm_Naviframe_Item * _item_new(Evas_Object *obj,
162 const char *title_label,
163 Evas_Object *prev_btn,
164 Evas_Object *next_btn,
165 Evas_Object *content,
166 const char *item_style);
167static Eina_Bool _focus_next_hook(const Evas_Object *obj,
168 Elm_Focus_Direction dir,
169 Evas_Object **next);
170
171static void
172_del_hook(Evas_Object *obj)
173{
174 Widget_Data *wd;
175 Elm_Naviframe_Item *it;
176
177 wd = elm_widget_data_get(obj);
178 if (!wd) return;
179
180 if (wd->stack)
181 {
182 while (wd->stack->last)
183 {
184 it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
185 Elm_Naviframe_Item);
186 wd->stack = eina_inlist_remove(wd->stack, wd->stack->last);
187 _item_del(it);
188 elm_widget_item_free(it);
189 if (!wd->stack) break;
190 }
191 }
192 free(wd);
193}
194
195static void
196_theme_hook(Evas_Object *obj)
197{
198 Widget_Data *wd;
199 Elm_Naviframe_Item *it;
200
201 wd = elm_widget_data_get(obj);
202 if (!wd) return;
203
204 _elm_theme_object_set(obj,
205 wd->base,
206 "naviframe",
207 "base",
208 elm_widget_style_get(obj));
209
210 EINA_INLIST_FOREACH(wd->stack, it)
211 {
212 _item_style_set(it, it->style);
213 _item_title_visible_update(it);
214 }
215}
216
217static void _emit_hook(Evas_Object *obj,
218 const char *emission,
219 const char *source)
220{
221 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
222 if (!it) return;
223 return elm_object_item_signal_emit(it, emission, source);
224}
225
226static void
227_disable_hook(Evas_Object *obj __UNUSED__)
228{
229 //FIXME:
230}
231
232static void
233_item_text_set_hook(Elm_Object_Item *it,
234 const char *part,
235 const char *label)
236{
237 Elm_Naviframe_Text_Item_Pair *pair = NULL;
238 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
239 char buf[1024];
240
241 if (!part || !strcmp(part, "default"))
242 snprintf(buf, sizeof(buf), "elm.text.title");
243 else if (!strcmp("subtitle", part))
244 snprintf(buf, sizeof(buf), "elm.text.subtitle");
245 else
246 snprintf(buf, sizeof(buf), "%s", part);
247
248 EINA_INLIST_FOREACH(navi_it->text_list, pair)
249 if (!strcmp(buf, pair->part)) break;
250
251 if (!pair)
252 {
253 pair = ELM_NEW(Elm_Naviframe_Text_Item_Pair);
254 if (!pair)
255 {
256 ERR("Failed to allocate new text part of the item! : naviframe=%p",
257 WIDGET(navi_it));
258 return;
259 }
260 eina_stringshare_replace(&pair->part, buf);
261 navi_it->text_list = eina_inlist_append(navi_it->text_list,
262 EINA_INLIST_GET(pair));
263 }
264 elm_object_part_text_set(VIEW(navi_it), buf, label);
265
266 if (label)
267 {
268 snprintf(buf, sizeof(buf), "elm,state,%s,show", buf);
269 elm_object_signal_emit(VIEW(navi_it), buf, "elm");
270 }
271 else
272 {
273 snprintf(buf, sizeof(buf), "elm,state,%s,hide", buf);
274 elm_object_signal_emit(VIEW(navi_it), buf, "elm");
275 }
276
277 _sizing_eval(WIDGET(navi_it));
278}
279
280static const char *
281_item_text_get_hook(const Elm_Object_Item *it, const char *part)
282{
283 char buf[1024];
284
285 if (!part || !strcmp(part, "default"))
286 snprintf(buf, sizeof(buf), "elm.text.title");
287 else if (!strcmp("subtitle", part))
288 snprintf(buf, sizeof(buf), "elm.text.subtitle");
289 else
290 snprintf(buf, sizeof(buf), "%s", part);
291
292 return elm_object_part_text_get(VIEW(it), buf);
293}
294
295static void
296_item_content_set_hook(Elm_Object_Item *it,
297 const char *part,
298 Evas_Object *content)
299{
300 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
301
302 //specified parts
303 if (!part || !strcmp("default", part))
304 {
305 _item_content_set(navi_it, content);
306 return;
307 }
308 else if (!strcmp(part, "prev_btn"))
309 {
310 _title_prev_btn_set(navi_it, content, EINA_FALSE);
311 return;
312 }
313 else if (!strcmp(part, "next_btn"))
314 {
315 _title_next_btn_set(navi_it, content);
316 return;
317 }
318 else if (!strcmp(part, "icon"))
319 {
320 _title_icon_set(navi_it, content);
321 return;
322 }
323
324 //common part
325 _title_content_set(navi_it, part, content);
326}
327
328static Evas_Object *
329_item_content_get_hook(const Elm_Object_Item *it, const char *part)
330{
331 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
332
333 //specified parts
334 if (!part || !strcmp("default", part))
335 return navi_it->content;
336 else if (!strcmp(part, "prev_btn"))
337 return navi_it->title_prev_btn;
338 else if (!strcmp(part, "next_btn"))
339 return navi_it->title_next_btn;
340 else if (!strcmp(part, "icon"))
341 return navi_it->title_icon;
342
343 //common parts
344 return elm_object_part_content_get(VIEW(navi_it), part);
345}
346
347static Evas_Object *
348_item_content_unset_hook(Elm_Object_Item *it, const char *part)
349{
350 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
351
352 //specified parts
353 if (!part || !strcmp("default", part))
354 return _item_content_unset(navi_it);
355 else if (!strcmp(part, "prev_btn"))
356 return _title_prev_btn_unset(navi_it);
357 else if (!strcmp(part, "next_btn"))
358 return _title_next_btn_unset(navi_it);
359 else if (!strcmp(part, "icon"))
360 return _title_icon_unset(navi_it);
361
362 return _title_content_unset(navi_it, part);
363}
364
365static void
366_item_signal_emit_hook(Elm_Object_Item *it,
367 const char *emission,
368 const char *source)
369{
370 elm_object_signal_emit(VIEW(it), emission, source);
371}
372
373static void
374_item_title_visible_update(Elm_Naviframe_Item *navi_it)
375{
376 if (navi_it->title_visible)
377 elm_object_signal_emit(VIEW(navi_it), "elm,state,title,show", "elm");
378 else
379 elm_object_signal_emit(VIEW(navi_it), "elm,state,title,hide", "elm");
380}
381
382static void
383_sizing_eval(Evas_Object *obj)
384{
385 Widget_Data *wd;
386 Elm_Naviframe_Item *it;
387 Evas_Coord x, y, w, h;
388 Evas_Coord minw = -1, minh = -1;
389
390 wd = elm_widget_data_get(obj);
391 if (!wd) return;
392
393 evas_object_geometry_get(obj, &x, &y, &w, &h);
394
395 EINA_INLIST_FOREACH(wd->stack, it)
396 {
397 evas_object_move(VIEW(it), x, y);
398 evas_object_resize(VIEW(it), w, h);
399 edje_object_size_min_calc(elm_layout_edje_get(VIEW(it)),
400 &it->minw,
401 &it->minh);
402 if (it->minw > minw) minw = it->minw;
403 if (it->minh > minh) minh = it->minh;
404 }
405 evas_object_size_hint_min_set(obj, minw, minh);
406 evas_object_size_hint_max_set(obj, -1, -1);
407}
408
409static void
410_move(void *data __UNUSED__,
411 Evas *e __UNUSED__,
412 Evas_Object *obj,
413 void *event_info __UNUSED__)
414{
415 _sizing_eval(obj);
416}
417
418static void
419_resize(void *data __UNUSED__,
420 Evas *e __UNUSED__,
421 Evas_Object *obj,
422 void *event_info __UNUSED__)
423{
424 _sizing_eval(obj);
425}
426
427static void
428_title_clicked(void *data,
429 Evas_Object *obj __UNUSED__,
430 const char *emission __UNUSED__,
431 const char *source __UNUSED__)
432{
433 Elm_Naviframe_Item *it = data;
434 evas_object_smart_callback_call(WIDGET(it), SIG_TITLE_CLICKED, it);
435}
436
437static void
438_back_btn_clicked(void *data,
439 Evas_Object *obj,
440 void *event_info __UNUSED__)
441{
442/* Since edje has the event queue, clicked event could be happend multiple times
443 on some heavy environment. This callback del will prevent those scenario and
444 guarantee only one clicked for it's own page. */
445 evas_object_smart_callback_del(obj, "clicked", _back_btn_clicked);
446 elm_naviframe_item_pop(data);
447}
448
449static Evas_Object *
450_back_btn_new(Evas_Object *obj)
451{
452 Evas_Object *btn;
453 char buf[1024];
454 btn = elm_button_add(obj);
455 if (!btn) return NULL;
456 evas_object_smart_callback_add(btn, "clicked", _back_btn_clicked, obj);
457 snprintf(buf, sizeof(buf), "naviframe/back_btn/%s",
458 elm_widget_style_get(obj));
459 elm_object_style_set(btn, buf);
460 return btn;
461}
462
463static void _text_set_hook(Evas_Object *obj,
464 const char *part,
465 const char *label)
466{
467 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
468 if (!it) return;
469 elm_object_item_part_text_set(it, part, label);
470}
471
472static const char *_text_get_hook(const Evas_Object *obj, const char *part)
473{
474 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
475 if (!it) return NULL;
476 return elm_object_item_part_text_get(it, part);
477}
478
479static void
480_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
481{
482 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
483 if (!it) return;
484 elm_object_item_part_content_set(it, part, content);
485}
486
487static Evas_Object *
488_content_unset_hook(Evas_Object *obj, const char *part)
489{
490 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
491 if (!it) return NULL;
492 return elm_object_item_part_content_unset(it, part);
493}
494
495static Evas_Object *
496_content_get_hook(const Evas_Object *obj, const char *part)
497{
498 Elm_Object_Item *it = elm_naviframe_top_item_get(obj);
499 if (!it) return NULL;
500 return elm_object_item_part_content_get(it, part);
501}
502
503static void
504_title_content_del(void *data,
505 Evas *e __UNUSED__,
506 Evas_Object *obj __UNUSED__,
507 void *event_info __UNUSED__)
508{
509 char buf[1024];
510 Elm_Naviframe_Content_Item_Pair *pair = data;
511 Elm_Naviframe_Item *it = pair->it;
512 snprintf(buf, sizeof(buf), "elm,state,%s,hide", pair->part);
513 elm_object_signal_emit(VIEW(it), buf, "elm");
514 it->content_list = eina_inlist_remove(it->content_list,
515 EINA_INLIST_GET(pair));
516 eina_stringshare_del(pair->part);
517 free(pair);
518}
519
520static void
521_title_prev_btn_del(void *data,
522 Evas *e __UNUSED__,
523 Evas_Object *obj __UNUSED__,
524 void *event_info __UNUSED__)
525{
526 Elm_Naviframe_Item *it = data;
527 it->back_btn = EINA_FALSE;
528 it->title_prev_btn = NULL;
529 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
530}
531
532static void
533_title_next_btn_del(void *data,
534 Evas *e __UNUSED__,
535 Evas_Object *obj __UNUSED__,
536 void *event_info __UNUSED__)
537{
538 Elm_Naviframe_Item *it = data;
539 it->title_next_btn = NULL;
540 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
541}
542
543static void
544_title_icon_del(void *data,
545 Evas *e __UNUSED__,
546 Evas_Object *obj __UNUSED__,
547 void *event_info __UNUSED__)
548{
549 Elm_Naviframe_Item *it = data;
550 it->title_icon = NULL;
551 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
552}
553
554static void
555_item_content_del(void *data,
556 Evas *e __UNUSED__,
557 Evas_Object *obj __UNUSED__,
558 void *event_info __UNUSED__)
559{
560 Elm_Naviframe_Item *it = data;
561 it->content = NULL;
562 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
563}
564
565static void
566_title_content_set(Elm_Naviframe_Item *it,
567 const char *part,
568 Evas_Object *content)
569{
570 char buf[1024];
571 Elm_Naviframe_Content_Item_Pair *pair = NULL;
572 Evas_Object *prev_content = NULL;
573
574 EINA_INLIST_FOREACH(it->content_list, pair)
575 if (!strcmp(part, pair->part)) break;
576
577 if (pair)
578 {
579 prev_content = elm_object_part_content_get(VIEW(it), part);
580 if (prev_content != content)
581 {
582 if (content)
583 {
584 evas_object_event_callback_del(prev_content,
585 EVAS_CALLBACK_DEL,
586 _title_content_del);
587 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
588 elm_object_signal_emit(VIEW(it), buf, "elm");
589 }
590 evas_object_del(prev_content);
591 if (!content) return;
592 }
593 }
594 else
595 {
596 if (!content) return;
597 pair = ELM_NEW(Elm_Naviframe_Content_Item_Pair);
598 if (!pair)
599 {
600 ERR("Failed to allocate new content part of the item! : naviframe=%p", WIDGET(it));
601 return;
602 }
603 pair->it = it;
604 eina_stringshare_replace(&pair->part, part);
605 it->content_list = eina_inlist_append(it->content_list,
606 EINA_INLIST_GET(pair));
607 }
608 if (prev_content != content)
609 {
610 evas_object_event_callback_add(content,
611 EVAS_CALLBACK_DEL,
612 _title_content_del,
613 pair);
614 }
615 elm_object_part_content_set(VIEW(it), part, content);
616 snprintf(buf, sizeof(buf), "elm,state,%s,show", part);
617 elm_object_signal_emit(VIEW(it), buf, "elm");
618
619 _sizing_eval(WIDGET(it));
620}
621
622static void
623_title_prev_btn_set(Elm_Naviframe_Item *it,
624 Evas_Object *btn,
625 Eina_Bool back_btn)
626{
627 if (it->title_prev_btn == btn) return;
628 if (it->title_prev_btn) evas_object_del(it->title_prev_btn);
629 it->title_prev_btn = btn;
630 if (!btn) return;
631
632 evas_object_event_callback_add(btn,
633 EVAS_CALLBACK_DEL,
634 _title_prev_btn_del,
635 it);
636 elm_object_part_content_set(VIEW(it), "elm.swallow.prev_btn", btn);
637 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,show", "elm");
638 it->back_btn = back_btn;
639
640 _sizing_eval(WIDGET(it));
641}
642
643static void
644_title_next_btn_set(Elm_Naviframe_Item *it, Evas_Object *btn)
645{
646 if (it->title_next_btn == btn) return;
647 if (it->title_next_btn) evas_object_del(it->title_next_btn);
648 it->title_next_btn = btn;
649 if (!btn) return;
650
651 evas_object_event_callback_add(btn,
652 EVAS_CALLBACK_DEL,
653 _title_next_btn_del,
654 it);
655 elm_object_part_content_set(VIEW(it), "elm.swallow.next_btn", btn);
656 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,show", "elm");
657
658 _sizing_eval(WIDGET(it));
659}
660
661static void
662_title_icon_set(Elm_Naviframe_Item *it, Evas_Object *icon)
663{
664 if (it->title_icon == icon) return;
665 if (it->title_icon) evas_object_del(it->title_icon);
666 it->title_icon = icon;
667 if (!icon) return;
668
669 evas_object_event_callback_add(icon,
670 EVAS_CALLBACK_DEL,
671 _title_icon_del,
672 it);
673 elm_object_part_content_set(VIEW(it), "elm.swallow.icon", icon);
674 elm_object_signal_emit(VIEW(it), "elm,state,icon,show", "elm");
675
676 _sizing_eval(WIDGET(it));
677}
678
679static Evas_Object *
680_item_content_unset(Elm_Naviframe_Item *it)
681{
682 Evas_Object *content = it->content;
683 if (!content) return NULL;
684
685 elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
686 elm_object_signal_emit(VIEW(it), "elm,state,content,hide", "elm");
687 evas_object_event_callback_del(content,
688 EVAS_CALLBACK_DEL,
689 _item_content_del);
690 _sizing_eval(WIDGET(it));
691
692 it->content = NULL;
693 return content;
694}
695
696static Evas_Object *
697_title_prev_btn_unset(Elm_Naviframe_Item *it)
698{
699 Evas_Object *content = it->title_prev_btn;
700 if (!content) return NULL;
701
702 elm_object_part_content_unset(VIEW(it), "elm.swallow.prev_btn");
703 elm_object_signal_emit(VIEW(it), "elm,state,prev_btn,hide", "elm");
704 evas_object_event_callback_del(content,
705 EVAS_CALLBACK_DEL,
706 _title_prev_btn_del);
707 _sizing_eval(WIDGET(it));
708
709 it->title_prev_btn = NULL;
710 return content;
711}
712
713static Evas_Object *
714_title_next_btn_unset(Elm_Naviframe_Item *it)
715{
716 Evas_Object *content = it->title_next_btn;
717 if (!content) return NULL;
718
719 elm_object_part_content_unset(VIEW(it), "elm.swallow.next_btn");
720 elm_object_signal_emit(VIEW(it), "elm,state,next_btn,hide", "elm");
721 evas_object_event_callback_del(content,
722 EVAS_CALLBACK_DEL,
723 _title_next_btn_del);
724 _sizing_eval(WIDGET(it));
725
726 it->title_next_btn = NULL;
727 return content;
728}
729
730static Evas_Object *
731_title_icon_unset(Elm_Naviframe_Item *it)
732{
733 Evas_Object *content = it->title_icon;
734 if (!content) return NULL;
735
736 elm_object_part_content_unset(VIEW(it), "elm.swallow.icon");
737 elm_object_signal_emit(VIEW(it), "elm,state,icon,hide", "elm");
738 evas_object_event_callback_del(content,
739 EVAS_CALLBACK_DEL,
740 _title_icon_del);
741 _sizing_eval(WIDGET(it));
742 it->title_icon = NULL;
743
744 return content;
745}
746
747static Evas_Object *
748_title_content_unset(Elm_Naviframe_Item *it, const char *part)
749{
750 Elm_Naviframe_Content_Item_Pair *pair = NULL;
751 char buf[1028];
752 Evas_Object *content = NULL;
753
754 EINA_INLIST_FOREACH(it->content_list, pair)
755 {
756 if (!strcmp(part, pair->part))
757 {
758 content = elm_object_part_content_get(VIEW(it), part);
759 eina_stringshare_del(pair->part);
760 it->content_list = eina_inlist_remove(it->content_list,
761 EINA_INLIST_GET(pair));
762 free(pair);
763 break;
764 }
765 }
766
767 if (!content) return NULL;
768
769 elm_object_part_content_unset(VIEW(it), part);
770 snprintf(buf, sizeof(buf), "elm,state,%s,hide", part);
771 elm_object_signal_emit(VIEW(it), buf, "elm");
772 evas_object_event_callback_del(content,
773 EVAS_CALLBACK_DEL,
774 _title_content_del);
775 _sizing_eval(WIDGET(it));
776
777 return content;
778}
779
780static void
781_item_del(Elm_Naviframe_Item *it)
782{
783 Widget_Data *wd;
784 Elm_Naviframe_Content_Item_Pair *content_pair;
785 Elm_Naviframe_Text_Item_Pair *text_pair;
786 Evas_Object *content;
787
788 if (!it) return;
789
790 wd = elm_widget_data_get(WIDGET(it));
791 if (!wd) return;
792
793 while (it->content_list)
794 {
795 content_pair =
796 EINA_INLIST_CONTAINER_GET(it->content_list,
797 Elm_Naviframe_Content_Item_Pair);
798 content = elm_object_part_content_get(VIEW(it), content_pair->part);
799 evas_object_event_callback_del(content,
800 EVAS_CALLBACK_DEL,
801 _title_content_del);
802 eina_stringshare_del(content_pair->part);
803 it->content_list = eina_inlist_remove(it->content_list,
804 it->content_list);
805 free(content_pair);
806 }
807
808 while (it->text_list)
809 {
810 text_pair = EINA_INLIST_CONTAINER_GET(it->text_list,
811 Elm_Naviframe_Text_Item_Pair);
812 eina_stringshare_del(text_pair->part);
813 it->text_list = eina_inlist_remove(it->text_list,
814 it->text_list);
815 free(text_pair);
816 }
817
818 eina_stringshare_del(it->style);
819
820 if (wd->preserve && it->content)
821 {
822 elm_object_part_content_unset(VIEW(it), "elm.swallow.content");
823 evas_object_event_callback_del(it->content,
824 EVAS_CALLBACK_DEL,
825 _item_content_del);
826 }
827}
828
829static Eina_Bool
830_item_del_pre_hook(Elm_Object_Item *it)
831{
832 Elm_Naviframe_Item *navi_it;
833 Widget_Data *wd;
834
835 navi_it =(Elm_Naviframe_Item *)it;
836 wd = elm_widget_data_get(WIDGET(navi_it));
837 if (!wd) return EINA_FALSE;
838
839 if (it == elm_naviframe_top_item_get(WIDGET(navi_it)))
840 {
841 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
842 _item_del(navi_it);
843 //If the item is only one, the stack will be empty
844 if (!wd->stack) return EINA_TRUE;
845 navi_it = EINA_INLIST_CONTAINER_GET(wd->stack->last,
846 Elm_Naviframe_Item);
847 evas_object_show(VIEW(navi_it));
848 evas_object_raise(VIEW(navi_it));
849 elm_object_signal_emit(VIEW(navi_it), "elm,state,visible", "elm");
850 }
851 else
852 {
853 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(navi_it));
854 _item_del(navi_it);
855 }
856
857 return EINA_TRUE;
858}
859
860static void
861_pushed_finished(void *data,
862 Evas_Object *obj __UNUSED__,
863 const char *emission __UNUSED__,
864 const char *source __UNUSED__)
865{
866 Widget_Data *wd;
867 Elm_Naviframe_Item *it = data;
868 if (!it) return;
869
870 wd = elm_widget_data_get(WIDGET(it));
871 if (!wd) return;
872
873 evas_object_hide(VIEW(it));
874
875 if (it->content)
876 elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable);
877
878 if (wd->freeze_events)
879 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
880}
881
882static void
883_popped_finished(void *data,
884 Evas_Object *obj __UNUSED__,
885 const char *emission __UNUSED__,
886 const char *source __UNUSED__)
887{
888 Widget_Data *wd;
889 Elm_Naviframe_Item *it = data;
890 if (!it) return;
891
892 wd = elm_widget_data_get(WIDGET(it));
893 if (!wd) return;
894
895 if (wd->preserve && it->content)
896 elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable);
897
898 _item_del(data);
899
900 elm_widget_item_free(data);
901}
902
903static void
904_show_finished(void *data,
905 Evas_Object *obj __UNUSED__,
906 const char *emission __UNUSED__,
907 const char *source __UNUSED__)
908{
909 Elm_Naviframe_Item *it;
910 Widget_Data *wd;
911
912 it = data;
913 if (!it) return;
914 wd = elm_widget_data_get(WIDGET(it));
915 if (!wd) return;
916
917 elm_widget_tree_unfocusable_set(it->content, it->content_unfocusable);
918
919 evas_object_smart_callback_call(WIDGET(it),
920 SIG_TRANSITION_FINISHED,
921 data);
922 if (wd->freeze_events)
923 evas_object_freeze_events_set(VIEW(it), EINA_FALSE);
924}
925
926static void
927_changed_size_hints(void *data,
928 Evas *e __UNUSED__,
929 Evas_Object *obj __UNUSED__,
930 void *event_info __UNUSED__)
931{
932 _sizing_eval(data);
933}
934
935static void
936_item_content_set(Elm_Naviframe_Item *navi_it, Evas_Object *content)
937{
938 if (navi_it->content == content) return;
939 if (navi_it->content) evas_object_del(navi_it->content);
940 elm_object_part_content_set(VIEW(navi_it), "elm.swallow.content", content);
941
942 if (content)
943 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
944 else
945 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,hide", "elm");
946
947 evas_object_event_callback_add(content,
948 EVAS_CALLBACK_DEL,
949 _item_content_del,
950 navi_it);
951 navi_it->content = content;
952 _sizing_eval(WIDGET(navi_it));
953}
954
955//FIXME: need to handle if this function is called while transition
956static void
957_item_style_set(Elm_Naviframe_Item *navi_it, const char *item_style)
958{
959 Elm_Naviframe_Content_Item_Pair *content_pair;
960 Elm_Naviframe_Text_Item_Pair *text_pair;
961 Widget_Data *wd;
962
963 char buf[256];
964
965 if (!item_style)
966 {
967 strcpy(buf, "item/basic");
968 eina_stringshare_replace(&navi_it->style, "basic");
969 }
970 else
971 {
972 snprintf(buf, sizeof(buf), "item/%s", item_style);
973 eina_stringshare_replace(&navi_it->style, item_style);
974 }
975 elm_layout_theme_set(VIEW(navi_it),
976 "naviframe",
977 buf,
978 elm_widget_style_get(WIDGET(navi_it)));
979 //recover item
980 EINA_INLIST_FOREACH(navi_it->text_list, text_pair)
981 _item_text_set_hook((Elm_Object_Item *) navi_it,
982 text_pair->part,
983 elm_object_part_text_get(VIEW(navi_it),
984 text_pair->part));
985
986 EINA_INLIST_FOREACH(navi_it->content_list, content_pair)
987 _item_content_set_hook((Elm_Object_Item *) navi_it,
988 content_pair->part,
989 elm_object_part_content_get(VIEW(navi_it),
990 content_pair->part));
991 //content
992 if (navi_it->content)
993 elm_object_signal_emit(VIEW(navi_it), "elm,state,content,show", "elm");
994
995 //prev button
996 if (navi_it->title_prev_btn)
997 elm_object_signal_emit(VIEW(navi_it), "elm,state,prev_btn,show", "elm");
998
999 //next button
1000 if (navi_it->title_next_btn)
1001 elm_object_signal_emit(VIEW(navi_it), "elm,state,next_btn,show", "elm");
1002
1003 _sizing_eval(WIDGET(navi_it));
1004
1005 wd = elm_widget_data_get(WIDGET(navi_it));
1006 if (!wd) return;
1007
1008 if (wd->freeze_events)
1009 evas_object_freeze_events_set(VIEW(navi_it), EINA_FALSE);
1010}
1011
1012static Elm_Naviframe_Item *
1013_item_new(Evas_Object *obj,
1014 const char *title_label,
1015 Evas_Object *prev_btn,
1016 Evas_Object *next_btn,
1017 Evas_Object *content,
1018 const char *item_style)
1019{
1020 Widget_Data *wd = elm_widget_data_get(obj);
1021
1022 //create item
1023 Elm_Naviframe_Item *it = elm_widget_item_new(obj, Elm_Naviframe_Item);
1024 if (!it)
1025 {
1026 ERR("Failed to allocate new item! : naviframe=%p", obj);
1027 return NULL;
1028 }
1029
1030 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1031 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1032 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1033 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1034 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1035 elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1036 elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
1037
1038 //item base layout
1039 VIEW(it) = elm_layout_add(obj);
1040 evas_object_smart_member_add(VIEW(it), obj);
1041
1042 evas_object_event_callback_add(VIEW(it),
1043 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1044 _changed_size_hints,
1045 obj);
1046 elm_object_signal_callback_add(VIEW(it),
1047 "elm,action,show,finished",
1048 "",
1049 _show_finished, it);
1050 elm_object_signal_callback_add(VIEW(it),
1051 "elm,action,pushed,finished",
1052 "",
1053 _pushed_finished, it);
1054 elm_object_signal_callback_add(VIEW(it),
1055 "elm,action,popped,finished",
1056 "",
1057 _popped_finished, it);
1058 elm_object_signal_callback_add(VIEW(it),
1059 "elm,action,title,clicked",
1060 "",
1061 _title_clicked, it);
1062
1063 _item_style_set(it, item_style);
1064 _item_text_set_hook((Elm_Object_Item *)it, "elm.text.title", title_label);
1065
1066 //title buttons
1067 if ((!prev_btn) && wd->auto_pushed && eina_inlist_count(wd->stack))
1068 {
1069 prev_btn = _back_btn_new(obj);
1070 _title_prev_btn_set(it, prev_btn, EINA_TRUE);
1071 }
1072 else
1073 _title_prev_btn_set(it, prev_btn, EINA_FALSE);
1074
1075 _title_next_btn_set(it, next_btn);
1076 _item_content_set(it, content);
1077 it->title_visible = EINA_TRUE;
1078 return it;
1079}
1080
1081static Eina_Bool
1082_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
1083{
1084 Eina_Bool ret;
1085 Elm_Naviframe_Item *top_it;
1086 Eina_List *l = NULL;
1087 Widget_Data *wd = elm_widget_data_get(obj);
1088 void *(*list_data_get)(const Eina_List *list);
1089 if (!wd) return EINA_FALSE;
1090
1091 top_it = (Elm_Naviframe_Item *)elm_naviframe_top_item_get(obj);
1092 if (!top_it) return EINA_FALSE;
1093
1094 list_data_get = eina_list_data_get;
1095
1096 //Forcus order: prev button, next button, contents
1097 if (top_it->title_prev_btn)
1098 l = eina_list_append(l, top_it->title_prev_btn);
1099 if (top_it->title_next_btn)
1100 l = eina_list_append(l, top_it->title_next_btn);
1101 l = eina_list_append(l, VIEW(top_it));
1102
1103 ret = elm_widget_focus_list_next_get(obj, l, list_data_get, dir, next);
1104 eina_list_free(l);
1105 return ret;
1106}
1107
1108EAPI Evas_Object *
1109elm_naviframe_add(Evas_Object *parent)
1110{
1111 Evas_Object *obj;
1112 Evas *e;
1113 Widget_Data *wd;
1114
1115 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1116 ELM_SET_WIDTYPE(widtype, "naviframe");
1117 elm_widget_type_set(obj, "naviframe");
1118 elm_widget_sub_object_add(parent, obj);
1119 elm_widget_data_set(obj, wd);
1120 elm_widget_del_hook_set(obj, _del_hook);
1121 elm_widget_disable_hook_set(obj, _disable_hook);
1122 elm_widget_theme_hook_set(obj, _theme_hook);
1123 elm_widget_text_set_hook_set(obj, _text_set_hook);
1124 elm_widget_text_get_hook_set(obj, _text_get_hook);
1125 elm_widget_content_set_hook_set(obj, _content_set_hook);
1126 elm_widget_content_get_hook_set(obj, _content_get_hook);
1127 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1128 elm_widget_signal_emit_hook_set(obj, _emit_hook);
1129 elm_widget_can_focus_set(obj, EINA_FALSE);
1130 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1131
1132 //base
1133 //FIXME: Is this base layout really needed?
1134 wd->base = elm_layout_add(obj);
1135 evas_object_event_callback_add(wd->base,
1136 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1137 _changed_size_hints,
1138 obj);
1139 elm_widget_resize_object_set(obj, wd->base);
1140 elm_layout_theme_set(wd->base, "naviframe", "base", "default");
1141
1142 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, obj);
1143 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1144 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1145
1146 wd->auto_pushed = EINA_TRUE;
1147 wd->freeze_events = EINA_TRUE;
1148
1149 return obj;
1150}
1151
1152EAPI Elm_Object_Item *
1153elm_naviframe_item_push(Evas_Object *obj,
1154 const char *title_label,
1155 Evas_Object *prev_btn,
1156 Evas_Object *next_btn,
1157 Evas_Object *content,
1158 const char *item_style)
1159{
1160 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1161 Widget_Data *wd;
1162 Elm_Naviframe_Item *prev_it, *it;
1163
1164 wd = elm_widget_data_get(obj);
1165 if (!wd) return NULL;
1166
1167 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1168 if (!it) return NULL;
1169
1170 evas_object_show(VIEW(it));
1171
1172 prev_it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1173 if (prev_it)
1174 {
1175 if (wd->freeze_events)
1176 {
1177 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1178 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1179 }
1180 elm_object_signal_emit(VIEW(prev_it), "elm,state,cur,pushed", "elm");
1181 elm_object_signal_emit(VIEW(it), "elm,state,new,pushed", "elm");
1182 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1183 if (prev_it->content)
1184 {
1185 prev_it->content_unfocusable = elm_widget_tree_unfocusable_get(prev_it->content);
1186 elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE);
1187 }
1188 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1189 }
1190 wd->stack = eina_inlist_append(wd->stack, EINA_INLIST_GET(it));
1191 _sizing_eval(obj);
1192 return (Elm_Object_Item *)it;
1193}
1194
1195EAPI Elm_Object_Item *
1196elm_naviframe_item_insert_before(Evas_Object *obj,
1197 Elm_Object_Item *before,
1198 const char *title_label,
1199 Evas_Object *prev_btn,
1200 Evas_Object *next_btn,
1201 Evas_Object *content,
1202 const char *item_style)
1203{
1204 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1205 ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1206 Elm_Naviframe_Item *it;
1207 Widget_Data *wd;
1208
1209 wd = elm_widget_data_get(obj);
1210 if (!wd) return NULL;
1211
1212 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1213 if (!it) return NULL;
1214
1215 wd->stack =
1216 eina_inlist_prepend_relative(wd->stack,
1217 EINA_INLIST_GET(it),
1218 EINA_INLIST_GET(((Elm_Naviframe_Item *) before)));
1219 _sizing_eval(obj);
1220 return (Elm_Object_Item *)it;
1221}
1222
1223EAPI Elm_Object_Item *
1224elm_naviframe_item_insert_after(Evas_Object *obj,
1225 Elm_Object_Item *after,
1226 const char *title_label,
1227 Evas_Object *prev_btn,
1228 Evas_Object *next_btn,
1229 Evas_Object *content,
1230 const char *item_style)
1231{
1232 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1233 ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1234 Elm_Naviframe_Item *it;
1235 Widget_Data *wd;
1236 Eina_Bool top_inserted;
1237
1238 wd = elm_widget_data_get(obj);
1239 if (!wd) return NULL;
1240
1241 it = _item_new(obj, title_label, prev_btn, next_btn, content, item_style);
1242 if (!it) return NULL;
1243
1244 if (elm_naviframe_top_item_get(obj) == after) top_inserted = EINA_TRUE;
1245
1246 wd->stack =
1247 eina_inlist_append_relative(wd->stack,
1248 EINA_INLIST_GET(it),
1249 EINA_INLIST_GET(((Elm_Naviframe_Item *) after)));
1250 if (top_inserted)
1251 {
1252 evas_object_show(VIEW(it));
1253 evas_object_hide(VIEW(after));
1254 }
1255
1256 _sizing_eval(obj);
1257
1258 return (Elm_Object_Item *)it;
1259}
1260
1261EAPI Evas_Object *
1262elm_naviframe_item_pop(Evas_Object *obj)
1263{
1264 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1265 Elm_Naviframe_Item *it, *prev_it = NULL;
1266 Widget_Data *wd;
1267 Evas_Object *content = NULL;
1268
1269 wd = elm_widget_data_get(obj);
1270 if (!wd) return NULL;
1271
1272 it = (Elm_Naviframe_Item *) elm_naviframe_top_item_get(obj);
1273 if (!it) return NULL;
1274 if (wd->preserve)
1275 content = it->content;
1276
1277 if (it->content)
1278 {
1279 it->content_unfocusable = elm_widget_tree_unfocusable_get(it->content);
1280 elm_widget_tree_unfocusable_set(it->content, EINA_TRUE);
1281 }
1282
1283 if (wd->stack->last->prev)
1284 prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1285 Elm_Naviframe_Item);
1286 wd->stack = eina_inlist_remove(wd->stack, EINA_INLIST_GET(it));
1287 if (prev_it)
1288 {
1289 if (wd->freeze_events)
1290 {
1291 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1292 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1293 }
1294 elm_object_signal_emit(VIEW(it), "elm,state,cur,popped", "elm");
1295 evas_object_show(VIEW(prev_it));
1296 elm_object_signal_emit(VIEW(prev_it),
1297 "elm,state,prev,popped",
1298 "elm");
1299 edje_object_message_signal_process(elm_layout_edje_get(VIEW(it)));
1300 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1301 }
1302 else
1303 {
1304 _item_del(it);
1305 elm_widget_item_free(it);
1306 }
1307
1308 return content;
1309}
1310
1311EAPI void
1312elm_naviframe_item_pop_to(Elm_Object_Item *it)
1313{
1314 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1315 Elm_Naviframe_Item *navi_it;
1316 Widget_Data *wd;
1317 Eina_Inlist *l, *prev_l;
1318
1319 navi_it = (Elm_Naviframe_Item *)it;
1320 wd = elm_widget_data_get(WIDGET(navi_it));
1321 if (!wd) return;
1322
1323 if (it == elm_naviframe_top_item_get(WIDGET(navi_it))) return;
1324
1325 l = wd->stack->last->prev;
1326
1327 while (l)
1328 {
1329 if (EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item) ==
1330 ((Elm_Naviframe_Item *)it)) break;
1331 prev_l = l->prev;
1332 wd->stack = eina_inlist_remove(wd->stack, l);
1333 _item_del(EINA_INLIST_CONTAINER_GET(l, Elm_Naviframe_Item));
1334 elm_widget_item_free(EINA_INLIST_CONTAINER_GET(l,
1335 Elm_Naviframe_Item));
1336 l = prev_l;
1337 }
1338 elm_naviframe_item_pop(WIDGET(navi_it));
1339}
1340
1341EAPI void
1342elm_naviframe_item_promote(Elm_Object_Item *it)
1343{
1344 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1345 Elm_Naviframe_Item *navi_it;
1346 Elm_Naviframe_Item *prev_it;
1347 Widget_Data *wd;
1348
1349 navi_it = (Elm_Naviframe_Item *)it;
1350 wd = elm_widget_data_get(navi_it->base.widget);
1351 if (!wd) return;
1352
1353 if (it == elm_naviframe_top_item_get(navi_it->base.widget)) return;
1354 wd->stack = eina_inlist_demote(wd->stack, EINA_INLIST_GET(navi_it));
1355 prev_it = EINA_INLIST_CONTAINER_GET(wd->stack->last->prev,
1356 Elm_Naviframe_Item);
1357 if (prev_it->content)
1358 {
1359 prev_it->content_unfocusable = elm_widget_tree_unfocusable_get(prev_it->content);
1360 elm_widget_tree_unfocusable_set(prev_it->content, EINA_TRUE);
1361 }
1362
1363 if (wd->freeze_events)
1364 {
1365 evas_object_freeze_events_set(VIEW(it), EINA_TRUE);
1366 evas_object_freeze_events_set(VIEW(prev_it), EINA_TRUE);
1367 }
1368 elm_object_signal_emit(VIEW(prev_it),
1369 "elm,state,cur,pushed",
1370 "elm");
1371 evas_object_show(VIEW(navi_it));
1372 evas_object_raise(VIEW(navi_it));
1373 elm_object_signal_emit(VIEW(navi_it),
1374 "elm,state,new,pushed",
1375 "elm");
1376 edje_object_message_signal_process(elm_layout_edje_get(VIEW(prev_it)));
1377 edje_object_message_signal_process(elm_layout_edje_get(VIEW(navi_it)));
1378}
1379
1380EAPI void
1381elm_naviframe_item_simple_promote(Evas_Object *obj, Evas_Object *content)
1382{
1383 ELM_CHECK_WIDTYPE(obj, widtype);
1384 Widget_Data *wd = elm_widget_data_get(obj);
1385 if (!wd) return;
1386 Elm_Naviframe_Item *itr;
1387 EINA_INLIST_FOREACH(wd->stack, itr)
1388 {
1389 if (elm_object_item_content_get((Elm_Object_Item *)itr) == content)
1390 {
1391 elm_naviframe_item_promote((Elm_Object_Item *)itr);
1392 break;
1393 }
1394 }
1395}
1396
1397
1398EAPI void
1399elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve)
1400{
1401 ELM_CHECK_WIDTYPE(obj, widtype);
1402 Widget_Data *wd = elm_widget_data_get(obj);
1403 if (!wd) return;
1404 wd->preserve = !!preserve;
1405}
1406
1407EAPI Eina_Bool
1408elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj)
1409{
1410 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1411 Widget_Data *wd = elm_widget_data_get(obj);
1412 if (!wd) return EINA_FALSE;
1413 return wd->preserve;
1414}
1415
1416EAPI Elm_Object_Item*
1417elm_naviframe_top_item_get(const Evas_Object *obj)
1418{
1419 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1420 Widget_Data *wd = elm_widget_data_get(obj);
1421 if ((!wd) || (!wd->stack)) return NULL;
1422 return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack->last,
1423 Elm_Naviframe_Item));
1424}
1425
1426EAPI Elm_Object_Item*
1427elm_naviframe_bottom_item_get(const Evas_Object *obj)
1428{
1429 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1430 Widget_Data *wd = elm_widget_data_get(obj);
1431 if ((!wd) || (!wd->stack)) return NULL;
1432 return (Elm_Object_Item *) (EINA_INLIST_CONTAINER_GET(wd->stack,
1433 Elm_Naviframe_Item));
1434}
1435
1436EAPI void
1437elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style)
1438{
1439 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1440 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1441
1442 if (item_style)
1443 if (!strcmp(item_style, navi_it->style)) return;
1444
1445 if (!item_style)
1446 if (!strcmp("basic", navi_it->style)) return;
1447
1448 _item_style_set(navi_it, item_style);
1449 _item_title_visible_update(navi_it);
1450}
1451
1452EAPI const char *
1453elm_naviframe_item_style_get(const Elm_Object_Item *it)
1454{
1455 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1456 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1457 return navi_it->style;
1458}
1459
1460EAPI void
1461elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible)
1462{
1463 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1464 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1465
1466 visible = !!visible;
1467 if (navi_it->title_visible == visible) return;
1468
1469 navi_it->title_visible = visible;
1470 _item_title_visible_update(navi_it);
1471}
1472
1473EAPI Eina_Bool
1474elm_naviframe_item_title_visible_get(const Elm_Object_Item *it)
1475{
1476 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1477 Elm_Naviframe_Item *navi_it = (Elm_Naviframe_Item *)it;
1478 return navi_it->title_visible;
1479}
1480
1481EAPI void
1482elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed)
1483{
1484 ELM_CHECK_WIDTYPE(obj, widtype);
1485 Widget_Data *wd = elm_widget_data_get(obj);
1486 if (!wd) return;
1487 wd->auto_pushed = !!auto_pushed;
1488}
1489
1490EAPI Eina_Bool
1491elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj)
1492{
1493 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1494 Widget_Data *wd = elm_widget_data_get(obj);
1495 if (!wd) return EINA_FALSE;
1496 return wd->auto_pushed;
1497}
1498
1499EAPI Eina_List *
1500elm_naviframe_items_get(const Evas_Object *obj)
1501{
1502 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1503 Widget_Data *wd = elm_widget_data_get(obj);
1504 if (!wd) return NULL;
1505 Eina_List *ret = NULL;
1506 Elm_Naviframe_Item *itr;
1507 EINA_INLIST_FOREACH(wd->stack, itr)
1508 ret = eina_list_append(ret, itr);
1509 return ret;
1510}
1511
1512EAPI void
1513elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled)
1514{
1515 ELM_CHECK_WIDTYPE(obj, widtype);
1516 Widget_Data *wd = elm_widget_data_get(obj);
1517 if (!wd) return;
1518 enabled = !!enabled;
1519 if (wd->freeze_events == !enabled) return;
1520 wd->freeze_events = !enabled;
1521}
1522
1523EAPI Eina_Bool
1524elm_naviframe_event_enabled_get(const Evas_Object *obj)
1525{
1526 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1527 Widget_Data *wd = elm_widget_data_get(obj);
1528 if (!wd) return EINA_FALSE;
1529 return !wd->freeze_events;
1530}
diff --git a/libraries/elementary/src/lib/elc_naviframe.h b/libraries/elementary/src/lib/elc_naviframe.h
new file mode 100644
index 0000000..c17147c
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_naviframe.h
@@ -0,0 +1,406 @@
1/**
2 * @defgroup Naviframe Naviframe
3 * @ingroup Elementary
4 *
5 * @brief Naviframe is a kind of view manager for the applications.
6 *
7 * Naviframe provides functions to switch different pages with stack
8 * mechanism. It means if one page(item) needs to be changed to the new one,
9 * then naviframe would push the new page to its internal stack. Of course,
10 * it can be back to the previous page by popping the top page. Naviframe
11 * provides some transition effect while the pages are switching (same as
12 * pager).
13 *
14 * Since each item could keep the different styles, users could keep the
15 * same look & feel for the pages or different styles for the items in it's
16 * application.
17 *
18 * Default content parts of the naviframe that you can use content hooks for
19 * are:
20 * @li "default" - The main content of the current page
21 * @li "icon" - An icon in the title area of the current page
22 * @li "prev_btn" - A button of the current page to go to the previous page
23 * @li "next_btn" - A button of the current page to go to the next page
24 *
25 * Default text parts of the naviframe that you can use for are:
26 * @li "default" - Title label in the title area of the current page
27 * @li "subtitle" - Sub-title label in the title area of the current page
28 *
29 * Signals that you can add callbacks for are:
30 * @li "transition,finished" - When the transition is finished in changing the
31 * item
32 * @li "title,clicked" - User clicked title area
33 *
34 * Default content parts of the naviframe items that you can use content hooks
35 * for are:
36 * @li "default" - The main content of the page
37 * @li "icon" - An icon in the title area
38 * @li "prev_btn" - A button to go to the previous page
39 * @li "next_btn" - A button to go to the next page
40 *
41 * Default text parts of the naviframe items that you can use for are:
42 * @li "default" - Title label in the title area
43 * @li "subtitle" - Sub-title label in the title area
44 *
45 * Supported elm_object common APIs.
46 * @li @ref elm_object_signal_emit
47 * @li @ref elm_object_part_text_set
48 * @li @ref elm_object_part_text_get
49 * @li @ref elm_object_part_content_set
50 * @li @ref elm_object_part_content_get
51 * @li @ref elm_object_part_content_unset
52 *
53 * Supported elm_object_item common APIs.
54 * @li @ref elm_object_item_part_text_set
55 * @li @ref elm_object_item_part_text_get
56 * @li @ref elm_object_item_part_content_set
57 * @li @ref elm_object_item_part_content_get
58 * @li @ref elm_object_item_part_content_unset
59 * @li @ref elm_object_item_signal_emit
60 */
61
62/**
63 * @addtogroup Naviframe
64 * @{
65 */
66
67/**
68 * @brief Add a new Naviframe object to the parent.
69 *
70 * @param parent Parent object
71 * @return New object or @c NULL, if it cannot be created
72 *
73 * @ingroup Naviframe
74 */
75EAPI Evas_Object *elm_naviframe_add(Evas_Object *parent);
76
77/**
78 * @brief Push a new item to the top of the naviframe stack (and show it).
79 *
80 * @param obj The naviframe object
81 * @param title_label The label in the title area. The name of the title
82 * label part is "elm.text.title"
83 * @param prev_btn The button to go to the previous item. If it is NULL,
84 * then naviframe will create a back button automatically. The name of
85 * the prev_btn part is "elm.swallow.prev_btn"
86 * @param next_btn The button to go to the next item. Or It could be just an
87 * extra function button. The name of the next_btn part is
88 * "elm.swallow.next_btn"
89 * @param content The main content object. The name of content part is
90 * "elm.swallow.content"
91 * @param item_style The current item style name. @c NULL would be default.
92 * @return The created item or @c NULL upon failure.
93 *
94 * The item pushed becomes one page of the naviframe, this item will be
95 * deleted when it is popped.
96 *
97 * @see also elm_naviframe_item_style_set()
98 * @see also elm_naviframe_item_insert_before()
99 * @see also elm_naviframe_item_insert_after()
100 *
101 * The following styles are available for this item:
102 * @li @c "default"
103 *
104 * @ingroup Naviframe
105 */
106EAPI Elm_Object_Item *elm_naviframe_item_push(Evas_Object *obj, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style);
107
108/**
109 * @brief Insert a new item into the naviframe before item @p before.
110 *
111 * @param obj The naviframe object
112 * @param before The naviframe item to insert before.
113 * @param title_label The label in the title area. The name of the title
114 * label part is "elm.text.title"
115 * @param prev_btn The button to go to the previous item. If it is NULL,
116 * then naviframe will create a back button automatically. The name of
117 * the prev_btn part is "elm.swallow.prev_btn"
118 * @param next_btn The button to go to the next item. Or It could be just an
119 * extra function button. The name of the next_btn part is
120 * "elm.swallow.next_btn"
121 * @param content The main content object. The name of content part is
122 * "elm.swallow.content"
123 * @param item_style The current item style name. @c NULL would be default.
124 * @return The created item or @c NULL upon failure.
125 *
126 * The item is inserted into the naviframe straight away without any
127 * transition operations. This item will be deleted when it is popped.
128 *
129 * @see also elm_naviframe_item_style_set()
130 * @see also elm_naviframe_item_push()
131 * @see also elm_naviframe_item_insert_after()
132 *
133 * The following styles are available for this item:
134 * @li @c "default"
135 *
136 * @ingroup Naviframe
137 */
138EAPI Elm_Object_Item *elm_naviframe_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style);
139
140/**
141 * @brief Insert a new item into the naviframe after item @p after.
142 *
143 * @param obj The naviframe object
144 * @param after The naviframe item to insert after.
145 * @param title_label The label in the title area. The name of the title
146 * label part is "elm.text.title"
147 * @param prev_btn The button to go to the previous item. If it is NULL,
148 * then naviframe will create a back button automatically. The name of
149 * the prev_btn part is "elm.swallow.prev_btn"
150 * @param next_btn The button to go to the next item. Or It could be just an
151 * extra function button. The name of the next_btn part is
152 * "elm.swallow.next_btn"
153 * @param content The main content object. The name of content part is
154 * "elm.swallow.content"
155 * @param item_style The current item style name. @c NULL would be default.
156 * @return The created item or @c NULL upon failure.
157 *
158 * The item is inserted into the naviframe straight away without any
159 * transition operations. This item will be deleted when it is popped.
160 *
161 * @see also elm_naviframe_item_style_set()
162 * @see also elm_naviframe_item_push()
163 * @see also elm_naviframe_item_insert_before()
164 *
165 * The following styles are available for this item:
166 * @li @c "default"
167 *
168 * @ingroup Naviframe
169 */
170EAPI Elm_Object_Item *elm_naviframe_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *title_label, Evas_Object *prev_btn, Evas_Object *next_btn, Evas_Object *content, const char *item_style);
171
172/**
173 * @brief Pop an item that is on top of the stack
174 *
175 * @param obj The naviframe object
176 * @return @c NULL or the content object(if the
177 * elm_naviframe_content_preserve_on_pop_get is true).
178 *
179 * This pops an item that is on the top(visible) of the naviframe, makes it
180 * disappear, then deletes the item. The item that was underneath it on the
181 * stack will become visible.
182 *
183 * @see also elm_naviframe_content_preserve_on_pop_get()
184 *
185 * @ingroup Naviframe
186 */
187EAPI Evas_Object *elm_naviframe_item_pop(Evas_Object *obj);
188
189/**
190 * @brief Pop the items between the top and the above one on the given item.
191 *
192 * @param it The naviframe item
193 *
194 * @ingroup Naviframe
195 */
196EAPI void elm_naviframe_item_pop_to(Elm_Object_Item *it);
197
198/**
199 * Promote an item already in the naviframe stack to the top of the stack
200 *
201 * @param it The naviframe item
202 *
203 * This will take the indicated item and promote it to the top of the stack
204 * as if it had been pushed there. The item must already be inside the
205 * naviframe stack to work.
206 *
207 */
208EAPI void elm_naviframe_item_promote(Elm_Object_Item *it);
209
210/**
211 * @brief preserve the content objects when items are popped.
212 *
213 * @param obj The naviframe object
214 * @param preserve Enable the preserve mode if EINA_TRUE, disable otherwise
215 *
216 * @see also elm_naviframe_content_preserve_on_pop_get()
217 *
218 * @ingroup Naviframe
219 */
220EAPI void elm_naviframe_content_preserve_on_pop_set(Evas_Object *obj, Eina_Bool preserve);
221
222/**
223 * @brief Get a value whether preserve mode is enabled or not.
224 *
225 * @param obj The naviframe object
226 * @return If @c EINA_TRUE, preserve mode is enabled
227 *
228 * @see also elm_naviframe_content_preserve_on_pop_set()
229 *
230 * @ingroup Naviframe
231 */
232EAPI Eina_Bool elm_naviframe_content_preserve_on_pop_get(const Evas_Object *obj);
233
234/**
235 * @brief Get a top item on the naviframe stack
236 *
237 * @param obj The naviframe object
238 * @return The top item on the naviframe stack or @c NULL, if the stack is
239 * empty
240 *
241 * @ingroup Naviframe
242 */
243EAPI Elm_Object_Item *elm_naviframe_top_item_get(const Evas_Object *obj);
244
245/**
246 * @brief Get a bottom item on the naviframe stack
247 *
248 * @param obj The naviframe object
249 * @return The bottom item on the naviframe stack or @c NULL, if the stack is
250 * empty
251 *
252 * @ingroup Naviframe
253 */
254EAPI Elm_Object_Item *elm_naviframe_bottom_item_get(const Evas_Object *obj);
255
256/**
257 * @brief Set an item style
258 *
259 * @param it The naviframe item
260 * @param item_style The current item style name. @c NULL would be default
261 *
262 * The following styles are available for this item:
263 * @li @c "default"
264 *
265 * @see also elm_naviframe_item_style_get()
266 *
267 * @ingroup Naviframe
268 */
269EAPI void elm_naviframe_item_style_set(Elm_Object_Item *it, const char *item_style);
270
271/**
272 * @brief Get an item style
273 *
274 * @param it The naviframe item
275 * @return The current item style name
276 *
277 * @see also elm_naviframe_item_style_set()
278 *
279 * @ingroup Naviframe
280 */
281EAPI const char *elm_naviframe_item_style_get(const Elm_Object_Item *it);
282
283/**
284 * @brief Show/Hide the title area
285 *
286 * @param it The naviframe item
287 * @param visible If @c EINA_TRUE, title area will be visible, hidden
288 * otherwise
289 *
290 * When the title area is invisible, then the controls would be hidden so as * to expand the content area to full-size.
291 *
292 * @see also elm_naviframe_item_title_visible_get()
293 *
294 * @ingroup Naviframe
295 */
296EAPI void elm_naviframe_item_title_visible_set(Elm_Object_Item *it, Eina_Bool visible);
297
298/**
299 * @brief Get a value whether title area is visible or not.
300 *
301 * @param it The naviframe item
302 * @return If @c EINA_TRUE, title area is visible
303 *
304 * @see also elm_naviframe_item_title_visible_set()
305 *
306 * @ingroup Naviframe
307 */
308EAPI Eina_Bool elm_naviframe_item_title_visible_get(const Elm_Object_Item *it);
309
310/**
311 * @brief Set creating prev button automatically or not
312 *
313 * @param obj The naviframe object
314 * @param auto_pushed If @c EINA_TRUE, the previous button(back button) will
315 * be created internally when you pass the @c NULL to the prev_btn
316 * parameter in elm_naviframe_item_push
317 *
318 * @see also elm_naviframe_item_push()
319 *
320 * @ingroup Naviframe
321 */
322EAPI void elm_naviframe_prev_btn_auto_pushed_set(Evas_Object *obj, Eina_Bool auto_pushed);
323
324/**
325 * @brief Get a value whether prev button(back button) will be auto pushed or
326 * not.
327 *
328 * @param obj The naviframe object
329 * @return If @c EINA_TRUE, prev button will be auto pushed.
330 *
331 * @see also elm_naviframe_item_push()
332 * elm_naviframe_prev_btn_auto_pushed_set()
333 *
334 * @ingroup Naviframe
335 */
336EAPI Eina_Bool elm_naviframe_prev_btn_auto_pushed_get(const Evas_Object *obj);
337
338/**
339 * @brief Get a list of all the naviframe items.
340 *
341 * @param obj The naviframe object
342 * @return An Eina_List of naviframe items, #Elm_Object_Item,
343 * or @c NULL on failure.
344 * @note The returned list MUST be freed.
345 *
346 * @ingroup Naviframe
347 */
348EAPI Eina_List *elm_naviframe_items_get(const Evas_Object *obj) EINA_MALLOC EINA_WARN_UNUSED_RESULT;
349
350/**
351 * @brief Set the event enabled when pushing/popping items
352 *
353 * If @c enabled is EINA_TRUE, the contents of the naviframe item will
354 * receives events from mouse and keyboard during view changing such as
355 * item push/pop.
356 *
357 * @param obj The naviframe object
358 * @param enabled Events are received when enabled is @c EINA_TRUE, and
359 * ignored otherwise.
360 *
361 * @warning Events will be blocked by calling evas_object_freeze_events_set()
362 * internally. So don't call the API whiling pushing/popping items.
363 *
364 * @see elm_naviframe_event_enabled_get()
365 * @see evas_object_freeze_events_set()
366 *
367 * @ingroup Naviframe
368 */
369EAPI void elm_naviframe_event_enabled_set(Evas_Object *obj, Eina_Bool enabled);
370
371/**
372 * @brief Get the value of event enabled status.
373 *
374 * @param obj The naviframe object
375 * @return EINA_TRUE, when event is enabled
376 *
377 * @see elm_naviframe_event_enabled_set()
378 *
379 * @ingroup Naviframe
380 */
381EAPI Eina_Bool elm_naviframe_event_enabled_get(const Evas_Object *obj);
382
383/**
384 * @brief Simple version of item_push.
385 *
386 * @see elm_naviframe_item_push
387 */
388static inline Elm_Object_Item *
389elm_naviframe_item_simple_push(Evas_Object *obj, Evas_Object *content)
390{
391 Elm_Object_Item *it;
392 it = elm_naviframe_item_push(obj, NULL, NULL, NULL, content, NULL);
393 elm_naviframe_item_title_visible_set(it, EINA_FALSE);
394 return it;
395}
396
397/**
398 * @brief Simple version of item_promote.
399 *
400 * @see elm_naviframe_item_promote
401 */
402EAPI void elm_naviframe_item_simple_promote(Evas_Object *obj, Evas_Object *content);
403
404/**
405 * @}
406 */
diff --git a/libraries/elementary/src/lib/elc_player.c b/libraries/elementary/src/lib/elc_player.c
new file mode 100644
index 0000000..a6327c3
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_player.c
@@ -0,0 +1,590 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#ifdef HAVE_EMOTION
5# include <Emotion.h>
6#endif
7
8typedef struct _Widget_Data Widget_Data;
9struct _Widget_Data
10{
11 Evas_Object *layout;
12 Evas_Object *video;
13 Evas_Object *emotion;
14
15 Evas_Object *forward;
16 Evas_Object *info;
17 Evas_Object *next;
18 Evas_Object *pause;
19 Evas_Object *play;
20 Evas_Object *prev;
21 Evas_Object *rewind;
22 Evas_Object *stop;
23
24 Evas_Object *slider;
25};
26
27#ifdef HAVE_EMOTION
28static const char *widtype = NULL;
29
30static const char SIG_FORWARD_CLICKED[] = "forward,clicked";
31static const char SIG_INFO_CLICKED[] = "info,clicked";
32static const char SIG_NEXT_CLICKED[] = "next,clicked";
33static const char SIG_PAUSE_CLICKED[] = "pause,clicked";
34static const char SIG_PLAY_CLICKED[] = "play,clicked";
35static const char SIG_PREV_CLICKED[] = "prev,clicked";
36static const char SIG_REWIND_CLICKED[] = "rewind,clicked";
37static const char SIG_STOP_CLICKED[] = "stop,clicked";
38
39static const Evas_Smart_Cb_Description _signals[] = {
40 { SIG_FORWARD_CLICKED, "" },
41 { SIG_INFO_CLICKED, "" },
42 { SIG_NEXT_CLICKED, "" },
43 { SIG_PAUSE_CLICKED, "" },
44 { SIG_PLAY_CLICKED, "" },
45 { SIG_PREV_CLICKED, "" },
46 { SIG_REWIND_CLICKED, "" },
47 { SIG_STOP_CLICKED, "" },
48 { NULL, NULL }
49};
50
51static void _del_hook(Evas_Object *obj);
52static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
53static void _theme_hook(Evas_Object *obj);
54static void _sizing_eval(Evas_Object *obj);
55static void _on_focus_hook(void *data, Evas_Object *obj);
56static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
57 Evas_Callback_Type type, void *event_info);
58
59static Eina_Bool
60_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
61{
62 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
63 Evas_Event_Key_Down *ev = event_info;
64 Widget_Data *wd = elm_widget_data_get(obj);
65 if (!wd) return EINA_FALSE;
66 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
67 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
68 if (!wd->video) return EINA_FALSE;
69 if ((!strcmp(ev->keyname, "Left")) ||
70 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
71 {
72 double current, last;
73
74 current = elm_video_play_position_get(wd->video);
75 last = elm_video_play_length_get(wd->video);
76
77 if (current < last)
78 {
79 current += last / 100;
80 elm_video_play_position_set(wd->video, current);
81 }
82
83 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
84 return EINA_TRUE;
85 }
86 if ((!strcmp(ev->keyname, "Right")) ||
87 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
88 {
89 double current, last;
90
91 current = elm_video_play_position_get(wd->video);
92 last = elm_video_play_length_get(wd->video);
93
94 if (current > 0)
95 {
96 current -= last / 100;
97 if (current < 0) current = 0;
98 elm_video_play_position_set(wd->video, current);
99 }
100
101 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
102 return EINA_TRUE;
103 }
104 if (!strcmp(ev->keyname, "space"))
105 {
106 if (elm_video_is_playing_get(wd->video))
107 elm_video_pause(wd->video);
108 else
109 elm_video_play(wd->video);
110 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
111 return EINA_TRUE;
112 }
113 fprintf(stderr, "keyname: '%s' not handle\n", ev->keyname);
114 return EINA_FALSE;
115}
116
117static void
118_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
119{
120 Widget_Data *wd = elm_widget_data_get(obj);
121 if (!wd) return;
122 if (elm_widget_focus_get(obj))
123 {
124 edje_object_signal_emit(wd->layout, "elm,action,focus", "elm");
125 evas_object_focus_set(wd->layout, EINA_TRUE);
126 }
127 else
128 {
129 edje_object_signal_emit(wd->layout, "elm,action,unfocus", "elm");
130 evas_object_focus_set(wd->layout, EINA_FALSE);
131 }
132}
133
134static void
135_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
136{
137 Widget_Data *wd = elm_widget_data_get(obj);
138 if (!wd) return;
139 edje_object_mirrored_set(wd->layout, rtl);
140}
141
142static void
143_theme_hook(Evas_Object *obj)
144{
145 Widget_Data *wd = elm_widget_data_get(obj);
146 if (!wd) return;
147 _elm_widget_mirrored_reload(obj);
148 _mirrored_set(obj, elm_widget_mirrored_get(obj));
149 _elm_theme_object_set(obj, wd->layout, "video", "base", elm_widget_style_get(obj));
150 edje_object_scale_set(wd->layout, elm_widget_scale_get(obj) *
151 _elm_config->scale);
152
153#define UPDATE_THEME(Obj, Target, Layout, Name) \
154 if (Target) \
155 { \
156 elm_object_style_set(Target, elm_widget_style_get(Obj)); \
157 if (!edje_object_part_swallow(Layout, Name, Target)) \
158 evas_object_hide(Target); \
159 elm_object_disabled_set(Target, elm_widget_disabled_get(Obj)); \
160 }
161
162 UPDATE_THEME(obj, wd->forward, wd->layout, "media_player/forward");
163 UPDATE_THEME(obj, wd->info, wd->layout, "media_player/info");
164 UPDATE_THEME(obj, wd->next, wd->layout, "media_player/next");
165 UPDATE_THEME(obj, wd->pause, wd->layout, "media_player/pause");
166 UPDATE_THEME(obj, wd->play, wd->layout, "media_player/play");
167 UPDATE_THEME(obj, wd->prev, wd->layout, "media_player/prev");
168 UPDATE_THEME(obj, wd->rewind, wd->layout, "media_player/rewind");
169 UPDATE_THEME(obj, wd->next, wd->layout, "media_player/next");
170 UPDATE_THEME(obj, wd->slider, wd->layout, "media_player/slider");
171
172 _sizing_eval(obj);
173}
174
175static void
176_sizing_eval(Evas_Object *obj)
177{
178 Widget_Data *wd = elm_widget_data_get(obj);
179 Evas_Coord w, h;
180
181 if (!wd) return;
182 edje_object_size_min_get(wd->layout, &w, &h);
183 edje_object_size_min_restricted_calc(wd->layout, &w, &h, w, h);
184 evas_object_size_hint_min_set(obj, w, h);
185}
186
187static void
188_update_slider(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
189{
190 Evas_Object *player = data;
191 Widget_Data *wd = elm_widget_data_get(player);
192 double pos, length;
193 Eina_Bool seekable;
194
195 if (!wd) return ;
196 seekable = elm_video_is_seekable_get(wd->video);
197 length = elm_video_play_length_get(wd->video);
198 pos = elm_video_play_position_get(wd->video);
199
200 elm_object_disabled_set(wd->slider, !seekable);
201 elm_slider_min_max_set(wd->slider, 0, length);
202 elm_slider_value_set(wd->slider, pos);
203}
204
205static void
206_update_position(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
207{
208 Evas_Object *player = data;
209 Widget_Data *wd = elm_widget_data_get(player);
210
211 if (!wd) return ;
212 elm_video_play_position_set(wd->video, elm_slider_value_get(wd->slider));
213}
214
215static void
216_forward(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
217{
218 Evas_Object *player = data;
219 Widget_Data *wd = elm_widget_data_get(player);
220 double pos, length;
221
222 if (!wd) return ;
223
224 pos = elm_video_play_position_get(wd->video);
225 length = elm_video_play_length_get(wd->video);
226
227 pos += length * 0.3;
228 elm_video_play_position_set(wd->video, pos);
229
230 edje_object_signal_emit(wd->layout, "elm,button,forward", "elm");
231 evas_object_smart_callback_call(player, SIG_FORWARD_CLICKED, NULL);
232}
233
234static void
235_info(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
236{
237 Evas_Object *player = data;
238 Widget_Data *wd = elm_widget_data_get(player);
239
240 if (!wd) return ;
241
242 edje_object_signal_emit(wd->layout, "elm,button,info", "elm");
243 evas_object_smart_callback_call(player, SIG_INFO_CLICKED, NULL);
244}
245
246static void
247_next(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
248{
249 Evas_Object *player = data;
250 Widget_Data *wd = elm_widget_data_get(player);
251 double pos, length;
252
253 if (!wd) return ;
254
255 pos = elm_video_play_position_get(wd->video);
256 length = elm_video_play_length_get(wd->video);
257
258 pos += length * 0.1;
259 elm_video_play_position_set(wd->video, pos);
260
261 edje_object_signal_emit(wd->layout, "elm,button,next", "elm");
262 evas_object_smart_callback_call(player, SIG_NEXT_CLICKED, NULL);
263}
264
265static void
266_pause(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
267{
268 Evas_Object *player = data;
269 Widget_Data *wd = elm_widget_data_get(player);
270
271 if (!wd) return ;
272
273 edje_object_signal_emit(wd->layout, "elm,player,pause", "elm");
274 elm_video_pause(wd->video);
275
276 edje_object_signal_emit(wd->layout, "elm,button,pause", "elm");
277 evas_object_smart_callback_call(player, SIG_PAUSE_CLICKED, NULL);
278}
279
280static void
281_play(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
282{
283 Evas_Object *player = data;
284 Widget_Data *wd = elm_widget_data_get(player);
285
286 if (!wd) return ;
287 elm_video_play(wd->video);
288 edje_object_signal_emit(wd->layout, "elm,button,play", "elm");
289 evas_object_smart_callback_call(player, SIG_PLAY_CLICKED, NULL);
290}
291
292static void
293_prev(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
294{
295 Evas_Object *player = data;
296 Widget_Data *wd = elm_widget_data_get(player);
297 double pos, length;
298
299 if (!wd) return ;
300
301 pos = elm_video_play_position_get(wd->video);
302 length = elm_video_play_length_get(wd->video);
303
304 pos -= length * 0.1;
305 elm_video_play_position_set(wd->video, pos);
306 evas_object_smart_callback_call(player, SIG_PREV_CLICKED, NULL);
307 edje_object_signal_emit(wd->layout, "elm,button,prev", "elm");
308}
309
310static void
311_rewind(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
312{
313 Evas_Object *player = data;
314 Widget_Data *wd = elm_widget_data_get(player);
315
316 if (!wd) return ;
317 elm_video_play_position_set(wd->video, 0);
318 edje_object_signal_emit(wd->layout, "elm,button,rewind", "elm");
319 evas_object_smart_callback_call(player, SIG_REWIND_CLICKED, NULL);
320}
321
322static void
323_stop(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
324{
325 Evas_Object *player = data;
326 Widget_Data *wd = elm_widget_data_get(player);
327
328 if (!wd) return ;
329
330 edje_object_signal_emit(wd->layout, "elm,button,stop", "elm");
331 evas_object_smart_callback_call(player, SIG_STOP_CLICKED, NULL);
332}
333
334static void
335_play_started(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
336{
337 Evas_Object *player = data;
338 Widget_Data *wd = elm_widget_data_get(player);
339
340 if (!wd) return ;
341
342 edje_object_signal_emit(wd->layout, "elm,player,play", "elm");
343}
344
345static void
346_play_finished(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
347{
348 Evas_Object *player = data;
349 Widget_Data *wd = elm_widget_data_get(player);
350
351 if (!wd) return ;
352
353 edje_object_signal_emit(wd->layout, "elm,player,pause", "elm");
354}
355
356static void
357_cleanup_callback(Widget_Data *wd)
358{
359 if (!wd || !wd->emotion) return;
360
361 evas_object_smart_callback_del(wd->emotion, "frame_decode",
362 _update_slider);
363 evas_object_smart_callback_del(wd->emotion, "frame_resize",
364 _update_slider);
365 evas_object_smart_callback_del(wd->emotion, "length_change",
366 _update_slider);
367 evas_object_smart_callback_del(wd->emotion, "position_update",
368 _update_slider);
369 evas_object_smart_callback_del(wd->emotion, "playback_started",
370 _play_started);
371 evas_object_smart_callback_del(wd->emotion, "playback_finished",
372 _play_finished);
373 elm_object_disabled_set(wd->slider, EINA_TRUE);
374 elm_object_disabled_set(wd->forward, EINA_TRUE);
375 elm_object_disabled_set(wd->info, EINA_TRUE);
376 elm_object_disabled_set(wd->next, EINA_TRUE);
377 elm_object_disabled_set(wd->pause, EINA_TRUE);
378 elm_object_disabled_set(wd->play, EINA_TRUE);
379 elm_object_disabled_set(wd->prev, EINA_TRUE);
380 elm_object_disabled_set(wd->rewind, EINA_TRUE);
381 elm_object_disabled_set(wd->next, EINA_TRUE);
382 wd->video = NULL;
383 wd->emotion = NULL;
384}
385
386static void
387_track_video(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
388{
389 _cleanup_callback(data);
390}
391
392static void
393_del_hook(Evas_Object *obj)
394{
395 Widget_Data *wd = elm_widget_data_get(obj);
396
397 if (!wd) return;
398 evas_object_smart_callback_del(wd->forward, "clicked", _forward);
399 evas_object_smart_callback_del(wd->info, "clicked", _info);
400 evas_object_smart_callback_del(wd->next, "clicked", _next);
401 evas_object_smart_callback_del(wd->pause, "clicked", _pause);
402 evas_object_smart_callback_del(wd->play, "clicked", _play);
403 evas_object_smart_callback_del(wd->prev, "clicked", _prev);
404 evas_object_smart_callback_del(wd->rewind, "clicked", _rewind);
405 evas_object_smart_callback_del(wd->next, "clicked", _next);
406 _cleanup_callback(wd);
407 free(wd);
408}
409
410static Evas_Object *
411_player_button_add(Evas_Object *parent, Evas_Object *obj, Evas_Object *layout, const char *name, Evas_Smart_Cb func)
412{
413 Evas_Object *ic;
414 Evas_Object *bt;
415
416 ic = elm_icon_add(parent);
417 elm_icon_standard_set(ic, name);
418 evas_object_size_hint_aspect_set(ic, EVAS_ASPECT_CONTROL_VERTICAL, 1, 1);
419 bt = elm_button_add(parent);
420 elm_widget_mirrored_automatic_set(bt, EINA_FALSE);
421 elm_object_part_content_set(bt, "icon", ic);
422 evas_object_size_hint_align_set(bt, 0.0, 0.0);
423 elm_object_style_set(bt, "anchor");
424 evas_object_smart_callback_add(bt, "clicked", func, obj);
425 elm_widget_sub_object_add(obj, bt);
426
427 if (!edje_object_part_swallow(layout, name, bt))
428 evas_object_hide(bt);
429 return bt;
430}
431
432static char *
433_double_to_time(double value)
434{
435 char buf[256];
436 int ph, pm, ps, pf;
437
438 ph = value / 3600;
439 pm = value / 60 - (ph * 60);
440 ps = value - (pm * 60);
441 pf = value * 100 - (ps * 100) - (pm * 60 * 100) - (ph * 60 * 60 * 100);
442 if (ph)
443 snprintf(buf, sizeof(buf), "%i:%02i:%02i.%02i",
444 ph, pm, ps, pf);
445 else if (pm)
446 snprintf(buf, sizeof(buf), "%02i:%02i.%02i",
447 pm, ps, pf);
448 else
449 snprintf(buf, sizeof(buf), "%02i.%02i",
450 ps, pf);
451
452 return (char *)eina_stringshare_add(buf);
453}
454
455static void
456_value_free(char *data)
457{
458 eina_stringshare_del(data);
459}
460#endif
461
462#ifdef HAVE_EMOTION
463static void
464_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
465{
466 if (part && strcmp(part, "video")) return;
467 ELM_CHECK_WIDTYPE(obj, widtype);
468 Widget_Data *wd = elm_widget_data_get(obj);
469 if (!wd) return;
470 double pos, length;
471 Eina_Bool seekable;
472
473 if (!_elm_video_check(content)) return;
474 if (wd->video == content) return;
475
476 if (wd->video) evas_object_del(wd->video);
477 _cleanup_callback(wd);
478
479 wd->video = content;
480
481 if (!wd->video)
482 {
483 wd->emotion = NULL;
484 return ;
485 }
486
487 elm_object_disabled_set(wd->slider, EINA_FALSE);
488 elm_object_disabled_set(wd->forward, EINA_FALSE);
489 elm_object_disabled_set(wd->info, EINA_FALSE);
490 elm_object_disabled_set(wd->next, EINA_FALSE);
491 elm_object_disabled_set(wd->pause, EINA_FALSE);
492 elm_object_disabled_set(wd->play, EINA_FALSE);
493 elm_object_disabled_set(wd->prev, EINA_FALSE);
494 elm_object_disabled_set(wd->rewind, EINA_FALSE);
495 elm_object_disabled_set(wd->next, EINA_FALSE);
496
497 wd->emotion = elm_video_emotion_get(wd->video);
498 emotion_object_priority_set(wd->emotion, EINA_TRUE);
499 evas_object_event_callback_add(wd->video, EVAS_CALLBACK_DEL,
500 _track_video, wd);
501
502 seekable = elm_video_is_seekable_get(wd->video);
503 length = elm_video_play_length_get(wd->video);
504 pos = elm_video_play_position_get(wd->video);
505
506 elm_object_disabled_set(wd->slider, !seekable);
507 elm_slider_min_max_set(wd->slider, 0, length);
508 elm_slider_value_set(wd->slider, pos);
509
510 if (elm_video_is_playing_get(wd->video)) edje_object_signal_emit(wd->layout, "elm,player,play", "elm");
511 else edje_object_signal_emit(wd->layout, "elm,player,pause", "elm");
512
513 evas_object_smart_callback_add(wd->emotion, "frame_decode",
514 _update_slider, obj);
515 evas_object_smart_callback_add(wd->emotion, "frame_resize",
516 _update_slider, obj);
517 evas_object_smart_callback_add(wd->emotion, "length_change",
518 _update_slider, obj);
519 evas_object_smart_callback_add(wd->emotion, "position_update",
520 _update_slider, obj);
521 evas_object_smart_callback_add(wd->emotion, "playback_started",
522 _play_started, obj);
523 evas_object_smart_callback_add(wd->emotion, "playback_finished",
524 _play_finished, obj);
525
526 /* FIXME: track info from video */
527}
528#endif
529
530EAPI Evas_Object *
531elm_player_add(Evas_Object *parent)
532{
533#ifdef HAVE_EMOTION
534 Evas_Object *obj;
535 Evas *e;
536 Widget_Data *wd;
537
538 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
539 ELM_SET_WIDTYPE(widtype, "player");
540 elm_widget_type_set(obj, "player");
541 elm_widget_sub_object_add(parent, obj);
542 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
543 elm_widget_data_set(obj, wd);
544 elm_widget_del_hook_set(obj, _del_hook);
545 elm_widget_theme_hook_set(obj, _theme_hook);
546 elm_widget_can_focus_set(obj, EINA_TRUE);
547 elm_widget_event_hook_set(obj, _event_hook);
548 elm_widget_content_set_hook_set(obj, _content_set_hook);
549 /* TODO: add content_unset and content_get hook */
550
551 wd->layout = edje_object_add(e);
552 _elm_theme_object_set(obj, wd->layout, "player", "base", "default");
553 elm_widget_resize_object_set(obj, wd->layout);
554 elm_widget_sub_object_add(obj, wd->layout);
555 evas_object_show(wd->layout);
556 evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
557
558 wd->forward = _player_button_add(parent, obj, wd->layout, "media_player/forward", _forward);
559 wd->info = _player_button_add(parent, obj, wd->layout, "media_player/info", _info);
560 wd->next = _player_button_add(parent, obj, wd->layout, "media_player/next", _next);
561 wd->pause = _player_button_add(parent, obj, wd->layout, "media_player/pause", _pause);
562 wd->play = _player_button_add(parent, obj, wd->layout, "media_player/play", _play);
563 wd->prev = _player_button_add(parent, obj, wd->layout, "media_player/prev", _prev);
564 wd->rewind = _player_button_add(parent, obj, wd->layout, "media_player/rewind", _rewind);
565 wd->stop = _player_button_add(parent, obj, wd->layout, "media_player/stop", _stop);
566
567 wd->slider = elm_slider_add(parent);
568 elm_widget_sub_object_add(obj, wd->slider);
569 elm_slider_indicator_format_function_set(wd->slider, _double_to_time, _value_free);
570 elm_slider_units_format_function_set(wd->slider, _double_to_time, _value_free);
571 elm_slider_min_max_set(wd->slider, 0, 0);
572 elm_slider_value_set(wd->slider, 0);
573 elm_object_disabled_set(wd->slider, EINA_TRUE);
574 evas_object_size_hint_align_set(wd->slider, EVAS_HINT_FILL, 0.5);
575 evas_object_size_hint_weight_set(wd->slider, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
576 edje_object_part_swallow(wd->layout, "media_player/slider", wd->slider);
577 evas_object_smart_callback_add(wd->slider, "changed", _update_position, obj);
578
579 wd->emotion = NULL;
580 wd->video = NULL;
581
582 _mirrored_set(obj, elm_widget_mirrored_get(obj));
583 _sizing_eval(obj);
584
585 return obj;
586#else
587 (void) parent;
588 return NULL;
589#endif
590}
diff --git a/libraries/elementary/src/lib/elc_popup.c b/libraries/elementary/src/lib/elc_popup.c
new file mode 100644
index 0000000..1013f49
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_popup.c
@@ -0,0 +1,1454 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define ELM_POPUP_ACTION_BUTTON_MAX 3
5typedef struct _Widget_Data Widget_Data;
6typedef struct _Elm_Popup_Content_Item Elm_Popup_Content_Item;
7typedef struct _Action_Area_Data Action_Area_Data;
8
9struct _Widget_Data
10{
11 Evas_Object *base;
12 Evas_Object *notify;
13 Evas_Object *title_icon;
14 Evas_Object *content_area;
15 Evas_Object *content_text_obj;
16 Evas_Object *action_area;
17 Evas_Object *box;
18 Evas_Object *scr;
19 Evas_Object *content;
20 Eina_List *items;
21 const char *title_text;
22 Action_Area_Data *buttons[ELM_POPUP_ACTION_BUTTON_MAX];
23 Elm_Wrap_Type content_text_wrap_type;
24 unsigned int button_count;
25 Evas_Coord max_sc_w;
26 Evas_Coord max_sc_h;
27 Eina_Bool scr_size_recalc:1;
28};
29
30struct _Elm_Popup_Content_Item
31{
32 Elm_Widget_Item base;
33 const char *label;
34 Evas_Object *icon;
35 Evas_Smart_Cb func;
36 Eina_Bool disabled:1;
37};
38
39struct _Action_Area_Data
40{
41 Evas_Object *obj;
42 Evas_Object *btn;
43 Eina_Bool delete_me;
44};
45
46static const char *widtype = NULL;
47static void _del_hook(Evas_Object *obj);
48static void _theme_hook(Evas_Object *obj);
49static void _text_set_hook(Evas_Object *obj, const char *part,
50 const char *label);
51static const char *_text_get_hook(const Evas_Object *obj,
52 const char *part);
53static void _content_set_hook(Evas_Object *obj, const char *part,
54 Evas_Object *content);
55static Evas_Object *_content_get_hook(Evas_Object *obj,
56 const char *part);
57static Evas_Object *_content_unset_hook(Evas_Object *obj,
58 const char *part);
59static void _item_text_set_hook(Elm_Object_Item *it, const char *part,
60 const char *label);
61static const char *_item_text_get_hook(const Elm_Object_Item *it,
62 const char *part);
63static void _item_content_set_hook(Elm_Object_Item *it, const char *part,
64 Evas_Object *content);
65static Evas_Object *_item_content_unset_hook(const Elm_Object_Item *it,
66 const char *part);
67static Evas_Object *_item_content_get_hook(const Elm_Object_Item *it,
68 const char *part);
69static void _item_disable_hook(Elm_Object_Item *it);
70static void _item_del_pre_hook(Elm_Object_Item *it);
71static void _item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
72 const char *source);
73static void _sizing_eval(Evas_Object *obj);
74static void _block_clicked_cb(void *data, Evas_Object *obj, void *event_info);
75static void _notify_resize(void *data, Evas *e, Evas_Object *obj,
76 void *event_info);
77static void _scroller_resize(void *data, Evas *e, Evas_Object *obj,
78 void *event_info);
79static void _timeout(void *data, Evas_Object *obj , void *event_info);
80static void _sub_del(void *data, Evas_Object *obj, void *event_info);
81static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
82static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
83static void _layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
84 const char *emission __UNUSED__,
85 const char *source __UNUSED__);
86static void _item_new(Elm_Popup_Content_Item *item);
87static void _remove_items(Widget_Data *wd);
88static void _list_new(Evas_Object *obj);
89static void _list_del(Widget_Data *wd);
90static void _item_sizing_eval(Elm_Popup_Content_Item *item);
91static void _item_select_cb(void *data, Evas_Object *obj __UNUSED__,
92 const char *emission __UNUSED__,
93 const char *source __UNUSED__);
94static void _scroller_size_calc(Evas_Object *obj);
95static void _action_button_set(Evas_Object *obj, Evas_Object *btn,
96 unsigned int idx);
97static Evas_Object *_action_button_get(Evas_Object *obj, unsigned int idx);
98static Evas_Object *_action_button_unset(Evas_Object *obj, unsigned int idx);
99static void _button_remove(Evas_Object *obj, Evas_Object *content,
100 Eina_Bool delete);
101static void _popup_show(void *data, Evas *e, Evas_Object *obj,
102 void *event_info);
103static void _popup_hide(void *data, Evas *e, Evas_Object *obj,
104 void *event_info);
105static const char SIG_BLOCK_CLICKED[] = "block,clicked";
106static const char SIG_TIMEOUT[] = "timeout";
107static const Evas_Smart_Cb_Description _signals[] = {
108 {SIG_BLOCK_CLICKED, ""},
109 {SIG_TIMEOUT, ""},
110 {NULL, NULL}
111};
112
113#define ELM_POPUP_CONTENT_ITEM_CHECK_RETURN(it, ...) \
114 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
115 ELM_CHECK_WIDTYPE(WIDGET(item), widtype) __VA_ARGS__;
116
117static void
118_layout_set(Evas_Object *obj)
119{
120 Widget_Data *wd = elm_widget_data_get(obj);
121
122 if (!wd) return;
123 if ((!(wd->title_text)) && (!(wd->title_icon)))
124 elm_object_signal_emit(wd->base, "elm,state,title_area,hidden", "elm");
125 else
126 elm_object_signal_emit(wd->base, "elm,state,title_area,visible", "elm");
127 if (wd->button_count)
128 elm_object_signal_emit(wd->base, "elm,state,action_area,visible", "elm");
129 else
130 elm_object_signal_emit(wd->base, "elm,state,action_area,hidden", "elm");
131}
132
133static void
134_del_hook(Evas_Object *obj)
135{
136 Widget_Data *wd = elm_widget_data_get(obj);
137
138 if (!wd) return;
139 free(wd);
140}
141
142static void
143_del_pre_hook(Evas_Object *obj)
144{
145 unsigned int i;
146 Widget_Data *wd = elm_widget_data_get(obj);
147
148 if (!wd) return;
149 evas_object_smart_callback_del(wd->notify, "block,clicked",
150 _block_clicked_cb);
151 evas_object_smart_callback_del(wd->notify, "timeout", _timeout);
152 evas_object_event_callback_del(wd->notify, EVAS_CALLBACK_RESIZE,
153 _notify_resize);
154 evas_object_event_callback_del(obj, EVAS_CALLBACK_SHOW, _popup_show);
155 wd->button_count = 0;
156 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
157 if (wd->buttons[i])
158 {
159 evas_object_del(wd->buttons[i]->btn);
160 free(wd->buttons[i]);
161 wd->buttons[i] = NULL;
162 }
163 if (wd->items)
164 {
165 _remove_items(wd);
166 _list_del(wd);
167 }
168}
169
170static void
171_theme_hook(Evas_Object *obj)
172{
173 Eina_List *elist;
174 Elm_Popup_Content_Item *item;
175 char buf[128];
176 unsigned int i = 0;
177 Widget_Data *wd = elm_widget_data_get(obj);
178
179 if (!wd) return;
180 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
181 _elm_widget_mirrored_reload(obj);
182 _mirrored_set(obj, elm_widget_mirrored_get(obj));
183 if (wd->button_count)
184 {
185 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
186 elm_layout_theme_set(wd->action_area, "popup", buf,
187 elm_widget_style_get(obj));
188 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
189 {
190 if (!wd->buttons[i]) continue;
191 elm_object_style_set(wd->buttons[i]->btn, buf);
192 }
193 }
194 elm_layout_theme_set(wd->content_area, "popup", "content",
195 elm_widget_style_get(obj));
196 if (wd->content_text_obj)
197 {
198 snprintf(buf, sizeof(buf), "popup/%s", elm_widget_style_get(obj));
199 elm_object_style_set(wd->content_text_obj, buf);
200 }
201 else if (wd->items)
202 {
203 EINA_LIST_FOREACH(wd->items, elist, item)
204 {
205 _elm_theme_object_set(obj, VIEW(item), "popup",
206 "item", elm_widget_style_get(obj));
207 if (item->label)
208 {
209 edje_object_part_text_escaped_set(VIEW(item), "elm.text",
210 item->label);
211 edje_object_signal_emit(VIEW(item),
212 "elm,state,item,text,visible", "elm");
213 }
214 if (item->icon)
215 edje_object_signal_emit(VIEW(item),
216 "elm,state,item,icon,visible", "elm");
217 if (item->disabled)
218 edje_object_signal_emit(VIEW(item),
219 "elm,state,item,disabled", "elm");
220 evas_object_show(VIEW(item));
221 edje_object_message_signal_process(VIEW(item));
222 }
223 _scroller_size_calc(obj);
224 }
225 if (wd->title_text)
226 {
227 elm_object_part_text_set(wd->base, "elm.text.title", wd->title_text);
228 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
229 }
230 if (wd->title_icon)
231 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
232 _layout_set(obj);
233 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
234 _sizing_eval(obj);
235}
236
237static void
238_item_sizing_eval(Elm_Popup_Content_Item *item)
239{
240 Evas_Coord min_w = -1, min_h = -1, max_w = -1, max_h = -1;
241
242 edje_object_size_min_restricted_calc(VIEW(item), &min_w, &min_h, min_w,
243 min_h);
244 evas_object_size_hint_min_set(VIEW(item), min_w, min_h);
245 evas_object_size_hint_max_set(VIEW(item), max_w, max_h);
246}
247
248static void
249_sizing_eval(Evas_Object *obj)
250{
251 Eina_List *elist;
252 Elm_Popup_Content_Item *item;
253 Evas_Coord w_box = 0, h_box = 0;
254 Evas_Coord minw_box = 0, minh_box = 0;
255 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
256 Widget_Data *wd = elm_widget_data_get(obj);
257
258 if (!wd) return;
259 if (wd->items)
260 {
261 EINA_LIST_FOREACH(wd->items, elist, item)
262 {
263 _item_sizing_eval(item);
264 evas_object_size_hint_min_get(VIEW(item), &minw_box,
265 &minh_box);
266 if (minw_box > w_box)
267 w_box = minw_box;
268 if (minh_box != -1)
269 h_box += minh_box;
270 }
271 evas_object_size_hint_min_set(wd->box, w_box, h_box);
272 evas_object_size_hint_min_set(wd->scr, w_box, MIN(h_box, wd->max_sc_h));
273 evas_object_size_hint_max_set(wd->scr, w_box, wd->max_sc_h);
274 evas_object_smart_calculate(wd->scr);
275 }
276 edje_object_size_min_calc(elm_layout_edje_get(wd->base), &minw, &minh);
277 evas_object_size_hint_min_set(wd->base, minw, minh);
278 evas_object_size_hint_max_set(wd->base, maxw, maxh);
279 evas_object_size_hint_min_set(obj, minw, minh);
280 evas_object_size_hint_max_set(obj, maxw, maxh);
281 elm_layout_sizing_eval(wd->base);
282}
283
284static void
285_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
286 void *event_info __UNUSED__)
287{
288 _sizing_eval(data);
289}
290
291static void
292_sub_del(void *data, Evas_Object *obj, void *event_info)
293{
294 Elm_Popup_Content_Item *item;
295 unsigned int i;
296 Evas_Object *sub = event_info;
297 Widget_Data *wd = elm_widget_data_get(data);
298
299 if (!wd) return;
300 if (obj == data)
301 {
302 if ((item = evas_object_data_get(sub, "_popup_content_item")) != NULL)
303 {
304 if (sub == item->icon)
305 {
306 edje_object_part_unswallow(VIEW(item), sub);
307 edje_object_signal_emit(VIEW(item),
308 "elm,state,item,icon,hidden", "elm");
309 item->icon = NULL;
310 }
311 }
312 }
313 else if (obj == wd->content_area)
314 {
315 if (sub == wd->content)
316 {
317 wd->content = NULL;
318 elm_object_part_content_unset(wd->base, "elm.swallow.content");
319 _sizing_eval(data);
320 }
321 else if (sub == wd->content_text_obj)
322 {
323 wd->content_text_obj = NULL;
324 elm_object_part_content_unset(wd->base, "elm.swallow.content");
325 _sizing_eval(data);
326 }
327 else if (sub == wd->scr)
328 {
329 wd->scr = NULL;
330 wd->box = NULL;
331 elm_object_part_content_unset(wd->base, "elm.swallow.content");
332 _sizing_eval(data);
333 }
334 }
335 else if (obj == wd->action_area)
336 {
337 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
338 {
339 if (wd->buttons[i] && sub == wd->buttons[i]->btn &&
340 wd->buttons[i]->delete_me == EINA_TRUE)
341 {
342 _button_remove(data, sub, EINA_FALSE);
343 break;
344 }
345 }
346 }
347 else if (obj == wd->base)
348 {
349 if (sub == wd->title_icon)
350 {
351 elm_object_signal_emit(wd->base, "elm,state,title,icon,hidden",
352 "elm");
353 edje_object_message_signal_process(wd->base);
354 wd->title_icon = NULL;
355 }
356 }
357}
358
359static void
360_block_clicked_cb(void *data, Evas_Object *obj __UNUSED__,
361 void *event_info __UNUSED__)
362{
363 Widget_Data *wd = elm_widget_data_get(data);
364
365 if (!wd) return;
366 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
367}
368
369static void
370_timeout(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
371{
372 evas_object_hide(data);
373 evas_object_smart_callback_call(data, SIG_TIMEOUT, NULL);
374}
375
376static void
377_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
378{
379 Eina_List *elist;
380 Elm_Popup_Content_Item *item;
381 Widget_Data *wd = elm_widget_data_get(obj);
382
383 if (!wd) return;
384 elm_object_mirrored_set(wd->notify, rtl);
385 if (wd->items)
386 EINA_LIST_FOREACH(wd->items, elist, item)
387 edje_object_mirrored_set(VIEW(item), rtl);
388}
389
390static void
391_layout_change_cb(void *data, Evas_Object *obj __UNUSED__,
392 const char *emission __UNUSED__,
393 const char *source __UNUSED__)
394{
395 Widget_Data *wd = elm_widget_data_get((Evas_Object*)data);
396
397 if (!wd) return;
398 if (wd->base)
399 elm_layout_sizing_eval(wd->base);
400}
401
402static void
403_restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
404 void *event_info __UNUSED__)
405{
406 Widget_Data *wd = elm_widget_data_get(obj);
407
408 if (!wd) return;
409 evas_object_layer_set(wd->notify, evas_object_layer_get(obj));
410}
411
412static void
413_scroller_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj,
414 void *event_info __UNUSED__)
415{
416 Evas_Coord w, h;
417 Widget_Data *wd = elm_widget_data_get(data);
418
419 if (!wd || wd->scr_size_recalc) return;
420 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
421 if (w && h)
422 {
423 if ((w <= wd->max_sc_w) && (h <= wd->max_sc_h))
424 {
425 _sizing_eval(data);
426 wd->scr_size_recalc = EINA_TRUE;
427 return;
428 }
429 }
430 if (wd->max_sc_w < w)
431 wd->max_sc_w = w;
432 if (wd->max_sc_h < h)
433 wd->max_sc_h = h;
434 _sizing_eval(data);
435}
436
437static void
438_list_new(Evas_Object *obj)
439{
440 Widget_Data *wd = elm_widget_data_get(obj);
441
442 if (!wd) return;
443 //Scroller
444 wd->scr = elm_scroller_add(obj);
445 elm_scroller_bounce_set(wd->scr, EINA_FALSE, EINA_TRUE);
446 elm_object_content_set(wd->scr, wd->box);
447 evas_object_size_hint_weight_set(wd->scr, EVAS_HINT_EXPAND,
448 EVAS_HINT_EXPAND);
449 evas_object_size_hint_align_set(wd->scr, EVAS_HINT_FILL, EVAS_HINT_FILL);
450 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE,
451 _scroller_resize, obj);
452 evas_object_event_callback_add(wd->scr,
453 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
454 _changed_size_hints, obj);
455 elm_object_part_content_set(wd->base, "elm.swallow.content", wd->scr);
456
457 //Box
458 wd->box = elm_box_add(obj);
459 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
460 EVAS_HINT_EXPAND);
461 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, EVAS_HINT_FILL);
462
463 elm_object_content_set(wd->scr, wd->box);
464}
465
466static void
467_list_del(Widget_Data *wd)
468{
469 if (!wd->scr) return;
470 elm_object_part_content_unset(wd->base, "elm.swallow.content");
471 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_RESIZE,
472 _scroller_resize);
473 evas_object_event_callback_del(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
474 _changed_size_hints);
475 evas_object_del(wd->scr);
476 wd->scr = NULL;
477 wd->box = NULL;
478}
479
480static void
481_scroller_size_calc(Evas_Object *obj)
482{
483 Evas_Coord h;
484 Evas_Coord h_title = 0;
485 Evas_Coord h_action_area = 0;
486 Evas_Coord h_content = 0;
487 const char *action_area_height;
488 Widget_Data *wd = elm_widget_data_get(obj);
489
490 if (!wd || !wd->items) return;
491 wd->scr_size_recalc = EINA_FALSE;
492 wd->max_sc_h = -1;
493 wd->max_sc_w = -1;
494 evas_object_geometry_get(wd->notify, NULL, NULL, NULL, &h);
495 if (wd->title_text || wd->title_icon)
496 edje_object_part_geometry_get(elm_layout_edje_get(wd->base),
497 "elm.bg.title", NULL, NULL, NULL, &h_title);
498 if (wd->button_count)
499 {
500 action_area_height = edje_object_data_get(
501 elm_layout_edje_get(wd->action_area), "action_area_height");
502 if (action_area_height) h_action_area = (int)(atoi(action_area_height)
503 * _elm_config->scale * elm_object_scale_get(obj));
504 }
505 h_content = h - (h_title + h_action_area);
506 wd->max_sc_h = h_content;
507}
508
509static void
510_item_select_cb(void *data, Evas_Object *obj __UNUSED__,
511 const char *emission __UNUSED__, const char *source __UNUSED__)
512{
513 Elm_Popup_Content_Item *item = data;
514
515 if (!item || item->disabled) return;
516 if (item->func)
517 item->func((void*)item->base.data, WIDGET(item), data);
518}
519
520static void
521_item_new(Elm_Popup_Content_Item *item)
522{
523 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
524
525 if (!wd) return;
526 elm_widget_item_text_set_hook_set(item, _item_text_set_hook);
527 elm_widget_item_text_get_hook_set(item, _item_text_get_hook);
528 elm_widget_item_content_set_hook_set(item, _item_content_set_hook);
529 elm_widget_item_content_get_hook_set(item, _item_content_get_hook);
530 elm_widget_item_content_unset_hook_set(item, _item_content_unset_hook);
531 elm_widget_item_disable_hook_set(item, _item_disable_hook);
532 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
533 elm_widget_item_signal_emit_hook_set(item, _item_signal_emit_hook);
534 VIEW(item) = edje_object_add(evas_object_evas_get(wd->base));
535 _elm_theme_object_set(WIDGET(item), VIEW(item), "popup", "item",
536 elm_widget_style_get(WIDGET(item)));
537 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
538 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
539 _item_select_cb, item);
540 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL,
541 EVAS_HINT_FILL);
542 evas_object_show(VIEW(item));
543}
544
545static void
546_remove_items(Widget_Data *wd)
547{
548 Eina_List *elist;
549 Elm_Popup_Content_Item *item;
550
551 if (!wd->items) return;
552 EINA_LIST_FOREACH(wd->items, elist, item)
553 {
554 if (item->label)
555 eina_stringshare_del(item->label);
556 if (item->icon)
557 {
558 evas_object_del(item->icon);
559 item->icon = NULL;
560 }
561 evas_object_del(VIEW(item));
562 wd->items = eina_list_remove(wd->items, item);
563 free(item);
564 }
565 wd->items = NULL;
566}
567
568static void
569_notify_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
570 void *event_info __UNUSED__)
571{
572 Widget_Data *wd = elm_widget_data_get(data);
573
574 if (wd->items)
575 _scroller_size_calc(data);
576 _sizing_eval(data);
577}
578
579static void
580_title_text_set(Evas_Object *obj, const char *text)
581{
582 ELM_CHECK_WIDTYPE(obj, widtype);
583 Eina_Bool title_visibility_old, title_visibility_current;
584 Widget_Data *wd = elm_widget_data_get(obj);
585
586 if (!wd) return;
587 if (wd->title_text == text) return;
588 title_visibility_old = (wd->title_text) || (wd->title_icon);
589 eina_stringshare_replace(&wd->title_text, text);
590 elm_object_part_text_set(wd->base, "elm.text.title", text);
591 if (wd->title_text)
592 elm_object_signal_emit(wd->base, "elm,state,title,text,visible", "elm");
593 else
594 elm_object_signal_emit(wd->base, "elm,state,title,text,hidden", "elm");
595 title_visibility_current = (wd->title_text) || (wd->title_icon);
596 if (title_visibility_old != title_visibility_current)
597 _layout_set(obj);
598 edje_object_message_signal_process(wd->base);
599 _sizing_eval(obj);
600}
601
602static void
603_content_text_set(Evas_Object *obj, const char *text)
604{
605 ELM_CHECK_WIDTYPE(obj, widtype);
606 Evas_Object *prev_content;
607 char buf[128];
608 Widget_Data *wd = elm_widget_data_get(obj);
609
610 if (!wd) return;
611 if (wd->items)
612 {
613 _remove_items(wd);
614 _list_del(wd);
615 }
616 prev_content = elm_object_part_content_get(wd->content_area,
617 "elm.swallow.content");
618 if (prev_content)
619 evas_object_del(prev_content);
620 if (text)
621 {
622 elm_object_part_content_set(wd->base, "elm.swallow.content",
623 wd->content_area);
624 wd->content_text_obj = elm_label_add(obj);
625 snprintf(buf, sizeof(buf), "popup/%s",
626 elm_widget_style_get(obj));
627 elm_object_style_set(wd->content_text_obj, buf);
628 elm_label_line_wrap_set(wd->content_text_obj,
629 wd->content_text_wrap_type);
630 elm_object_text_set(wd->content_text_obj, text);
631 evas_object_size_hint_weight_set(wd->content_text_obj, EVAS_HINT_EXPAND,
632 0.0);
633 evas_object_size_hint_align_set(wd->content_text_obj, EVAS_HINT_FILL,
634 EVAS_HINT_FILL);
635 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
636 wd->content_text_obj);
637 }
638 _sizing_eval(obj);
639}
640
641static void
642_text_set_hook(Evas_Object *obj, const char *part,
643 const char *label)
644{
645 ELM_CHECK_WIDTYPE(obj, widtype);
646 Widget_Data *wd = elm_widget_data_get(obj);
647
648 if (!wd) return;
649 if (!part || !strcmp(part, "default"))
650 _content_text_set(obj, label);
651 else if (!strcmp(part, "title,text"))
652 _title_text_set(obj, label);
653 else
654 WRN("The part name is invalid! : popup=%p", obj);
655}
656
657static const char*
658_title_text_get(const Evas_Object *obj)
659{
660 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
661 Widget_Data *wd = elm_widget_data_get(obj);
662
663 if (!wd) return NULL;
664 return wd->title_text;
665}
666
667static const char*
668_content_text_get(const Evas_Object *obj)
669{
670 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
671 const char *str = NULL;
672 Widget_Data *wd = elm_widget_data_get(obj);
673
674 if (!wd) return NULL;
675 if (wd->content_text_obj)
676 str = elm_object_text_get(wd->content_text_obj);
677 return str;
678}
679
680static const char *
681_text_get_hook(const Evas_Object *obj, const char *part)
682{
683 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
684 const char *str = NULL;
685 Widget_Data *wd = elm_widget_data_get(obj);
686
687 if (!wd) return NULL;
688 if (!part || !strcmp(part, "default"))
689 str = _content_text_get(obj);
690 else if (!strcmp(part, "title,text"))
691 str = _title_text_get(obj);
692 else
693 WRN("The part name is invalid! : popup=%p", obj);
694 return str;
695}
696
697static void
698_title_icon_set(Evas_Object *obj, Evas_Object *icon)
699{
700 ELM_CHECK_WIDTYPE(obj, widtype);
701 Eina_Bool title_visibility_old, title_visibility_current;
702 Widget_Data *wd = elm_widget_data_get(obj);
703
704 if (!wd) return;
705 if (wd->title_icon == icon) return;
706 title_visibility_old = (wd->title_text) || (wd->title_icon);
707 if (wd->title_icon) evas_object_del(wd->title_icon);
708
709 wd->title_icon = icon;
710 title_visibility_current = (wd->title_text) || (wd->title_icon);
711 elm_object_part_content_set(wd->base, "elm.swallow.title.icon",
712 wd->title_icon);
713 if (wd->title_icon)
714 elm_object_signal_emit(wd->base, "elm,state,title,icon,visible", "elm");
715 if (title_visibility_old != title_visibility_current) _layout_set(obj);
716 edje_object_message_signal_process(wd->base);
717 _sizing_eval(obj);
718}
719
720static void
721_content_set(Evas_Object *obj, Evas_Object *content)
722{
723 ELM_CHECK_WIDTYPE(obj, widtype);
724 Evas_Object *prev_content;
725 Widget_Data *wd = elm_widget_data_get(obj);
726
727 if (!wd) return;
728 if (wd->content && wd->content == content) return;
729 if (wd->items)
730 {
731 _remove_items(wd);
732 _list_del(wd);
733 }
734 prev_content = elm_object_part_content_get(wd->content_area,
735 "elm.swallow.content");
736 if (prev_content)
737 evas_object_del(prev_content);
738 wd->content = content;
739 if (content)
740 {
741 elm_object_part_content_set(wd->base, "elm.swallow.content",
742 wd->content_area);
743 elm_object_part_content_set(wd->content_area, "elm.swallow.content",
744 content);
745 evas_object_show(content);
746 }
747 _sizing_eval(obj);
748}
749
750static void
751_button_remove(Evas_Object *obj, Evas_Object *content, Eina_Bool delete)
752{
753 unsigned int i = 0, position = 0;
754 char buf[128];
755 Widget_Data *wd = elm_widget_data_get(obj);
756
757 if (!wd->button_count) return;
758 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
759 {
760 if (wd->buttons[i])
761 {
762 position++;
763 wd->buttons[i]->delete_me = EINA_FALSE;
764 if (wd->buttons[i]->btn == content)
765 {
766 snprintf(buf, sizeof(buf), "actionbtn%u", position);
767 elm_object_part_content_unset(wd->action_area, buf);
768 evas_object_hide(content);
769 if (delete) evas_object_del(content);
770 free(wd->buttons[i]);
771 wd->buttons[i] = NULL;
772 wd->button_count -= 1;
773 }
774 }
775 }
776 position = 0;
777 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
778 {
779 if (!wd->buttons[i]) continue;
780 position++;
781 snprintf(buf, sizeof(buf), "actionbtn%u", position);
782 elm_object_part_content_unset(wd->action_area, buf);
783 elm_object_part_content_set(wd->action_area, buf,
784 wd->buttons[i]->btn);
785 evas_object_show(wd->buttons[i]->btn);
786 wd->buttons[i]->delete_me = EINA_TRUE;
787 }
788 if (!wd->button_count)
789 {
790 _layout_set(obj);
791 elm_object_part_content_unset(wd->base, "elm.swallow.action_area");
792 evas_object_hide(wd->action_area);
793 edje_object_message_signal_process(elm_layout_edje_get(wd->base));
794 }
795 else
796 {
797 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
798 elm_layout_theme_set(wd->action_area, "popup", buf,
799 elm_widget_style_get(obj));
800 }
801}
802
803static void
804_action_button_set(Evas_Object *obj, Evas_Object *btn, unsigned int idx)
805{
806 Action_Area_Data *adata;
807 char buf[128];
808 unsigned int num = idx - 1, i = 0, position = 0;
809 Widget_Data *wd = elm_widget_data_get(obj);
810
811 if (!wd) return;
812 if (num >= ELM_POPUP_ACTION_BUTTON_MAX) return;
813 if (wd->buttons[num])
814 _button_remove(obj, wd->buttons[num]->btn, EINA_TRUE);
815 if (btn)
816 {
817 wd->button_count++;
818 snprintf(buf, sizeof(buf), "buttons%u", wd->button_count);
819 elm_layout_theme_set(wd->action_area, "popup", buf,
820 elm_widget_style_get(obj));
821 adata = ELM_NEW(Action_Area_Data);
822 adata->obj = obj;
823 adata->btn = btn;
824 wd->buttons[num] = adata;
825 /* Adding delete_me state inside action data as unset calls _sub_del
826 too and before setting a new content, the previous one needs to
827 be unset in order to avoid unwanted deletion. This way rearrangement
828 of buttons can be achieved in action area.
829 */
830 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
831 if (wd->buttons[i])
832 wd->buttons[i]->delete_me = EINA_FALSE;
833 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
834 {
835 if (!wd->buttons[i]) continue;
836 position++;
837 snprintf(buf, sizeof(buf), "actionbtn%u", position);
838 elm_object_part_content_unset(wd->action_area, buf);
839 elm_object_part_content_set(wd->action_area, buf,
840 wd->buttons[i]->btn);
841 evas_object_show(wd->buttons[i]->btn);
842 /* Setting delete_me to TRUE in order to let _sub_del handle it
843 if deleted externally and update the buttons array after freeing
844 action data allocated earlier.
845 */
846 wd->buttons[i]->delete_me = EINA_TRUE;
847 }
848 elm_object_part_content_set(wd->base, "elm.swallow.action_area",
849 wd->action_area);
850 evas_object_show(wd->action_area);
851 if (wd->button_count == 1)
852 _layout_set(obj);
853 edje_object_message_signal_process(wd->base);
854 if (wd->items)
855 _scroller_size_calc(obj);
856 _sizing_eval(obj);
857 }
858}
859
860static void
861_content_set_hook(Evas_Object *obj, const char *part,
862 Evas_Object *content)
863{
864 ELM_CHECK_WIDTYPE(obj, widtype);
865 char buff[3];
866 unsigned int i;
867 Widget_Data *wd = elm_widget_data_get(obj);
868
869 if (!wd) return;
870 if (!part || !strcmp(part, "default"))
871 _content_set(obj, content);
872 else if (!strcmp(part, "title,icon"))
873 _title_icon_set(obj, content);
874 else if (!strncmp(part, "button", 6))
875 {
876 part += 6;
877 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
878 {
879 snprintf(buff, sizeof(buff), "%u", i+1);
880 if (!strncmp(part, buff, sizeof(buff)))
881 {
882 _action_button_set(obj, content, i+1);
883 break;
884 }
885 }
886 }
887 else
888 WRN("The part name is invalid! : popup=%p", obj);
889}
890
891static Evas_Object *
892_title_icon_get(Evas_Object *obj)
893{
894 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
895 Widget_Data *wd = elm_widget_data_get(obj);
896
897 if (!wd) return NULL;
898 return wd->title_icon;
899}
900
901static Evas_Object *
902_content_get(Evas_Object *obj)
903{
904 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
905 Widget_Data *wd = elm_widget_data_get(obj);
906
907 if (!wd) return NULL;
908 return wd->content;
909}
910
911static Evas_Object *
912_action_button_get(Evas_Object *obj, unsigned int idx)
913{
914 unsigned int num = idx - 1;
915 Evas_Object *button = NULL;
916 Widget_Data *wd = elm_widget_data_get(obj);
917
918 if (!wd || !wd->button_count) return NULL;
919 if (wd->buttons[num])
920 button = wd->buttons[num]->btn;
921 return button;
922}
923
924static Evas_Object *
925_content_get_hook(Evas_Object *obj, const char *part)
926{
927 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
928 Evas_Object *content = NULL;
929 char buff[3];
930 unsigned int i;
931 Widget_Data *wd = elm_widget_data_get(obj);
932
933 if (!wd) return NULL;
934 if (!part || !strcmp(part, "default"))
935 content = _content_get(obj);
936 else if (!strcmp(part, "title,text"))
937 content = _title_icon_get(obj);
938 else if (!strncmp(part, "button", 6))
939 {
940 part += 6;
941 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
942 {
943 snprintf(buff, sizeof(buff), "%u", i+1);
944 if (!strncmp(part, buff, sizeof(buff)))
945 {
946 content = _action_button_get(obj, i+1);
947 break;
948 }
949 }
950 }
951 else
952 WRN("The part name is invalid! : popup=%p", obj);
953 return content;
954}
955
956static Evas_Object *
957_content_unset(Evas_Object *obj)
958{
959 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
960 Evas_Object *content;
961 Widget_Data *wd = elm_widget_data_get(obj);
962
963 if (!wd || !wd->content) return NULL;
964 content = elm_object_part_content_unset(wd->content_area,
965 "elm.swallow.content");
966 wd->content = NULL;
967 _sizing_eval(obj);
968 return content;
969}
970
971static Evas_Object *
972_title_icon_unset(Evas_Object *obj)
973{
974 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
975 Evas_Object *icon;
976 Widget_Data *wd = elm_widget_data_get(obj);
977
978 if (!wd || !wd->title_icon) return NULL;
979 icon = elm_object_part_content_unset(wd->base, "elm.swallow.title.icon");
980 wd->title_icon = NULL;
981 return icon;
982}
983
984static Evas_Object *
985_action_button_unset(Evas_Object *obj, unsigned int idx)
986{
987 unsigned int num = idx -1;
988 Evas_Object *button = NULL;
989 Widget_Data *wd = elm_widget_data_get(obj);
990
991 if (!wd) return NULL;
992 if ((!wd->button_count) || (num >= ELM_POPUP_ACTION_BUTTON_MAX))
993 return NULL;
994
995 if (wd->buttons[num])
996 {
997 button = wd->buttons[num]->btn;
998 _button_remove(obj, button, EINA_FALSE);
999 }
1000 return button;
1001}
1002
1003static Evas_Object *
1004_content_unset_hook(Evas_Object *obj, const char *part)
1005{
1006 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1007 Evas_Object *content = NULL;
1008 char buff[3];
1009 unsigned int i;
1010 Widget_Data *wd = elm_widget_data_get(obj);
1011
1012 if (!wd) return NULL;
1013 if (!part || !strcmp(part, "default"))
1014 content = _content_unset(obj);
1015 else if (!strcmp(part, "title,icon"))
1016 content = _title_icon_unset(obj);
1017 else if (!strncmp(part, "button", 6))
1018 {
1019 part += 6;
1020 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1021 {
1022 snprintf(buff, sizeof(buff), "%u", i+1);
1023 if (!strncmp(part, buff, sizeof(buff)))
1024 {
1025 content = _action_button_unset(obj, i+1);
1026 break;
1027 }
1028 }
1029 }
1030 else
1031 WRN("The part name is invalid! : popup=%p", obj);
1032 return content;
1033}
1034
1035static Eina_Bool
1036_focus_next_hook(const Evas_Object *obj,
1037 Elm_Focus_Direction dir,
1038 Evas_Object **next)
1039{
1040 Widget_Data *wd = elm_widget_data_get(obj);
1041
1042 if (!wd)
1043 return EINA_FALSE;
1044 return elm_widget_focus_next_get(wd->notify, dir, next);
1045}
1046
1047static void
1048_item_text_set(Elm_Popup_Content_Item *item, const char *label)
1049{
1050 if (!eina_stringshare_replace(&item->label, label)) return;
1051 edje_object_part_text_escaped_set(VIEW(item), "elm.text", label);
1052 if (item->label)
1053 edje_object_signal_emit(VIEW(item),
1054 "elm,state,item,text,visible", "elm");
1055 else
1056 edje_object_signal_emit(VIEW(item),
1057 "elm,state,item,text,hidden", "elm");
1058 edje_object_message_signal_process(VIEW(item));
1059}
1060
1061static void
1062_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
1063{
1064 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1065 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1066
1067 if ((!part) || (!strcmp(part, "default")))
1068 {
1069 _item_text_set(item, label);
1070 return;
1071 }
1072 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1073}
1074
1075static const char *
1076_item_text_get_hook(const Elm_Object_Item *it, const char *part)
1077{
1078 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1079 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1080
1081 if ((!part) || (!strcmp(part, "default")))
1082 return item->label;
1083 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1084 return NULL;
1085}
1086
1087static void
1088_item_icon_set(Elm_Popup_Content_Item *item, Evas_Object *icon)
1089{
1090 if (item->icon == icon) return;
1091 if (item->icon)
1092 {
1093 evas_object_data_del(item->icon, "_popup_content_item");
1094 evas_object_del(item->icon);
1095 }
1096 item->icon = icon;
1097 if (item->icon)
1098 {
1099 elm_widget_sub_object_add(WIDGET(item), item->icon);
1100 evas_object_data_set(item->icon, "_popup_content_item", item);
1101 edje_object_part_swallow(VIEW(item), "elm.swallow.content",
1102 item->icon);
1103 edje_object_signal_emit(VIEW(item),
1104 "elm,state,item,icon,visible", "elm");
1105 }
1106 else
1107 edje_object_signal_emit(VIEW(item),
1108 "elm,state,item,icon,hidden", "elm");
1109 edje_object_message_signal_process(item->base.view);
1110}
1111
1112static void
1113_item_content_set_hook(Elm_Object_Item *it, const char *part,
1114 Evas_Object *content)
1115{
1116 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1117 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1118
1119 if ((!(part)) || (!strcmp(part, "default")))
1120 _item_icon_set(item, content);
1121 else
1122 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1123}
1124
1125static Evas_Object *
1126_item_content_get_hook(const Elm_Object_Item *it,
1127 const char *part)
1128{
1129 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1130 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1131
1132 if ((!(part)) || (!strcmp(part, "default")))
1133 return item->icon;
1134 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1135 return NULL;
1136}
1137
1138static Evas_Object *
1139_item_icon_unset(Elm_Popup_Content_Item *item)
1140{
1141 Evas_Object *icon = item->icon;
1142
1143 if (!item->icon) return NULL;
1144 elm_widget_sub_object_del(WIDGET(item), icon);
1145 evas_object_data_del(icon, "_popup_content_item");
1146 edje_object_part_unswallow(item->base.view, icon);
1147 edje_object_signal_emit(VIEW(item),
1148 "elm,state,item,icon,hidden", "elm");
1149 item->icon = NULL;
1150 return icon;
1151}
1152
1153static Evas_Object *
1154_item_content_unset_hook(const Elm_Object_Item *it,
1155 const char *part)
1156{
1157 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1158 Evas_Object *content = NULL;
1159 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1160
1161 if ((!(part)) || (!strcmp(part, "default")))
1162 content = _item_icon_unset(item);
1163 else
1164 WRN("The part name is invalid! : popup=%p", WIDGET(item));
1165 return content;
1166}
1167
1168static void
1169_item_disable_hook(Elm_Object_Item *it)
1170{
1171 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1172 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1173 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1174
1175 if (!wd) return;
1176 if (elm_widget_item_disabled_get(it))
1177 edje_object_signal_emit(VIEW(item), "elm,state,item,disabled", "elm");
1178 else
1179 edje_object_signal_emit(VIEW(item), "elm,state,item,enabled", "elm");
1180}
1181
1182static void
1183_item_del_pre_hook(Elm_Object_Item *it)
1184{
1185 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1186 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1187 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1188
1189 if (!wd) return;
1190 if (item->icon)
1191 evas_object_del(item->icon);
1192 eina_stringshare_del(item->label);
1193 wd->items = eina_list_remove(wd->items, item);
1194 if (!eina_list_count(wd->items))
1195 {
1196 wd->items = NULL;
1197 _list_del(wd);
1198 }
1199}
1200
1201static void
1202_item_signal_emit_hook(Elm_Object_Item *it, const char *emission,
1203 const char *source)
1204{
1205 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1206 Elm_Popup_Content_Item *item = (Elm_Popup_Content_Item *)it;
1207
1208 edje_object_signal_emit(VIEW(item), emission, source);
1209}
1210
1211static void
1212_popup_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1213 void *event_info __UNUSED__)
1214{
1215 Widget_Data *wd;
1216
1217 wd = elm_widget_data_get(obj);
1218 if (!wd) return;
1219
1220 evas_object_show(wd->notify);
1221}
1222
1223static void
1224_popup_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
1225 void *event_info __UNUSED__)
1226{
1227 Widget_Data *wd;
1228
1229 wd = elm_widget_data_get(obj);
1230 if (!wd) return;
1231
1232 evas_object_hide(wd->notify);
1233}
1234
1235EAPI Evas_Object *
1236elm_popup_add(Evas_Object *parent)
1237{
1238 Evas_Object *obj;
1239 Evas *e;
1240 int i = 0;
1241 Widget_Data *wd;
1242
1243 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1244 ELM_SET_WIDTYPE(widtype, "popup");
1245 elm_widget_type_set(obj, widtype);
1246 elm_widget_sub_object_add(parent, obj);
1247 elm_widget_data_set(obj, wd);
1248 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1249 elm_widget_del_hook_set(obj, _del_hook);
1250 elm_widget_theme_hook_set(obj, _theme_hook);
1251 elm_widget_text_set_hook_set(obj, _text_set_hook);
1252 elm_widget_text_get_hook_set(obj, _text_get_hook);
1253 elm_widget_content_set_hook_set(obj, _content_set_hook);
1254 elm_widget_content_get_hook_set(obj, _content_get_hook);
1255 elm_widget_content_unset_hook_set(obj,_content_unset_hook);
1256 elm_widget_can_focus_set(obj, EINA_FALSE);
1257 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
1258 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1259
1260 wd->notify = elm_notify_add(obj);
1261 elm_notify_parent_set(wd->notify, parent);
1262 elm_notify_orient_set(wd->notify, ELM_NOTIFY_ORIENT_CENTER);
1263 elm_notify_allow_events_set(wd->notify, EINA_FALSE);
1264 evas_object_size_hint_weight_set(wd->notify,
1265 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1266 evas_object_size_hint_align_set(wd->notify, EVAS_HINT_FILL, EVAS_HINT_FILL);
1267 elm_object_style_set(wd->notify, "popup");
1268
1269 evas_object_event_callback_add(wd->notify, EVAS_CALLBACK_RESIZE,
1270 _notify_resize, obj);
1271 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _popup_show,
1272 NULL);
1273 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _popup_hide,
1274 NULL);
1275 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, NULL);
1276 wd->base = elm_layout_add(obj);
1277 evas_object_size_hint_weight_set(wd->base, EVAS_HINT_EXPAND,
1278 EVAS_HINT_EXPAND);
1279 evas_object_size_hint_align_set(wd->base, EVAS_HINT_FILL, EVAS_HINT_FILL);
1280
1281 elm_layout_theme_set(wd->base, "popup", "base", elm_widget_style_get(obj));
1282 elm_object_content_set(wd->notify, wd->base);
1283
1284 elm_object_signal_callback_add(wd->base, "elm,state,title_area,visible",
1285 "elm", _layout_change_cb, obj);
1286 elm_object_signal_callback_add(wd->base, "elm,state,title_area,hidden",
1287 "elm", _layout_change_cb, obj);
1288 elm_object_signal_callback_add(wd->base, "elm,state,action_area,visible",
1289 "elm", _layout_change_cb, obj);
1290 elm_object_signal_callback_add(wd->base, "elm,state,action_area,hidden",
1291 "elm", _layout_change_cb, obj);
1292 wd->content_area = elm_layout_add(obj);
1293 elm_layout_theme_set(wd->content_area, "popup", "content",
1294 elm_widget_style_get(obj));
1295 wd->action_area = elm_layout_add(obj);
1296 evas_object_size_hint_weight_set(wd->action_area, EVAS_HINT_EXPAND,
1297 EVAS_HINT_EXPAND);
1298 evas_object_size_hint_align_set(wd->action_area, EVAS_HINT_FILL,
1299 EVAS_HINT_FILL);
1300 evas_object_event_callback_add(wd->action_area,
1301 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1302 _changed_size_hints, obj);
1303 evas_object_event_callback_add(wd->content_area,
1304 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1305 _changed_size_hints, obj);
1306 evas_object_smart_callback_add(wd->base, "sub-object-del",
1307 _sub_del, obj);
1308 evas_object_smart_callback_add(wd->content_area, "sub-object-del",
1309 _sub_del, obj);
1310 evas_object_smart_callback_add(wd->action_area, "sub-object-del",
1311 _sub_del, obj);
1312 evas_object_smart_callback_add(obj, "sub-object-del",
1313 _sub_del, obj);
1314
1315 wd->content_text_wrap_type = ELM_WRAP_MIXED;
1316 evas_object_smart_callback_add(wd->notify, "block,clicked",
1317 _block_clicked_cb, obj);
1318 evas_object_smart_callback_add(wd->notify, "timeout", _timeout, obj);
1319 for (i = 0; i < ELM_POPUP_ACTION_BUTTON_MAX; i++)
1320 wd->buttons[i] = NULL;
1321 _layout_set(obj);
1322 //TODO: To use scroller for description also
1323 return obj;
1324}
1325
1326EAPI void
1327elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap)
1328{
1329 ELM_CHECK_WIDTYPE(obj, widtype);
1330 Evas_Object *content_text_obj;
1331 Widget_Data *wd = elm_widget_data_get(obj);
1332
1333 if (!wd) return;
1334 if (wd->content_text_wrap_type == ELM_WRAP_NONE) return;
1335 //Need to wrap the content text, so not allowing ELM_WRAP_NONE
1336 wd->content_text_wrap_type = wrap;
1337 if (wd->content_text_obj)
1338 {
1339 content_text_obj = elm_object_part_content_get(wd->content_area,
1340 "elm.swallow.content");
1341 elm_label_line_wrap_set(content_text_obj, wrap);
1342 }
1343}
1344
1345EAPI Elm_Wrap_Type
1346elm_popup_content_text_wrap_type_get(const Evas_Object *obj)
1347{
1348 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WRAP_LAST;
1349 Widget_Data *wd = elm_widget_data_get(obj);
1350
1351 if (!wd) return ELM_WRAP_LAST;
1352 return wd->content_text_wrap_type;
1353}
1354
1355EAPI void
1356elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient)
1357{
1358 ELM_CHECK_WIDTYPE(obj, widtype);
1359 Widget_Data *wd = elm_widget_data_get(obj);
1360
1361 if (!wd) return;
1362 if (orient >= ELM_POPUP_ORIENT_LAST) return;
1363 elm_notify_orient_set(wd->notify, (Elm_Notify_Orient)orient);
1364}
1365
1366EAPI Elm_Popup_Orient
1367elm_popup_orient_get(const Evas_Object *obj)
1368{
1369 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1370 Widget_Data *wd = elm_widget_data_get(obj);
1371
1372 if (!wd) return ELM_POPUP_ORIENT_LAST;
1373 return (Elm_Popup_Orient)elm_notify_orient_get(wd->notify);
1374}
1375
1376EAPI void
1377elm_popup_timeout_set(Evas_Object *obj, double timeout)
1378{
1379 ELM_CHECK_WIDTYPE(obj, widtype);
1380 Widget_Data *wd = elm_widget_data_get(obj);
1381
1382 if (!wd) return;
1383 elm_notify_timeout_set(wd->notify, timeout);
1384}
1385
1386EAPI double
1387elm_popup_timeout_get(const Evas_Object *obj)
1388{
1389 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1390 Widget_Data *wd = elm_widget_data_get(obj);
1391
1392 if (!wd) return 0.0;
1393 return elm_notify_timeout_get(wd->notify);
1394}
1395
1396EAPI void
1397elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow)
1398{
1399 ELM_CHECK_WIDTYPE(obj, widtype);
1400 Eina_Bool allow_events = !!allow;
1401 Widget_Data *wd = elm_widget_data_get(obj);
1402
1403 if (!wd) return;
1404 elm_notify_allow_events_set(wd->notify, allow_events);
1405}
1406
1407EAPI Eina_Bool
1408elm_popup_allow_events_get(const Evas_Object *obj)
1409{
1410 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1411 Widget_Data *wd = elm_widget_data_get(obj);
1412
1413 if (!wd) return EINA_FALSE;
1414 return elm_notify_allow_events_get(wd->notify);
1415}
1416
1417EAPI Elm_Object_Item *
1418elm_popup_item_append(Evas_Object *obj, const char *label,
1419 Evas_Object *icon, Evas_Smart_Cb func,
1420 const void *data)
1421{
1422 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1423 Evas_Object *prev_content;
1424 Elm_Popup_Content_Item *item;
1425 Widget_Data *wd = elm_widget_data_get(obj);
1426
1427 if (!wd) return NULL;
1428 item = elm_widget_item_new(obj, Elm_Popup_Content_Item);
1429 if (!item) return NULL;
1430 if (wd->content || wd->content_text_obj)
1431 {
1432 prev_content = elm_object_part_content_get(wd->content_area,
1433 "elm.swallow.content");
1434 if (prev_content)
1435 evas_object_del(prev_content);
1436 }
1437
1438 //The first item is appended.
1439 if (!wd->items)
1440 _list_new(obj);
1441
1442 item->func = func;
1443 item->base.data = data;
1444
1445 _item_new(item);
1446 _item_icon_set(item, icon);
1447 _item_text_set(item, label);
1448 elm_box_pack_end(wd->box, VIEW(item));
1449 wd->items = eina_list_append(wd->items, item);
1450
1451 _scroller_size_calc(obj);
1452 _sizing_eval(obj);
1453 return (Elm_Object_Item *)item;
1454}
diff --git a/libraries/elementary/src/lib/elc_popup.h b/libraries/elementary/src/lib/elc_popup.h
new file mode 100644
index 0000000..14687af
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_popup.h
@@ -0,0 +1,269 @@
1/**
2 * @defgroup Popup Popup
3 * @ingroup Elementary
4 *
5 * This widget is an enhancement of @ref Notify.
6 * In addition to Content area, there are two optional sections namely Title
7 * area and Action area.
8 *
9 * Popup Widget displays its content with a particular orientation in the parent
10 * area. This orientation can be one among top, center, bottom, left, top-left,
11 * top-right, bottom-left and bottom-right.
12 * Content part of Popup can be an Evas Object set by application or it can be
13 * Text set by application or set of items containing an icon and/or text.
14 * The content/item-list can be removed using elm_object_content_set with second
15 * parameter passed as NULL.
16 *
17 * Following figures shows the textual layouts of popup in which Title Area and
18 * Action area area are optional ones.
19 * Action area can have up to 3 buttons handled using elm_object common APIs
20 * mentioned below. If user wants to have more than 3 buttons then these buttons
21 * can be put inside the items of a list as content.
22 * User needs to handle the clicked signal of these action buttons if required.
23 * No event is processed by the widget automatically when clicked on these
24 * action buttons.
25 *
26 * <pre>
27 *
28 * |-------------------- | |----------------- ---| |----------------- ---|
29 * | Title Area | | Title Area | | Title Area |
30 * |Icon| Text | |Icon| Text | |Icon| Text |
31 * |------------------- -| |---------------- ----| |------------------ --|
32 * | Item 1 | | | | |
33 * |------------------- -| | | | |
34 * | Item 2 | | | | Description |
35 * |------------------ --| | Content | | |
36 * | Item 3 | | | | |
37 * |------------------ --| | | | |
38 * | . | |------------------ --| |------------------- -|
39 * | . | | Action Area | | Action Area |
40 * | . | | Btn1 |Btn2|. |Btn3 | | Btn1 |Btn2| |Btn3 |
41 * |------------------ --| |------------------- -| |------------------- -|
42 * | Item N | Content Based Layout Description based Layout
43 * |------------------ --|
44 * | Action Area |
45 * | Btn1 |Btn2|. |Btn3 |
46 * |------------------- -|
47 * Item Based Layout
48 *
49 * </pre>
50 *
51 * Timeout can be set on expiry of which popup instance hides and sends a smart
52 * signal "timeout" to the user.
53 * The visible region of popup is surrounded by a translucent region called
54 * Blocked Event area.
55 * By clicking on Blocked Event area, the signal "block,clicked" is sent to
56 * the application. This block event area can be avoided by using
57 * API elm_popup_allow_events_set.
58 * When gets hidden, popup does not get destroyed automatically, application
59 * should destroy the popup instance after use.
60 * To control the maximum height of the internal scroller for item, we use the
61 * height of the action area which is passed by theme based on the number of
62 * buttons currently set to popup.
63 *
64 * Signals that you can add callbacks for are:
65 * @li "timeout" - when ever popup is closed as a result of timeout.
66 * @li "block,clicked" - when ever user taps on Blocked Event area.
67 *
68 * Styles available for Popup
69 * @li "default"
70 *
71 * Default contents parts of the popup widget that you can use for are:
72 * @li "default" - The content of the popup
73 * @li "title,icon" - Title area's icon
74 * @li "button1" - 1st button of the action area
75 * @li "button2" - 2nd button of the action area
76 * @li "button3" - 3rd button of the action area
77 *
78 * Default text parts of the popup widget that you can use for are:
79 * @li "title,text" - This operates on Title area's label
80 * @li "default" - content-text set in the content area of the widget
81 *
82 * Default contents parts of the popup items that you can use for are:
83 * @li "default" -Item's icon
84 *
85 * Default text parts of the popup items that you can use for are:
86 * @li "default" - Item's label
87 *
88 * Supported elm_object common APIs.
89 * @li @ref elm_object_part_content_set
90 * @li @ref elm_object_part_content_get
91 * @li @ref elm_object_part_content_unset
92 *
93 * Supported elm_object_item common APIs.
94 * @li @ref elm_object_item_disabled_set
95 * @li @ref elm_object_item_disabled_get
96 * @li @ref elm_object_item_part_text_set
97 * @li @ref elm_object_item_part_text_get
98 * @li @ref elm_object_item_part_content_set
99 * @li @ref elm_object_item_part_content_get
100 * @li @ref elm_object_item_signal_emit
101 * @li @ref elm_object_item_del
102 *
103 * Here are some sample code to illustrate Popup usage:
104 * @li @ref popup_example_01_c
105 * @li @ref popup_example_02_c
106 * @li @ref popup_example_03_c
107 */
108
109/**
110 * @brief Possible orient values for popup.
111 *
112 * These values should be used in conjunction to elm_popup_orient_set() to
113 * set the position in which the popup should appear(relative to its parent)
114 * and in conjunction with elm_popup_orient_get() to know where the popup
115 * is appearing.
116 *
117 * @ingroup Popup
118 */
119typedef enum
120{
121 ELM_POPUP_ORIENT_TOP = 0, /**< Popup should appear in the top of parent, default */
122 ELM_POPUP_ORIENT_CENTER, /**< Popup should appear in the center of parent */
123 ELM_POPUP_ORIENT_BOTTOM, /**< Popup should appear in the bottom of parent */
124 ELM_POPUP_ORIENT_LEFT, /**< Popup should appear in the left of parent */
125 ELM_POPUP_ORIENT_RIGHT, /**< Popup should appear in the right of parent */
126 ELM_POPUP_ORIENT_TOP_LEFT, /**< Popup should appear in the top left of parent */
127 ELM_POPUP_ORIENT_TOP_RIGHT, /**< Popup should appear in the top right of parent */
128 ELM_POPUP_ORIENT_BOTTOM_LEFT, /**< Popup should appear in the bottom left of parent */
129 ELM_POPUP_ORIENT_BOTTOM_RIGHT, /**< Notify should appear in the bottom right of parent */
130 ELM_POPUP_ORIENT_LAST /**< Sentinel value, @b don't use */
131 } Elm_Popup_Orient;
132
133/**
134 * @brief Adds a new Popup to the parent
135 *
136 * @param parent The parent object
137 * @return The new object or NULL if it cannot be created
138 *
139 * @ingroup Popup
140 */
141EAPI Evas_Object *elm_popup_add(Evas_Object *parent) EINA_ARG_NONNULL(1);
142
143/**
144 * @brief Add a new item to a Popup object
145 *
146 * Both an item list and a content could not be set at the same time!
147 * once you add an item, the previous content will be removed.
148 *
149 * @param obj popup object
150 * @param icon Icon to be set on new item
151 * @param label The Label of the new item
152 * @param func Convenience function called when item selected
153 * @param data Data passed to @p func above
154 * @return A handle to the item added or @c NULL, on errors
155 *
156 * @ingroup Popup
157 * @warning When the first item is appended to popup object, any previous content
158 * of the content area is deleted. At a time, only one of content, content-text
159 * and item(s) can be there in a popup content area.
160 */
161EAPI Elm_Object_Item *elm_popup_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data) EINA_ARG_NONNULL(1);
162
163/**
164 * @brief Sets the wrapping type of content text packed in content
165 * area of popup object.
166 *
167 * @param obj The Popup object
168 * @param wrap wrapping type of type Elm_Wrap_Type
169 *
170 * @ingroup Popup
171 * @see elm_popup_content_text_wrap_type_get()
172 */
173EAPI void elm_popup_content_text_wrap_type_set(Evas_Object *obj, Elm_Wrap_Type wrap) EINA_ARG_NONNULL(1);
174
175/**
176 * @brief Returns the wrapping type of content text packed in content area of
177 * popup object.
178 *
179 * @param obj The Popup object
180 * @return wrap type of the content text
181 *
182 * @ingroup Popup
183 * @see elm_popup_content_text_wrap_type_set
184 */
185EAPI Elm_Wrap_Type elm_popup_content_text_wrap_type_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
186
187/**
188 * @brief Sets the orientation of the popup in the parent region
189 *
190 * @param obj The popup object
191 * @param orient the orientation of the popup
192 *
193 * Sets the position in which popup will appear in its parent
194 *
195 * @ingroup Popup
196 * @see @ref Elm_Popup_Orient for possible values.
197 */
198EAPI void elm_popup_orient_set(Evas_Object *obj, Elm_Popup_Orient orient) EINA_ARG_NONNULL(1);
199
200/**
201 * @brief Returns the orientation of Popup
202 *
203 * @param obj The popup object
204 * @return the orientation of the popup
205 *
206 * @ingroup Popup
207 * @see elm_popup_orient_set()
208 * @see Elm_Popup_Orient
209 */
210EAPI Elm_Popup_Orient elm_popup_orient_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
211
212/**
213 * @brief Sets a timeout to hide popup automatically
214 *
215 * @param obj The popup object
216 * @param timeout The timeout in seconds
217 *
218 * This function sets a timeout and starts the timer controlling when the
219 * popup is hidden. Since calling evas_object_show() on a popup restarts
220 * the timer controlling when it is hidden, setting this before the
221 * popup is shown will in effect mean starting the timer when the popup is
222 * shown. Smart signal "timeout" is called afterwards which can be handled
223 * if needed.
224 *
225 * @note Set a value <= 0.0 to disable a running timer.
226 *
227 * @note If the value > 0.0 and the popup is previously visible, the
228 * timer will be started with this value, canceling any running timer.
229 * @ingroup Popup
230 */
231EAPI void elm_popup_timeout_set(Evas_Object *obj, double timeout) EINA_ARG_NONNULL(1);
232
233/**
234 * @brief Returns the timeout value set to the popup (in seconds)
235 *
236 * @param obj The popup object
237 * @return the timeout value
238 *
239 * @ingroup Popup
240 * @see elm_popup_timeout_set()
241 */
242EAPI double elm_popup_timeout_get(const Evas_Object *obj) EINA_ARG_NONNULL(1);
243
244/**
245 * @brief Sets whether events should be passed to by a click outside.
246 *
247 * @param obj The popup object
248 * @param allow EINA_TRUE Events are passed to lower objects, else not
249 *
250 * Enabling allow event will remove the Blocked event area and events will
251 * pass to the lower layer objects otherwise they are blocked.
252 *
253 * @ingroup Popup
254 * @see elm_popup_allow_events_get()
255 * @note The default value is EINA_FALSE.
256 */
257EAPI void elm_popup_allow_events_set(Evas_Object *obj, Eina_Bool allow);
258
259/**
260 * @brief Returns value indicating whether allow event is enabled or not
261 *
262 * @param obj The popup object
263 * @return EINA_FALSE if Blocked event area is present else EINA_TRUE
264 *
265 * @ingroup Popup
266 * @see elm_popup_allow_events_set()
267 * @note By default the Blocked event area is present
268 */
269EAPI Eina_Bool elm_popup_allow_events_get(const Evas_Object *obj);
diff --git a/libraries/elementary/src/lib/elc_scrolled_entry.c b/libraries/elementary/src/lib/elc_scrolled_entry.c
new file mode 100644
index 0000000..cbba45e
--- /dev/null
+++ b/libraries/elementary/src/lib/elc_scrolled_entry.c
@@ -0,0 +1,193 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3EINA_DEPRECATED EAPI Evas_Object *
4elm_scrolled_entry_add(Evas_Object *parent)
5{
6 Evas_Object *obj;
7 obj = elm_entry_add(parent);
8 elm_entry_scrollable_set(obj, EINA_TRUE);
9 return obj;
10}
11EINA_DEPRECATED EAPI void
12elm_scrolled_entry_icon_set(Evas_Object *obj, Evas_Object *icon)
13{elm_object_part_content_set(obj, "icon", icon);}
14EINA_DEPRECATED EAPI Evas_Object *
15elm_scrolled_entry_icon_get(const Evas_Object *obj)
16{return elm_object_part_content_get(obj, "icon");}
17EINA_DEPRECATED EAPI Evas_Object *
18elm_scrolled_entry_icon_unset(Evas_Object *obj)
19{return elm_object_part_content_unset(obj, "icon");}
20EINA_DEPRECATED EAPI void
21elm_scrolled_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting)
22{elm_entry_icon_visible_set(obj, setting);}
23EINA_DEPRECATED EAPI void
24elm_scrolled_entry_end_set(Evas_Object *obj, Evas_Object *end)
25{elm_object_part_content_set(obj, "end", end);}
26EINA_DEPRECATED EAPI Evas_Object *
27elm_scrolled_entry_end_get(const Evas_Object *obj)
28{return elm_object_part_content_get(obj, "end");}
29EINA_DEPRECATED EAPI Evas_Object *
30elm_scrolled_entry_end_unset(Evas_Object *obj)
31{return elm_object_part_content_unset(obj, "end");}
32EINA_DEPRECATED EAPI void
33elm_scrolled_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting)
34{elm_entry_end_visible_set(obj, setting);}
35EINA_DEPRECATED EAPI void
36elm_scrolled_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line)
37{elm_entry_single_line_set(obj, single_line);}
38EINA_DEPRECATED EAPI Eina_Bool
39elm_scrolled_entry_single_line_get(const Evas_Object *obj)
40{return elm_entry_single_line_get(obj);}
41EINA_DEPRECATED EAPI void
42elm_scrolled_entry_password_set(Evas_Object *obj, Eina_Bool password)
43{elm_entry_password_set(obj, password);}
44EINA_DEPRECATED EAPI Eina_Bool
45elm_scrolled_entry_password_get(const Evas_Object *obj)
46{return elm_entry_password_get(obj);}
47EINA_DEPRECATED EAPI void
48elm_scrolled_entry_entry_set(Evas_Object *obj, const char *entry)
49{elm_object_text_set(obj, entry);}
50EINA_DEPRECATED EAPI void
51elm_scrolled_entry_entry_append(Evas_Object *obj, const char *entry)
52{elm_entry_entry_append(obj, entry);}
53EINA_DEPRECATED EAPI const char *
54elm_scrolled_entry_entry_get(const Evas_Object *obj)
55{return elm_object_text_get(obj);}
56EINA_DEPRECATED EAPI Eina_Bool
57elm_scrolled_entry_is_empty(const Evas_Object *obj)
58{return elm_entry_is_empty(obj);}
59EINA_DEPRECATED EAPI const char *
60elm_scrolled_entry_selection_get(const Evas_Object *obj)
61{return elm_entry_selection_get(obj);}
62EINA_DEPRECATED EAPI void
63elm_scrolled_entry_entry_insert(Evas_Object *obj, const char *entry)
64{elm_entry_entry_insert(obj, entry);}
65EINA_DEPRECATED EAPI void
66elm_scrolled_entry_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
67{elm_entry_line_wrap_set(obj, wrap);}
68EINA_DEPRECATED EAPI void
69elm_scrolled_entry_editable_set(Evas_Object *obj, Eina_Bool editable)
70{elm_entry_editable_set(obj, editable);}
71EINA_DEPRECATED EAPI Eina_Bool
72elm_scrolled_entry_editable_get(const Evas_Object *obj)
73{return elm_entry_editable_get(obj);}
74EINA_DEPRECATED EAPI void
75elm_scrolled_entry_select_none(Evas_Object *obj)
76{elm_entry_select_none(obj);}
77EINA_DEPRECATED EAPI void
78elm_scrolled_entry_select_all(Evas_Object *obj)
79{return elm_entry_select_all(obj);}
80EINA_DEPRECATED EAPI Eina_Bool
81elm_scrolled_entry_cursor_next(Evas_Object *obj)
82{return elm_entry_cursor_next(obj);}
83EINA_DEPRECATED EAPI Eina_Bool
84elm_scrolled_entry_cursor_prev(Evas_Object *obj)
85{return elm_entry_cursor_prev(obj);}
86EINA_DEPRECATED EAPI Eina_Bool
87elm_scrolled_entry_cursor_up(Evas_Object *obj)
88{return elm_entry_cursor_up(obj);}
89EINA_DEPRECATED EAPI Eina_Bool
90elm_scrolled_entry_cursor_down(Evas_Object *obj)
91{return elm_entry_cursor_down(obj);}
92EINA_DEPRECATED EAPI void
93elm_scrolled_entry_cursor_begin_set(Evas_Object *obj)
94{elm_entry_cursor_begin_set(obj);}
95EINA_DEPRECATED EAPI void
96elm_scrolled_entry_cursor_end_set(Evas_Object *obj)
97{elm_entry_cursor_end_set(obj);}
98EINA_DEPRECATED EAPI void
99elm_scrolled_entry_cursor_line_begin_set(Evas_Object *obj)
100{elm_entry_cursor_line_begin_set(obj);}
101EINA_DEPRECATED EAPI void
102elm_scrolled_entry_cursor_line_end_set(Evas_Object *obj)
103{elm_entry_cursor_line_end_set(obj);}
104EINA_DEPRECATED EAPI void
105elm_scrolled_entry_cursor_selection_begin(Evas_Object *obj)
106{elm_entry_cursor_selection_begin(obj);}
107EINA_DEPRECATED EAPI void
108elm_scrolled_entry_cursor_selection_end(Evas_Object *obj)
109{return elm_entry_cursor_selection_end(obj);}
110EINA_DEPRECATED EAPI Eina_Bool
111elm_scrolled_entry_cursor_is_format_get(const Evas_Object *obj)
112{return elm_entry_cursor_is_format_get(obj);}
113EINA_DEPRECATED EAPI Eina_Bool
114elm_scrolled_entry_cursor_is_visible_format_get(const Evas_Object *obj)
115{return elm_entry_cursor_is_visible_format_get(obj);}
116EINA_DEPRECATED EAPI const char *
117elm_scrolled_entry_cursor_content_get(const Evas_Object *obj)
118{return elm_entry_cursor_content_get(obj);}
119EINA_DEPRECATED EAPI void
120elm_scrolled_entry_cursor_pos_set(Evas_Object *obj, int pos)
121{elm_entry_cursor_pos_set(obj, pos);}
122EINA_DEPRECATED EAPI int
123elm_scrolled_entry_cursor_pos_get(const Evas_Object *obj)
124{return elm_entry_cursor_pos_get(obj);}
125EINA_DEPRECATED EAPI void
126elm_scrolled_entry_selection_cut(Evas_Object *obj)
127{elm_entry_selection_cut(obj);}
128EINA_DEPRECATED EAPI void
129elm_scrolled_entry_selection_copy(Evas_Object *obj)
130{elm_entry_selection_copy(obj);}
131EINA_DEPRECATED EAPI void
132elm_scrolled_entry_selection_paste(Evas_Object *obj)
133{elm_entry_selection_paste(obj);}
134EINA_DEPRECATED EAPI void
135elm_scrolled_entry_context_menu_clear(Evas_Object *obj)
136{elm_entry_context_menu_clear(obj);}
137EINA_DEPRECATED EAPI void
138elm_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)
139{elm_entry_context_menu_item_add(obj, label, icon_file, icon_type, func, data);}
140EINA_DEPRECATED EAPI void
141elm_scrolled_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled)
142{elm_entry_context_menu_disabled_set(obj, disabled);}
143EINA_DEPRECATED EAPI Eina_Bool
144elm_scrolled_entry_context_menu_disabled_get(const Evas_Object *obj)
145{return elm_entry_context_menu_disabled_get(obj);}
146EINA_DEPRECATED EAPI void
147elm_scrolled_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v)
148{elm_entry_scrollbar_policy_set(obj, h, v);}
149EINA_DEPRECATED EAPI void
150elm_scrolled_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
151{elm_entry_bounce_set(obj, h_bounce, v_bounce);}
152EINA_DEPRECATED EAPI void
153elm_scrolled_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
154{elm_entry_bounce_get(obj, h_bounce, v_bounce);}
155EINA_DEPRECATED EAPI void
156elm_scrolled_entry_item_provider_append(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
157{elm_entry_item_provider_append(obj, func, data);}
158EINA_DEPRECATED EAPI void
159elm_scrolled_entry_item_provider_prepend(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
160{elm_entry_item_provider_prepend(obj, func, data);}
161EINA_DEPRECATED EAPI void
162elm_scrolled_entry_item_provider_remove(Evas_Object *obj, Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item), void *data)
163{elm_entry_item_provider_remove(obj, func, data);}
164EINA_DEPRECATED EAPI void
165elm_scrolled_entry_text_filter_append(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
166{elm_entry_markup_filter_append(obj, func, data);}
167EINA_DEPRECATED EAPI void
168elm_scrolled_entry_text_filter_prepend(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
169{elm_entry_markup_filter_prepend(obj, func, data);}
170EINA_DEPRECATED EAPI void
171elm_scrolled_entry_text_filter_remove(Evas_Object *obj, void (*func) (void *data, Evas_Object *entry, char **text), void *data)
172{elm_entry_markup_filter_remove(obj, func, data);}
173EINA_DEPRECATED EAPI void
174elm_scrolled_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format)
175{elm_entry_file_set(obj, file, format);}
176EINA_DEPRECATED EAPI void
177elm_scrolled_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format)
178{elm_entry_file_get(obj, file, format);}
179EINA_DEPRECATED EAPI void
180elm_scrolled_entry_file_save(Evas_Object *obj)
181{elm_entry_file_save(obj);}
182EINA_DEPRECATED EAPI void
183elm_scrolled_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave)
184{elm_entry_autosave_set(obj, autosave);}
185EINA_DEPRECATED EAPI Eina_Bool
186elm_scrolled_entry_autosave_get(const Evas_Object *obj)
187{return elm_entry_autosave_get(obj);}
188EINA_DEPRECATED EAPI void
189elm_scrolled_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly)
190{Elm_Cnp_Mode cnp_mode = ELM_CNP_MODE_MARKUP; if (textonly) cnp_mode = ELM_CNP_MODE_NO_IMAGE; elm_entry_cnp_mode_set(obj, cnp_mode);}
191EINA_DEPRECATED EAPI Eina_Bool
192elm_scrolled_entry_cnp_textonly_get(Evas_Object *obj)
193{return elm_entry_cnp_mode_get(obj) != ELM_CNP_MODE_MARKUP;}
diff --git a/libraries/elementary/src/lib/elm_access.c b/libraries/elementary/src/lib/elm_access.c
new file mode 100644
index 0000000..4ea5582
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_access.c
@@ -0,0 +1,536 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Mod_Api Mod_Api;
5
6struct _Mod_Api
7{
8 void (*out_read) (const char *txt);
9 void (*out_read_done) (void);
10 void (*out_cancel) (void);
11 void (*out_done_callback_set) (void (*func) (void *data), const void *data);
12};
13
14static int initted = 0;
15static Mod_Api *mapi = NULL;
16
17static void
18_access_init(void)
19{
20 Elm_Module *m;
21 initted++;
22 if (initted > 1) return;
23 if (!(m = _elm_module_find_as("access/api"))) return;
24 m->api = malloc(sizeof(Mod_Api));
25 if (!m->api) return;
26 m->init_func(m);
27 ((Mod_Api *)(m->api) )->out_read = // called to read out some text
28 _elm_module_symbol_get(m, "out_read");
29 ((Mod_Api *)(m->api) )->out_read_done = // called to set a done marker so when it is reached the done callback is called
30 _elm_module_symbol_get(m, "out_read_done");
31 ((Mod_Api *)(m->api) )->out_cancel = // called to read out some text
32 _elm_module_symbol_get(m, "out_cancel");
33 ((Mod_Api *)(m->api) )->out_done_callback_set = // called when last read done
34 _elm_module_symbol_get(m, "out_done_callback_set");
35 mapi = m->api;
36}
37
38static Elm_Access_Item *
39_access_add_set(Elm_Access_Info *ac, int type)
40{
41 Elm_Access_Item *ai;
42 Eina_List *l;
43
44 if (!ac) return NULL;
45 EINA_LIST_FOREACH(ac->items, l, ai)
46 {
47 if (ai->type == type)
48 {
49 if (!ai->func)
50 {
51 if (ai->data) eina_stringshare_del(ai->data);
52 }
53 ai->func = NULL;
54 ai->data = NULL;
55 return ai;
56 }
57 }
58 ai = calloc(1, sizeof(Elm_Access_Item));
59 ai->type = type;
60 ac->items = eina_list_prepend(ac->items, ai);
61 return ai;
62}
63
64static Eina_Bool
65_access_obj_over_timeout_cb(void *data)
66{
67 Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
68 if (!ac) return EINA_FALSE;
69 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
70 {
71 _elm_access_object_hilight(data);
72 _elm_access_read(ac, ELM_ACCESS_CANCEL, data, NULL);
73 _elm_access_read(ac, ELM_ACCESS_TYPE, data, NULL);
74 _elm_access_read(ac, ELM_ACCESS_INFO, data, NULL);
75 _elm_access_read(ac, ELM_ACCESS_STATE, data, NULL);
76 _elm_access_read(ac, ELM_ACCESS_DONE, data, NULL);
77 }
78 ac->delay_timer = NULL;
79 return EINA_FALSE;
80}
81
82static void
83_access_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
84{
85 Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
86 if (!ac) return;
87
88 if (ac->delay_timer)
89 {
90 ecore_timer_del(ac->delay_timer);
91 ac->delay_timer = NULL;
92 }
93 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
94 ac->delay_timer = ecore_timer_add(0.2, _access_obj_over_timeout_cb, data);
95}
96
97static void
98_access_obj_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
99{
100 Elm_Access_Info *ac = evas_object_data_get(data, "_elm_access");
101 if (!ac) return;
102 _elm_access_object_unhilight(data);
103 if (ac->delay_timer)
104 {
105 ecore_timer_del(ac->delay_timer);
106 ac->delay_timer = NULL;
107 }
108}
109
110static void
111_access_obj_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
112{
113 Elm_Access_Info *ac;
114
115 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_IN,
116 _access_obj_mouse_in_cb, data);
117 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_OUT,
118 _access_obj_mouse_out_cb, data);
119 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
120 _access_obj_del_cb, data);
121 ac = evas_object_data_get(data, "_elm_access");
122 evas_object_data_del(data, "_elm_access");
123 if (ac)
124 {
125 _elm_access_clear(ac);
126 free(ac);
127 }
128}
129
130static void
131_access_read_done(void *data __UNUSED__)
132{
133 printf("read done\n");
134 // FIXME: produce event here
135}
136
137static void
138_access_2nd_click_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
139{
140 Ecore_Timer *t;
141
142 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
143 _access_2nd_click_del_cb, NULL);
144 t = evas_object_data_get(obj, "_elm_2nd_timeout");
145 if (t)
146 {
147 ecore_timer_del(t);
148 evas_object_data_del(obj, "_elm_2nd_timeout");
149 }
150}
151
152static Eina_Bool
153_access_2nd_click_timeout_cb(void *data)
154{
155 evas_object_event_callback_del_full(data, EVAS_CALLBACK_DEL,
156 _access_2nd_click_del_cb, NULL);
157 evas_object_data_del(data, "_elm_2nd_timeout");
158 return EINA_FALSE;
159}
160
161static void
162_access_obj_hilight_del_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
163{
164 _elm_access_object_hilight_disable(e);
165}
166
167static void
168_access_obj_hilight_hide_cb(void *data __UNUSED__, Evas *e, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
169{
170 _elm_access_object_hilight_disable(e);
171}
172
173static void
174_access_obj_hilight_move_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
175{
176 Evas_Coord x, y;
177 Evas_Object *o;
178
179 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
180 if (!o) return;
181 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
182 evas_object_move(o, x, y);
183}
184
185static void
186_access_obj_hilight_resize_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
187{
188 Evas_Coord w, h;
189 Evas_Object *o;
190
191 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
192 if (!o) return;
193 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
194 evas_object_resize(o, w, h);
195}
196
197
198
199//-------------------------------------------------------------------------//
200
201EAPI void
202_elm_access_clear(Elm_Access_Info *ac)
203{
204 Elm_Access_Item *ai;
205
206 if (!ac) return;
207 if (ac->delay_timer)
208 {
209 ecore_timer_del(ac->delay_timer);
210 ac->delay_timer = NULL;
211 }
212 EINA_LIST_FREE(ac->items, ai)
213 {
214 if (!ai->func)
215 {
216 if (ai->data) eina_stringshare_del(ai->data);
217 }
218 free(ai);
219 }
220}
221
222EAPI void
223_elm_access_text_set(Elm_Access_Info *ac, int type, const char *text)
224{
225 Elm_Access_Item *ai = _access_add_set(ac, type);
226 if (!ai) return;
227 ai->data = eina_stringshare_add(text);
228}
229
230EAPI void
231_elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data)
232{
233 Elm_Access_Item *ai = _access_add_set(ac, type);
234 if (!ai) return;
235 ai->func = func;
236 ai->data = data;
237}
238
239EAPI char *
240_elm_access_text_get(const Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
241{
242 Elm_Access_Item *ai;
243 Eina_List *l;
244
245 if (!ac) return NULL;
246 EINA_LIST_FOREACH(ac->items, l, ai)
247 {
248 if (ai->type == type)
249 {
250 if (ai->func) return ai->func((void *)(ai->data), obj, item);
251 else if (ai->data) return strdup(ai->data);
252 return NULL;
253 }
254 }
255 return NULL;
256}
257
258EAPI void
259_elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item)
260{
261 char *txt = _elm_access_text_get(ac, type, obj, item);
262
263 _access_init();
264 if (mapi)
265 {
266 if (mapi->out_done_callback_set)
267 mapi->out_done_callback_set(_access_read_done, NULL);
268 if (type == ELM_ACCESS_DONE)
269 {
270 if (mapi->out_read_done) mapi->out_read_done();
271 }
272 else if (type == ELM_ACCESS_CANCEL)
273 {
274 if (mapi->out_cancel) mapi->out_cancel();
275 }
276 else
277 {
278 if (txt)
279 {
280 if (mapi->out_read) mapi->out_read(txt);
281 if (mapi->out_read) mapi->out_read(".\n");
282 }
283 }
284 }
285 if (txt) free(txt);
286}
287
288EAPI void
289_elm_access_say(const char *txt)
290{
291 _access_init();
292 if (mapi)
293 {
294 if (mapi->out_done_callback_set)
295 mapi->out_done_callback_set(_access_read_done, NULL);
296 if (mapi->out_cancel) mapi->out_cancel();
297 if (txt)
298 {
299 if (mapi->out_read) mapi->out_read(txt);
300 if (mapi->out_read) mapi->out_read(".\n");
301 }
302 if (mapi->out_read_done) mapi->out_read_done();
303 }
304}
305
306EAPI Elm_Access_Info *
307_elm_access_object_get(const Evas_Object *obj)
308{
309 return evas_object_data_get(obj, "_elm_access");
310}
311
312EAPI Elm_Access_Info *
313_elm_access_item_get(const Elm_Widget_Item *it)
314{
315 return it->access;
316}
317
318EAPI void
319_elm_access_object_hilight(Evas_Object *obj)
320{
321 Evas_Object *o;
322 Evas_Coord x, y, w, h;
323
324 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
325 if (!o)
326 {
327 o = edje_object_add(evas_object_evas_get(obj));
328 evas_object_name_set(o, "_elm_access_disp");
329 evas_object_layer_set(o, ELM_OBJECT_LAYER_TOOLTIP);
330 }
331 else
332 {
333 Evas_Object *ptarget = evas_object_data_get(o, "_elm_access_target");
334 if (ptarget)
335 {
336 evas_object_data_del(o, "_elm_access_target");
337 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
338 _access_obj_hilight_del_cb, NULL);
339 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
340 _access_obj_hilight_hide_cb, NULL);
341 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
342 _access_obj_hilight_move_cb, NULL);
343 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
344 _access_obj_hilight_resize_cb, NULL);
345 }
346 }
347 evas_object_data_set(o, "_elm_access_target", obj);
348 _elm_theme_object_set(obj, o, "access", "base", "default");
349 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
350 _access_obj_hilight_del_cb, NULL);
351 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
352 _access_obj_hilight_hide_cb, NULL);
353 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
354 _access_obj_hilight_move_cb, NULL);
355 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
356 _access_obj_hilight_resize_cb, NULL);
357 evas_object_raise(o);
358 evas_object_geometry_get(obj, &x, &y, &w, &h);
359 evas_object_move(o, x, y);
360 evas_object_resize(o, w, h);
361 evas_object_show(o);
362}
363
364EAPI void
365_elm_access_object_unhilight(Evas_Object *obj)
366{
367 Evas_Object *o, *ptarget;
368
369 o = evas_object_name_find(evas_object_evas_get(obj), "_elm_access_disp");
370 if (!o) return;
371 ptarget = evas_object_data_get(o, "_elm_access_target");
372 if (ptarget == obj)
373 {
374 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
375 _access_obj_hilight_del_cb, NULL);
376 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
377 _access_obj_hilight_hide_cb, NULL);
378 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
379 _access_obj_hilight_move_cb, NULL);
380 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
381 _access_obj_hilight_resize_cb, NULL);
382 evas_object_del(o);
383 }
384}
385
386EAPI void
387_elm_access_object_hilight_disable(Evas *e)
388{
389 Evas_Object *o, *ptarget;
390
391 o = evas_object_name_find(e, "_elm_access_disp");
392 if (!o) return;
393 ptarget = evas_object_data_get(o, "_elm_access_target");
394 if (ptarget)
395 {
396 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_DEL,
397 _access_obj_hilight_del_cb, NULL);
398 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_HIDE,
399 _access_obj_hilight_hide_cb, NULL);
400 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_MOVE,
401 _access_obj_hilight_move_cb, NULL);
402 evas_object_event_callback_del_full(ptarget, EVAS_CALLBACK_RESIZE,
403 _access_obj_hilight_resize_cb, NULL);
404 }
405 evas_object_del(o);
406}
407
408EAPI void
409_elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj)
410{
411 Elm_Access_Info *ac;
412
413 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
414 _access_obj_mouse_in_cb, obj);
415 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
416 _access_obj_mouse_out_cb, obj);
417 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
418 _access_obj_del_cb, obj);
419 ac = calloc(1, sizeof(Elm_Access_Info));
420 evas_object_data_set(obj, "_elm_access", ac);
421}
422
423static Eina_Bool
424_access_item_over_timeout_cb(void *data)
425{
426 Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
427 if (!ac) return EINA_FALSE;
428 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
429 {
430 _elm_access_object_hilight(((Elm_Widget_Item *)data)->view);
431 _elm_access_read(ac, ELM_ACCESS_CANCEL, NULL, data);
432 _elm_access_read(ac, ELM_ACCESS_TYPE, NULL, data);
433 _elm_access_read(ac, ELM_ACCESS_INFO, NULL, data);
434 _elm_access_read(ac, ELM_ACCESS_STATE, NULL, data);
435 _elm_access_read(ac, ELM_ACCESS_DONE, NULL, data);
436 }
437 ac->delay_timer = NULL;
438 return EINA_FALSE;
439}
440
441static void
442_access_item_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
443{
444 Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
445 if (!ac) return;
446
447 if (ac->delay_timer)
448 {
449 ecore_timer_del(ac->delay_timer);
450 ac->delay_timer = NULL;
451 }
452 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
453 ac->delay_timer = ecore_timer_add(0.2, _access_item_over_timeout_cb, data);
454}
455
456static void
457_access_item_mouse_out_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
458{
459 Elm_Access_Info *ac = ((Elm_Widget_Item *)data)->access;
460 if (!ac) return;
461
462 _elm_access_object_unhilight(((Elm_Widget_Item *)data)->view);
463 if (ac->delay_timer)
464 {
465 ecore_timer_del(ac->delay_timer);
466 ac->delay_timer = NULL;
467 }
468}
469
470static void _access_item_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
471
472EAPI void
473_elm_access_item_unregister(Elm_Widget_Item *item)
474{
475 Elm_Access_Info *ac;
476
477 ac = item->access;
478 if (ac)
479 {
480 evas_object_event_callback_del_full(ac->hoverobj,
481 EVAS_CALLBACK_MOUSE_IN,
482 _access_item_mouse_in_cb, item);
483 evas_object_event_callback_del_full(ac->hoverobj,
484 EVAS_CALLBACK_MOUSE_OUT,
485 _access_item_mouse_out_cb, item);
486 evas_object_event_callback_del_full(ac->hoverobj,
487 EVAS_CALLBACK_DEL,
488 _access_item_del_cb, item);
489 item->access = NULL;
490 _elm_access_clear(ac);
491 free(ac);
492 }
493}
494
495static void
496_access_item_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
497{
498 _elm_access_item_unregister((Elm_Widget_Item *)data);
499}
500
501EAPI void
502_elm_access_item_register(Elm_Widget_Item *item, Evas_Object *hoverobj)
503{
504 Elm_Access_Info *ac;
505
506 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_IN,
507 _access_item_mouse_in_cb, item);
508 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_MOUSE_OUT,
509 _access_item_mouse_out_cb, item);
510 evas_object_event_callback_add(hoverobj, EVAS_CALLBACK_DEL,
511 _access_item_del_cb, item);
512 ac = calloc(1, sizeof(Elm_Access_Info));
513 ac->hoverobj = hoverobj;
514 item->access = ac;
515}
516
517EAPI Eina_Bool
518_elm_access_2nd_click_timeout(Evas_Object *obj)
519{
520 Ecore_Timer *t;
521
522 t = evas_object_data_get(obj, "_elm_2nd_timeout");
523 if (t)
524 {
525 ecore_timer_del(t);
526 evas_object_data_del(obj, "_elm_2nd_timeout");
527 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
528 _access_2nd_click_del_cb, NULL);
529 return EINA_TRUE;
530 }
531 t = ecore_timer_add(0.3, _access_2nd_click_timeout_cb, obj);
532 evas_object_data_set(obj, "_elm_2nd_timeout", t);
533 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
534 _access_2nd_click_del_cb, NULL);
535 return EINA_FALSE;
536}
diff --git a/libraries/elementary/src/lib/elm_actionslider.c b/libraries/elementary/src/lib/elm_actionslider.c
new file mode 100644
index 0000000..ec3087b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_actionslider.c
@@ -0,0 +1,505 @@
1#include <Elementary.h>
2#include <math.h>
3#include "elm_priv.h"
4
5typedef struct _Widget_Data Widget_Data;
6
7struct _Widget_Data
8{
9 Evas_Object *as; // actionslider
10 Evas_Object *drag_button_base;
11 Elm_Actionslider_Pos magnet_position, enabled_position;
12 const char *text_left, *text_right, *text_center;
13 const char *indicator_label;
14 Ecore_Animator *button_animator;
15 double final_position;
16 Eina_Bool mouse_down : 1;
17};
18
19static const char *widtype = NULL;
20
21static const char SIG_CHANGED[] = "pos_changed";
22static const char SIG_SELECTED[] = "selected";
23
24static const Evas_Smart_Cb_Description _signals[] =
25{
26 {SIG_CHANGED, ""},
27 {SIG_SELECTED, ""},
28 {NULL, NULL}
29};
30
31
32static void
33_del_hook(Evas_Object *obj)
34{
35 Widget_Data *wd = elm_widget_data_get(obj);
36 if (!wd) return;
37 if (wd->drag_button_base)
38 {
39 evas_object_del(wd->drag_button_base);
40 wd->drag_button_base = NULL;
41 }
42 if (wd->text_left) eina_stringshare_del(wd->text_left);
43 if (wd->text_right) eina_stringshare_del(wd->text_right);
44 if (wd->text_center) eina_stringshare_del(wd->text_center);
45 if (wd->indicator_label) eina_stringshare_del(wd->indicator_label);
46 free(wd);
47}
48
49static Elm_Actionslider_Pos
50_get_pos_by_orientation(const Evas_Object *obj, Elm_Actionslider_Pos pos)
51{
52 if (elm_widget_mirrored_get(obj))
53 {
54 switch (pos)
55 {
56 case ELM_ACTIONSLIDER_LEFT:
57 pos = ELM_ACTIONSLIDER_RIGHT;
58 break;
59 case ELM_ACTIONSLIDER_RIGHT:
60 pos = ELM_ACTIONSLIDER_LEFT;
61 break;
62 default:
63 break;
64 }
65 }
66 return pos;
67}
68
69static void
70_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
71{
72 Widget_Data *wd = elm_widget_data_get(obj);
73 double pos;
74
75 if (!wd) return;
76 if (edje_object_mirrored_get(wd->as) == rtl)
77 return;
78
79 edje_object_mirrored_set(wd->as, rtl);
80 if (!elm_widget_mirrored_get(obj))
81 {
82 edje_object_part_text_escaped_set(wd->as, "elm.text.left", wd->text_left);
83 edje_object_part_text_escaped_set(wd->as, "elm.text.right", wd->text_right);
84 }
85 else
86 {
87 edje_object_part_text_escaped_set(wd->as, "elm.text.left", wd->text_right);
88 edje_object_part_text_escaped_set(wd->as, "elm.text.right", wd->text_left);
89 }
90 edje_object_part_drag_value_get(wd->as, "elm.drag_button_base", &pos, NULL);
91 edje_object_part_drag_value_set(wd->as, "elm.drag_button_base", 1.0 - pos, 0.5);
92}
93
94static void
95_sizing_eval(Evas_Object *obj)
96{
97 Widget_Data *wd = elm_widget_data_get(obj);
98 Evas_Coord minw = -1, minh = -1;
99
100 if (!wd) return;
101 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
102 evas_object_size_hint_min_set(wd->drag_button_base, minw, minh);
103 evas_object_size_hint_max_set(wd->drag_button_base, -1, -1);
104
105 minw = -1;
106 minh = -1;
107 elm_coords_finger_size_adjust(3, &minw, 1, &minh);
108 edje_object_size_min_restricted_calc(wd->as, &minw, &minh, minw, minh);
109 evas_object_size_hint_min_set(obj, minw, minh);
110 evas_object_size_hint_max_set(obj, -1, -1);
111}
112
113static void
114_theme_hook(Evas_Object *obj)
115{
116 Widget_Data *wd = elm_widget_data_get(obj);
117 if (!wd) return;
118 _elm_widget_mirrored_reload(obj);
119 if (!edje_object_part_swallow_get(wd->as, "elm.drag_button_base"))
120 edje_object_part_unswallow(wd->as, wd->drag_button_base);
121
122 _elm_theme_object_set(obj, wd->as, "actionslider",
123 "base", elm_widget_style_get(obj));
124 _elm_theme_object_set(obj, wd->drag_button_base, "actionslider",
125 "drag_button", elm_widget_style_get(obj));
126 edje_object_part_swallow(wd->as, "elm.drag_button_base", wd->drag_button_base);
127
128 _mirrored_set(obj, elm_widget_mirrored_get(obj));
129 edje_object_part_text_escaped_set(wd->as, "elm.text.center", wd->text_center);
130 edje_object_part_text_escaped_set(wd->as, "elm.text.indicator", wd->indicator_label);
131 edje_object_message_signal_process(wd->as);
132 _sizing_eval(obj);
133}
134
135static void
136_drag_button_down_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
137{
138 Widget_Data *wd = elm_widget_data_get((Evas_Object *) data);
139 if (!wd) return;
140 wd->mouse_down = EINA_TRUE;
141}
142
143static void
144_drag_button_move_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
145{
146 Evas_Object *obj = (Evas_Object *) data;
147 Widget_Data *wd = elm_widget_data_get(obj);
148 double pos = 0.0;
149 if (!wd) return;
150
151 if (!wd->mouse_down) return;
152 edje_object_part_drag_value_get(wd->as, "elm.drag_button_base", &pos, NULL);
153 if (pos == 0.0)
154 evas_object_smart_callback_call(obj, SIG_CHANGED,
155 (void *) ((!elm_widget_mirrored_get(obj)) ?
156 "left" : "right"));
157 else if (pos == 1.0)
158 evas_object_smart_callback_call(obj, SIG_CHANGED,
159 (void *) ((!elm_widget_mirrored_get(obj)) ?
160 "right" : "left"));
161 else if (pos >= 0.45 && pos <= 0.55)
162 evas_object_smart_callback_call(obj, SIG_CHANGED, (void *)"center");
163}
164
165static Eina_Bool
166_button_animation(void *data)
167{
168 Evas_Object *obj = data;
169 Widget_Data *wd = elm_widget_data_get(obj);
170 double cur_position = 0.0, new_position = 0.0;
171 double move_amount = 0.05;
172 Eina_Bool flag_finish_animation = EINA_FALSE;
173 if (!wd) return ECORE_CALLBACK_CANCEL;
174
175 edje_object_part_drag_value_get(wd->as,
176 "elm.drag_button_base", &cur_position, NULL);
177 {
178 double adjusted_final;
179 adjusted_final = (!elm_widget_mirrored_get(obj)) ?
180 wd->final_position : 1.0 - wd->final_position;
181 if ((adjusted_final == 0.0) ||
182 (adjusted_final == 0.5 && cur_position >= adjusted_final))
183 {
184 new_position = cur_position - move_amount;
185 if (new_position <= adjusted_final)
186 {
187 new_position = adjusted_final;
188 flag_finish_animation = EINA_TRUE;
189 }
190 }
191 else if ((adjusted_final == 1.0) ||
192 (adjusted_final == 0.5 && cur_position < adjusted_final))
193 {
194 new_position = cur_position + move_amount;
195 if (new_position >= adjusted_final)
196 {
197 new_position = adjusted_final;
198 flag_finish_animation = EINA_TRUE;
199 }
200 }
201 edje_object_part_drag_value_set(wd->as,
202 "elm.drag_button_base", new_position, 0.5);
203 }
204
205 if (flag_finish_animation)
206 {
207 if ((!wd->final_position) &&
208 (wd->enabled_position & ELM_ACTIONSLIDER_LEFT))
209 evas_object_smart_callback_call(data, SIG_SELECTED,
210 (void *)wd->text_left);
211 else if ((wd->final_position == 0.5) &&
212 (wd->enabled_position & ELM_ACTIONSLIDER_CENTER))
213 evas_object_smart_callback_call(data, SIG_SELECTED,
214 (void *)wd->text_center);
215 else if ((wd->final_position == 1) &&
216 (wd->enabled_position & ELM_ACTIONSLIDER_RIGHT))
217 evas_object_smart_callback_call(data, SIG_SELECTED,
218 (void *)wd->text_right);
219 wd->button_animator = NULL;
220 return ECORE_CALLBACK_CANCEL;
221 }
222 return ECORE_CALLBACK_RENEW;
223}
224
225static void
226_drag_button_up_cb(void *data, Evas_Object *o __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
227{
228 Evas_Object *obj = (Evas_Object *) data;
229 Widget_Data *wd = elm_widget_data_get(obj);
230 double position = 0.0;
231 if (!wd) return;
232
233 wd->mouse_down = EINA_FALSE;
234
235 edje_object_part_drag_value_get(wd->as, "elm.drag_button_base",
236 &position, NULL);
237
238 if ((wd->enabled_position & ELM_ACTIONSLIDER_LEFT) &&
239 ((!elm_widget_mirrored_get(obj) && position == 0.0) ||
240 (elm_widget_mirrored_get(obj) && position == 1.0)))
241 {
242 wd->final_position = 0;
243 evas_object_smart_callback_call(data, SIG_SELECTED,
244 (void *) wd->text_left);
245 return;
246 }
247 if (position >= 0.45 && position <= 0.55 &&
248 (wd->enabled_position & ELM_ACTIONSLIDER_CENTER))
249 {
250 wd->final_position = 0.5;
251 evas_object_smart_callback_call(data, SIG_SELECTED,
252 (void *)wd->text_center);
253 if (wd->button_animator) ecore_animator_del(wd->button_animator);
254 wd->button_animator = ecore_animator_add(_button_animation, data);
255 return;
256 }
257 if ((wd->enabled_position & ELM_ACTIONSLIDER_RIGHT) &&
258 ((!elm_widget_mirrored_get(obj) && position == 1.0) ||
259 (elm_widget_mirrored_get(obj) && position == 0.0)))
260 {
261 wd->final_position = 1;
262 evas_object_smart_callback_call(data, SIG_SELECTED,
263 (void *) wd->text_right);
264 return;
265 }
266
267 if (wd->magnet_position == ELM_ACTIONSLIDER_NONE) return;
268
269#define _FINAL_POS_BY_ORIENTATION(x) (x)
270#define _POS_BY_ORIENTATION(x) \
271 ((!elm_widget_mirrored_get(obj)) ? \
272 x : 1.0 - x)
273
274 position = _POS_BY_ORIENTATION(position);
275
276 if (position < 0.3)
277 {
278 if (wd->magnet_position & ELM_ACTIONSLIDER_LEFT)
279 wd->final_position = _FINAL_POS_BY_ORIENTATION(0);
280 else if (wd->magnet_position & ELM_ACTIONSLIDER_CENTER)
281 wd->final_position = 0.5;
282 else if (wd->magnet_position & ELM_ACTIONSLIDER_RIGHT)
283 wd->final_position = _FINAL_POS_BY_ORIENTATION(1);
284 }
285 else if ((position >= 0.3) && (position <= 0.7))
286 {
287 if (wd->magnet_position & ELM_ACTIONSLIDER_CENTER)
288 wd->final_position = 0.5;
289 else if (position < 0.5)
290 {
291 if (wd->magnet_position & ELM_ACTIONSLIDER_LEFT)
292 wd->final_position = _FINAL_POS_BY_ORIENTATION(0);
293 else
294 wd->final_position = _FINAL_POS_BY_ORIENTATION(1);
295 }
296 else
297 {
298 if (wd->magnet_position & ELM_ACTIONSLIDER_RIGHT)
299 wd->final_position = _FINAL_POS_BY_ORIENTATION(1);
300 else
301 wd->final_position = _FINAL_POS_BY_ORIENTATION(0);
302 }
303 }
304 else
305 {
306 if (wd->magnet_position & ELM_ACTIONSLIDER_RIGHT)
307 wd->final_position = _FINAL_POS_BY_ORIENTATION(1);
308 else if (wd->magnet_position & ELM_ACTIONSLIDER_CENTER)
309 wd->final_position = 0.5;
310 else
311 wd->final_position = _FINAL_POS_BY_ORIENTATION(0);
312 }
313 if (wd->button_animator) ecore_animator_del(wd->button_animator);
314 wd->button_animator = ecore_animator_add(_button_animation, data);
315
316#undef _FINAL_POS_BY_ORIENTATION
317}
318
319static void
320_elm_actionslider_label_set(Evas_Object *obj, const char *item, const char *label)
321{
322 ELM_CHECK_WIDTYPE(obj, widtype);
323 Widget_Data *wd = elm_widget_data_get(obj);
324 if (!wd) return;
325
326 if (!item || !strcmp(item, "indicator"))
327 {
328 eina_stringshare_replace(&wd->indicator_label, label);
329 edje_object_part_text_escaped_set(wd->as, "elm.text.indicator",
330 wd->indicator_label);
331 }
332 else if (!strcmp(item, "left"))
333 {
334 eina_stringshare_replace(&wd->text_left, label);
335 if (!elm_widget_mirrored_get(obj))
336 edje_object_part_text_escaped_set(wd->as, "elm.text.left", wd->text_left);
337 else
338 edje_object_part_text_escaped_set(wd->as, "elm.text.right", wd->text_left);
339 }
340 else if (!strcmp(item, "center"))
341 {
342 eina_stringshare_replace(&wd->text_center, label);
343 edje_object_part_text_escaped_set(wd->as, "elm.text.center", wd->text_center);
344 }
345 else if (!strcmp(item, "right"))
346 {
347 eina_stringshare_replace(&wd->text_right, label);
348 if (!elm_widget_mirrored_get(obj))
349 edje_object_part_text_escaped_set(wd->as, "elm.text.right", wd->text_right);
350 else
351 edje_object_part_text_escaped_set(wd->as, "elm.text.left", wd->text_right);
352 }
353}
354
355static const char *
356_elm_actionslider_label_get(const Evas_Object *obj, const char *item)
357{
358 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
359 Widget_Data *wd = elm_widget_data_get(obj);
360 if (!wd) return NULL;
361
362 if (!item || !strcmp(item, "indicator"))
363 return wd->indicator_label;
364 else if (!strcmp(item, "left"))
365 return wd->text_left;
366 else if (!strcmp(item, "center"))
367 return wd->text_center;
368 else if (!strcmp(item, "right"))
369 return wd->text_right;
370
371 return NULL;
372}
373
374EAPI Evas_Object *
375elm_actionslider_add(Evas_Object *parent)
376{
377 Evas_Object *obj;
378 Widget_Data *wd;
379 Evas *e;
380
381 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
382
383 ELM_SET_WIDTYPE(widtype, "actionslider");
384 elm_widget_type_set(obj, "actionslider");
385 elm_widget_sub_object_add(parent, obj);
386 elm_widget_data_set(obj, wd);
387 elm_widget_del_hook_set(obj, _del_hook);
388 elm_widget_theme_hook_set(obj, _theme_hook);
389 elm_widget_text_set_hook_set(obj, _elm_actionslider_label_set);
390 elm_widget_text_get_hook_set(obj, _elm_actionslider_label_get);
391
392 wd->mouse_down = EINA_FALSE;
393 wd->enabled_position = ELM_ACTIONSLIDER_ALL;
394
395 wd->as = edje_object_add(e);
396 _elm_theme_object_set(obj, wd->as, "actionslider", "base", "default");
397 elm_widget_resize_object_set(obj, wd->as);
398
399 wd->drag_button_base = evas_object_rectangle_add(e);
400 evas_object_color_set(wd->drag_button_base, 0, 0, 0, 0);
401 edje_object_part_swallow(wd->as, "elm.drag_button_base", wd->drag_button_base);
402
403 edje_object_signal_callback_add(wd->as,
404 "elm.drag_button,mouse,up", "",
405 _drag_button_up_cb, obj);
406 edje_object_signal_callback_add(wd->as,
407 "elm.drag_button,mouse,down", "",
408 _drag_button_down_cb, obj);
409 edje_object_signal_callback_add(wd->as,
410 "elm.drag_button,mouse,move", "",
411 _drag_button_move_cb, obj);
412
413 evas_object_smart_callbacks_descriptions_set(obj, _signals);
414 _mirrored_set(obj, elm_widget_mirrored_get(obj));
415 _sizing_eval(obj);
416 return obj;
417}
418
419EAPI void
420elm_actionslider_indicator_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos)
421{
422 ELM_CHECK_WIDTYPE(obj, widtype);
423 Widget_Data *wd = elm_widget_data_get(obj);
424 double position = 0.0;
425 if (!wd) return;
426 pos = _get_pos_by_orientation(obj, pos);
427 if (pos == ELM_ACTIONSLIDER_CENTER) position = 0.5;
428 else if (pos == ELM_ACTIONSLIDER_RIGHT) position = 1.0;
429 edje_object_part_drag_value_set(wd->as, "elm.drag_button_base", position, 0.5);
430}
431
432EAPI Elm_Actionslider_Pos
433elm_actionslider_indicator_pos_get(const Evas_Object *obj)
434{
435 ELM_CHECK_WIDTYPE(obj, widtype) ELM_ACTIONSLIDER_NONE;
436 Widget_Data *wd = elm_widget_data_get(obj);
437 double position;
438 if (!wd) return ELM_ACTIONSLIDER_NONE;
439
440 edje_object_part_drag_value_get(wd->as, "elm.drag_button_base", &position, NULL);
441 if (position < 0.3)
442 return _get_pos_by_orientation(obj, ELM_ACTIONSLIDER_LEFT);
443 else if (position < 0.7)
444 return ELM_ACTIONSLIDER_CENTER;
445 else
446 return _get_pos_by_orientation(obj, ELM_ACTIONSLIDER_RIGHT);
447}
448
449EAPI void
450elm_actionslider_magnet_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos)
451{
452 ELM_CHECK_WIDTYPE(obj, widtype);
453 Widget_Data *wd = elm_widget_data_get(obj);
454 if (!wd) return;
455 wd->magnet_position = pos;
456}
457
458EAPI Elm_Actionslider_Pos
459elm_actionslider_magnet_pos_get(const Evas_Object *obj)
460{
461 ELM_CHECK_WIDTYPE(obj, widtype) ELM_ACTIONSLIDER_NONE;
462 Widget_Data *wd = elm_widget_data_get(obj);
463 if (!wd) return ELM_ACTIONSLIDER_NONE;
464 return wd->magnet_position;
465}
466
467EAPI void
468elm_actionslider_enabled_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos)
469{
470 ELM_CHECK_WIDTYPE(obj, widtype);
471 Widget_Data *wd = elm_widget_data_get(obj);
472 if (!wd) return;
473 wd->enabled_position = pos;
474}
475
476EAPI Elm_Actionslider_Pos
477elm_actionslider_enabled_pos_get(const Evas_Object *obj)
478{
479 ELM_CHECK_WIDTYPE(obj, widtype) ELM_ACTIONSLIDER_NONE;
480 Widget_Data *wd = elm_widget_data_get(obj);
481 if (!wd) return ELM_ACTIONSLIDER_NONE;
482 return wd->enabled_position;
483}
484
485EAPI const char *
486elm_actionslider_selected_label_get(const Evas_Object *obj)
487{
488 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
489 Widget_Data *wd = elm_widget_data_get(obj);
490 if (!wd) return NULL;
491
492 if ((wd->final_position == 0.0) &&
493 (wd->enabled_position & ELM_ACTIONSLIDER_LEFT))
494 return wd->text_left;
495
496 if ((wd->final_position == 0.5) &&
497 (wd->enabled_position & ELM_ACTIONSLIDER_CENTER))
498 return wd->text_center;
499
500 if ((wd->final_position == 1.0) &&
501 (wd->enabled_position & ELM_ACTIONSLIDER_RIGHT))
502 return wd->text_right;
503
504 return NULL;
505}
diff --git a/libraries/elementary/src/lib/elm_actionslider.h b/libraries/elementary/src/lib/elm_actionslider.h
new file mode 100644
index 0000000..1be91fc
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_actionslider.h
@@ -0,0 +1,139 @@
1/**
2 * @addtogroup Actionslider Actionslider
3 * @ingroup Elementary
4 *
5 * @image html img/widget/actionslider/preview-00.png
6 * @image latex img/widget/actionslider/preview-00.eps
7 *
8 * An actionslider is a switcher for 2 or 3 labels with customizable magnet
9 * properties. The user drags and releases the indicator, to choose a label.
10 *
11 * Labels occupy the following positions.
12 * a. Left
13 * b. Right
14 * c. Center
15 *
16 * Positions can be enabled or disabled.
17 *
18 * Magnets can be set on the above positions.
19 *
20 * When the indicator is released, it will move to its nearest "enabled and magnetized" position.
21 *
22 * @note By default all positions are set as enabled.
23 *
24 * Signals that you can add callbacks for are:
25 *
26 * "selected" - when user selects an enabled position (the label is passed as
27 * event info)".
28 * "pos_changed" - when the indicator reaches any of the positions("left",
29 * "right" or "center").
30 *
31 * Default text parts of the actionslider widget that you can use for are:
32 * @li "indicator" - An indicator label of the actionslider
33 * @li "left" - A left label of the actionslider
34 * @li "right" - A right label of the actionslider
35 * @li "center" - A center label of the actionslider
36 *
37 * Supported elm_object common APIs.
38 * @li @ref elm_object_part_text_set
39 * @li @ref elm_object_part_text_get
40 *
41 * See an example of actionslider usage @ref actionslider_example_page "here"
42 * @{
43 */
44typedef enum
45{
46 ELM_ACTIONSLIDER_NONE = 0,
47 ELM_ACTIONSLIDER_LEFT = 1 << 0,
48 ELM_ACTIONSLIDER_CENTER = 1 << 1,
49 ELM_ACTIONSLIDER_RIGHT = 1 << 2,
50 ELM_ACTIONSLIDER_ALL = (1 << 3) - 1
51} Elm_Actionslider_Pos;
52
53/**
54 * Add a new actionslider to the parent.
55 *
56 * @param parent The parent object
57 * @return The new actionslider object or NULL if it cannot be created
58 *
59 * @ingroup Actionslider
60 */
61EAPI Evas_Object *elm_actionslider_add(Evas_Object *parent);
62
63/**
64 * Get actionslider selected label.
65 *
66 * @param obj The actionslider object
67 * @return The selected label
68 *
69 * @ingroup Actionslider
70 */
71EAPI const char *elm_actionslider_selected_label_get(const Evas_Object *obj);
72
73/**
74 * Set actionslider indicator position.
75 *
76 * @param obj The actionslider object.
77 * @param pos The position of the indicator.
78 *
79 * @ingroup Actionslider
80 */
81EAPI void elm_actionslider_indicator_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos);
82
83/**
84 * Get actionslider indicator position.
85 *
86 * @param obj The actionslider object.
87 * @return The position of the indicator.
88 *
89 * @ingroup Actionslider
90 */
91EAPI Elm_Actionslider_Pos elm_actionslider_indicator_pos_get(const Evas_Object *obj);
92
93/**
94 * Set actionslider magnet position. To make multiple positions magnets @c or
95 * them together(e.g.: ELM_ACTIONSLIDER_LEFT | ELM_ACTIONSLIDER_RIGHT)
96 *
97 * @param obj The actionslider object.
98 * @param pos Bit mask indicating the magnet positions.
99 *
100 * @ingroup Actionslider
101 */
102EAPI void elm_actionslider_magnet_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos);
103
104/**
105 * Get actionslider magnet position.
106 *
107 * @param obj The actionslider object.
108 * @return The positions with magnet property.
109 *
110 * @ingroup Actionslider
111 */
112EAPI Elm_Actionslider_Pos elm_actionslider_magnet_pos_get(const Evas_Object *obj);
113
114/**
115 * Set actionslider enabled position. To set multiple positions as enabled @c or
116 * them together(e.g.: ELM_ACTIONSLIDER_LEFT | ELM_ACTIONSLIDER_RIGHT).
117 *
118 * @note All the positions are enabled by default.
119 *
120 * @param obj The actionslider object.
121 * @param pos Bit mask indicating the enabled positions.
122 *
123 * @ingroup Actionslider
124 */
125EAPI void elm_actionslider_enabled_pos_set(Evas_Object *obj, Elm_Actionslider_Pos pos);
126
127/**
128 * Get actionslider enabled position.
129 *
130 * @param obj The actionslider object.
131 * @return The enabled positions.
132 *
133 * @ingroup Actionslider
134 */
135EAPI Elm_Actionslider_Pos elm_actionslider_enabled_pos_get(const Evas_Object *obj);
136
137/**
138 * @}
139 */
diff --git a/libraries/elementary/src/lib/elm_app.h b/libraries/elementary/src/lib/elm_app.h
new file mode 100644
index 0000000..86dba27
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_app.h
@@ -0,0 +1,193 @@
1/**
2 * Provide information in order to make Elementary determine the @b
3 * run time location of the software in question, so other data files
4 * such as images, sound files, executable utilities, libraries,
5 * modules and locale files can be found.
6 *
7 * @param mainfunc This is your application's main function name,
8 * whose binary's location is to be found. Providing @c NULL
9 * will make Elementary not to use it
10 * @param dom This will be used as the application's "domain", in the
11 * form of a prefix to any environment variables that may
12 * override prefix detection and the directory name, inside the
13 * standard share or data directories, where the software's
14 * data files will be looked for.
15 * @param checkfile This is an (optional) magic file's path to check
16 * for existence (and it must be located in the data directory,
17 * under the share directory provided above). Its presence will
18 * help determine the prefix found was correct. Pass @c NULL if
19 * the check is not to be done.
20 *
21 * This function allows one to re-locate the application somewhere
22 * else after compilation, if the developer wishes for easier
23 * distribution of pre-compiled binaries.
24 *
25 * The prefix system is designed to locate where the given software is
26 * installed (under a common path prefix) at run time and then report
27 * specific locations of this prefix and common directories inside
28 * this prefix like the binary, library, data and locale directories,
29 * through the @c elm_app_*_get() family of functions.
30 *
31 * Call elm_app_info_set() early on before you change working
32 * directory or anything about @c argv[0], so it gets accurate
33 * information.
34 *
35 * It will then try and trace back which file @p mainfunc comes from,
36 * if provided, to determine the application's prefix directory.
37 *
38 * The @p dom parameter provides a string prefix to prepend before
39 * environment variables, allowing a fallback to @b specific
40 * environment variables to locate the software. You would most
41 * probably provide a lowercase string there, because it will also
42 * serve as directory domain, explained next. For environment
43 * variables purposes, this string is made uppercase. For example if
44 * @c "myapp" is provided as the prefix, then the program would expect
45 * @c "MYAPP_PREFIX" as a master environment variable to specify the
46 * exact install prefix for the software, or more specific environment
47 * variables like @c "MYAPP_BIN_DIR", @c "MYAPP_LIB_DIR", @c
48 * "MYAPP_DATA_DIR" and @c "MYAPP_LOCALE_DIR", which could be set by
49 * the user or scripts before launching. If not provided (@c NULL),
50 * environment variables will not be used to override compiled-in
51 * defaults or auto detections.
52 *
53 * The @p dom string also provides a subdirectory inside the system
54 * shared data directory for data files. For example, if the system
55 * directory is @c /usr/local/share, then this directory name is
56 * appended, creating @c /usr/local/share/myapp, if it @p was @c
57 * "myapp". It is expected that the application installs data files in
58 * this directory.
59 *
60 * The @p checkfile is a file name or path of something inside the
61 * share or data directory to be used to test that the prefix
62 * detection worked. For example, your app will install a wallpaper
63 * image as @c /usr/local/share/myapp/images/wallpaper.jpg and so to
64 * check that this worked, provide @c "images/wallpaper.jpg" as the @p
65 * checkfile string.
66 *
67 * @see elm_app_compile_bin_dir_set()
68 * @see elm_app_compile_lib_dir_set()
69 * @see elm_app_compile_data_dir_set()
70 * @see elm_app_compile_locale_set()
71 * @see elm_app_prefix_dir_get()
72 * @see elm_app_bin_dir_get()
73 * @see elm_app_lib_dir_get()
74 * @see elm_app_data_dir_get()
75 * @see elm_app_locale_dir_get()
76 */
77EAPI void elm_app_info_set(void *mainfunc, const char *dom, const char *checkfile);
78
79/**
80 * Provide information on the @b fallback application's binaries
81 * directory, in scenarios where they get overridden by
82 * elm_app_info_set().
83 *
84 * @param dir The path to the default binaries directory (compile time
85 * one)
86 *
87 * @note Elementary will as well use this path to determine actual
88 * names of binaries' directory paths, maybe changing it to be @c
89 * something/local/bin instead of @c something/bin, only, for
90 * example.
91 *
92 * @warning You should call this function @b before
93 * elm_app_info_set().
94 */
95EAPI void elm_app_compile_bin_dir_set(const char *dir);
96
97/**
98 * Provide information on the @b fallback application's libraries
99 * directory, on scenarios where they get overridden by
100 * elm_app_info_set().
101 *
102 * @param dir The path to the default libraries directory (compile
103 * time one)
104 *
105 * @note Elementary will as well use this path to determine actual
106 * names of libraries' directory paths, maybe changing it to be @c
107 * something/lib32 or @c something/lib64 instead of @c something/lib,
108 * only, for example.
109 *
110 * @warning You should call this function @b before
111 * elm_app_info_set().
112 */
113EAPI void elm_app_compile_lib_dir_set(const char *dir);
114
115/**
116 * Provide information on the @b fallback application's data
117 * directory, on scenarios where they get overridden by
118 * elm_app_info_set().
119 *
120 * @param dir The path to the default data directory (compile time
121 * one)
122 *
123 * @note Elementary will as well use this path to determine actual
124 * names of data directory paths, maybe changing it to be @c
125 * something/local/share instead of @c something/share, only, for
126 * example.
127 *
128 * @warning You should call this function @b before
129 * elm_app_info_set().
130 */
131EAPI void elm_app_compile_data_dir_set(const char *dir);
132
133/**
134 * Provide information on the @b fallback application's locale
135 * directory, on scenarios where they get overridden by
136 * elm_app_info_set().
137 *
138 * @param dir The path to the default locale directory (compile time
139 * one)
140 *
141 * @warning You should call this function @b before
142 * elm_app_info_set().
143 */
144EAPI void elm_app_compile_locale_set(const char *dir);
145
146/**
147 * Retrieve the application's run time prefix directory, as set by
148 * elm_app_info_set() and the way (environment) the application was
149 * run from.
150 *
151 * @return The directory prefix the application is actually using.
152 */
153EAPI const char *elm_app_prefix_dir_get(void);
154
155/**
156 * Retrieve the application's run time binaries prefix directory, as
157 * set by elm_app_info_set() and the way (environment) the application
158 * was run from.
159 *
160 * @return The binaries directory prefix the application is actually
161 * using.
162 */
163EAPI const char *elm_app_bin_dir_get(void);
164
165/**
166 * Retrieve the application's run time libraries prefix directory, as
167 * set by elm_app_info_set() and the way (environment) the application
168 * was run from.
169 *
170 * @return The libraries directory prefix the application is actually
171 * using.
172 */
173EAPI const char *elm_app_lib_dir_get(void);
174
175/**
176 * Retrieve the application's run time data prefix directory, as
177 * set by elm_app_info_set() and the way (environment) the application
178 * was run from.
179 *
180 * @return The data directory prefix the application is actually
181 * using.
182 */
183EAPI const char *elm_app_data_dir_get(void);
184
185/**
186 * Retrieve the application's run time locale prefix directory, as
187 * set by elm_app_info_set() and the way (environment) the application
188 * was run from.
189 *
190 * @return The locale directory prefix the application is actually
191 * using.
192 */
193EAPI const char *elm_app_locale_dir_get(void);
diff --git a/libraries/elementary/src/lib/elm_authors.h b/libraries/elementary/src/lib/elm_authors.h
new file mode 100644
index 0000000..694c797
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_authors.h
@@ -0,0 +1,61 @@
1/**
2 * @page authors Authors
3 * @author Carsten Haitzler <raster@@rasterman.com>
4 * @author Gustavo Sverzut Barbieri <barbieri@@profusion.mobi>
5 * @author Cedric Bail <cedric.bail@@free.fr>
6 * @author Vincent Torri <vtorri@@univ-evry.fr>
7 * @author Daniel Kolesa <quaker66@@gmail.com>
8 * @author Jaime Thomas <avi.thomas@@gmail.com>
9 * @author Swisscom - http://www.swisscom.ch/
10 * @author Christopher Michael <devilhorns@@comcast.net>
11 * @author Marco Trevisan (Treviño) <mail@@3v1n0.net>
12 * @author Michael Bouchaud <michael.bouchaud@@gmail.com>
13 * @author Jonathan Atton (Watchwolf) <jonathan.atton@@gmail.com>
14 * @author Brian Wang <brian.wang.0721@@gmail.com>
15 * @author Mike Blumenkrantz (discomfitor/zmike) <michael.blumenkrantz@@gmail.com>
16 * @author Samsung Electronics tbd
17 * @author Samsung SAIT tbd
18 * @author Brett Nash <nash@@nash.id.au>
19 * @author Bruno Dilly <bdilly@@profusion.mobi>
20 * @author Rafael Fonseca <rfonseca@@profusion.mobi>
21 * @author Chuneon Park <hermet@@hermet.pe.kr>
22 * @author Woohyun Jung <wh0705.jung@@samsung.com>
23 * @author Jaehwan Kim <jae.hwan.kim@@samsung.com>
24 * @author Wonguk Jeong <wonguk.jeong@@samsung.com>
25 * @author Leandro A. F. Pereira <leandro@@profusion.mobi>
26 * @author Helen Fornazier <helen.fornazier@@profusion.mobi>
27 * @author Gustavo Lima Chaves <glima@@profusion.mobi>
28 * @author Fabiano Fidêncio <fidencio@@profusion.mobi>
29 * @author Tiago Falcão <tiago@@profusion.mobi>
30 * @author Otavio Pontes <otavio@@profusion.mobi>
31 * @author Viktor Kojouharov <vkojouharov@@gmail.com>
32 * @author Daniel Juyung Seo (SeoZ) <juyung.seo@@samsung.com> <seojuyung2@@gmail.com>
33 * @author Sangho Park <sangho.g.park@@samsung.com> <gouache95@@gmail.com>
34 * @author Rajeev Ranjan (Rajeev) <rajeev.r@@samsung.com> <rajeev.jnnce@@gmail.com>
35 * @author Seunggyun Kim <sgyun.kim@@samsung.com> <tmdrbs@@gmail.com>
36 * @author Sohyun Kim <anna1014.kim@@samsung.com> <sohyun.anna@@gmail.com>
37 * @author Jihoon Kim <jihoon48.kim@@samsung.com>
38 * @author Jeonghyun Yun (arosis) <jh0506.yun@@samsung.com>
39 * @author Tom Hacohen <tom@@stosb.com>
40 * @author Aharon Hillel <a.hillel@@partner.samsung.com>
41 * @author Jonathan Atton (Watchwolf) <jonathan.atton@@gmail.com>
42 * @author Shinwoo Kim <kimcinoo@@gmail.com>
43 * @author Govindaraju SM <govi.sm@@samsung.com> <govism@@gmail.com>
44 * @author Prince Kumar Dubey <prince.dubey@@samsung.com> <prince.dubey@@gmail.com>
45 * @author Sung W. Park <sungwoo@@gmail.com>
46 * @author Thierry el Borgi <thierry@@substantiel.fr>
47 * @author Shilpa Singh <shilpa.singh@@samsung.com> <shilpasingh.o@@gmail.com>
48 * @author Chanwook Jung <joey.jung@@samsung.com>
49 * @author Hyoyoung Chang <hyoyoung.chang@@samsung.com>
50 * @author Guillaume "Kuri" Friloux <guillaume.friloux@@asp64.com>
51 * @author Kim Yunhan <spbear@@gmail.com>
52 * @author Bluezery <ohpowel@@gmail.com>
53 * @author Nicolas Aguirre <aguirre.nicolas@@gmail.com>
54 * @author Sanjeev BA <iamsanjeev@@gmail.com>
55 * @author Hyunsil Park <hyunsil.park@samsung.com>
56 * @author Goun Lee <gouni.lee@samsung.com>
57 * @author Mikael Sans <sans.mikael@gmail.com>
58 *
59 * Please contact <enlightenment-devel@lists.sourceforge.net> to get in
60 * contact with the developers and maintainers.
61 */
diff --git a/libraries/elementary/src/lib/elm_bg.c b/libraries/elementary/src/lib/elm_bg.c
new file mode 100644
index 0000000..df29d5b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_bg.c
@@ -0,0 +1,324 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *base, *rect, *img, *overlay;
9 const char *file, *group;
10 Elm_Bg_Option option;
11 struct
12 {
13 Evas_Coord w, h;
14 } load_opts;
15};
16
17static const char *widtype = NULL;
18
19static void _del_hook(Evas_Object *obj);
20static void _theme_hook(Evas_Object *obj);
21static void _custom_resize(void *data, Evas *a, Evas_Object *obj, void *event_info);
22static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
23static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
24static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
25
26static void
27_del_hook(Evas_Object *obj)
28{
29 Widget_Data *wd = elm_widget_data_get(obj);
30 free(wd);
31}
32
33static void
34_theme_hook(Evas_Object *obj)
35{
36 Widget_Data *wd = elm_widget_data_get(obj);
37 Evas_Coord w, h;
38
39 _elm_theme_object_set(obj, wd->base, "bg", "base",
40 elm_widget_style_get(obj));
41
42 if (wd->rect)
43 edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
44 if (wd->img)
45 edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
46 if (wd->overlay)
47 edje_object_part_swallow(wd->base, "elm.swallow.content", wd->overlay);
48
49 // FIXME: if i don't do this, bg doesnt calc correctly. why?
50 evas_object_geometry_get(wd->base, NULL, NULL, &w, &h);
51 evas_object_resize(wd->base, w, h);
52}
53
54static void
55_custom_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
56{
57 Widget_Data *wd = data;
58 Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
59 Evas_Coord iw = 0, ih = 0, mw = -1, mh = -1;
60 Evas_Coord fx = 0, fy = 0, fw = 0, fh = 0;
61 Evas_Coord nx = 0, ny = 0, nw = 0, nh = 0;
62 const char *p;
63
64 if ((!wd->img) || (!wd->file)) return;
65 if (((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))) return;
66
67 /* grab image size */
68 evas_object_image_size_get(wd->img, &iw, &ih);
69 if ((iw < 1) || (ih < 1)) return;
70
71 /* grab base object dimensions */
72 evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
73
74 /* set some defaults */
75 nx = bx;
76 ny = by;
77 nw = bw;
78 nh = bh;
79
80 switch (wd->option)
81 {
82 case ELM_BG_OPTION_CENTER:
83 fw = nw = iw;
84 fh = nh = ih;
85 nx = ((bw - fw) / 2);
86 ny = ((bh - fh) / 2);
87 mw = iw;
88 mh = ih;
89 break;
90 case ELM_BG_OPTION_SCALE:
91 fw = bw;
92 fh = ((ih * fw) / iw);
93 if (fh < bh)
94 {
95 fh = bh;
96 fw = ((iw * fh) / ih);
97 }
98 fx = ((bw - fw) / 2);
99 fy = ((bh - fh) / 2);
100 break;
101 case ELM_BG_OPTION_TILE:
102 fw = iw;
103 fh = ih;
104 break;
105 case ELM_BG_OPTION_STRETCH:
106 default:
107 fw = bw;
108 fh = bh;
109 break;
110 }
111
112 evas_object_move(wd->img, nx, ny);
113 evas_object_resize(wd->img, nw, nh);
114 evas_object_image_fill_set(wd->img, fx, fy, fw, fh);
115
116 evas_object_size_hint_min_set(wd->img, mw, mh);
117 evas_object_size_hint_max_set(wd->img, mw, mh);
118}
119
120static void
121_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
122{
123 ELM_CHECK_WIDTYPE(obj, widtype);
124 Widget_Data *wd;
125 if (part && strcmp(part, "overlay")) return;
126 wd = elm_widget_data_get(obj);
127 if (!wd) return;
128
129 if (content == wd->overlay) return;
130 if (wd->overlay) evas_object_del(wd->overlay);
131
132 wd->overlay = content;
133 if (content)
134 {
135 edje_object_part_swallow(wd->base, "elm.swallow.content", content);
136 elm_widget_sub_object_add(obj, content);
137 }
138
139 _custom_resize(wd, NULL, NULL, NULL);
140}
141
142static Evas_Object *
143_content_get_hook(const Evas_Object *obj, const char *part)
144{
145 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
146 Widget_Data *wd;
147 if (part && strcmp(part, "overlay")) return NULL;
148 wd = elm_widget_data_get(obj);
149 if (!wd) return NULL;
150 return wd->overlay;
151}
152
153static Evas_Object *
154_content_unset_hook(Evas_Object *obj, const char *part)
155{
156 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
157 Widget_Data *wd;
158 Evas_Object *overlay;
159 if (part && strcmp(part, "overlay")) return NULL;
160 wd = elm_widget_data_get(obj);
161 if (!wd || !wd->overlay) return NULL;
162 overlay = wd->overlay;
163 elm_widget_sub_object_del(obj, wd->overlay);
164 edje_object_part_unswallow(wd->base, wd->overlay);
165 wd->overlay = NULL;
166 _custom_resize(wd, NULL, NULL, NULL);
167 return overlay;
168}
169
170EAPI Evas_Object *
171elm_bg_add(Evas_Object *parent)
172{
173 Evas_Object *obj;
174 Evas *e;
175 Widget_Data *wd;
176
177 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
178
179 ELM_SET_WIDTYPE(widtype, "bg");
180 elm_widget_type_set(obj, "bg");
181 elm_widget_sub_object_add(parent, obj);
182 elm_widget_data_set(obj, wd);
183 elm_widget_del_hook_set(obj, _del_hook);
184 elm_widget_theme_hook_set(obj, _theme_hook);
185 elm_widget_content_set_hook_set(obj, _content_set_hook);
186 elm_widget_content_get_hook_set(obj, _content_get_hook);
187 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
188
189 elm_widget_can_focus_set(obj, EINA_FALSE);
190
191 wd->base = edje_object_add(e);
192 _elm_theme_object_set(obj, wd->base, "bg", "base", "default");
193 elm_widget_resize_object_set(obj, wd->base);
194
195 evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
196 _custom_resize, wd);
197
198 wd->option = ELM_BG_OPTION_SCALE;
199 return obj;
200}
201
202EAPI Eina_Bool
203elm_bg_file_set(Evas_Object *obj, const char *file, const char *group)
204{
205 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
206 Widget_Data *wd = elm_widget_data_get(obj);
207 const char *p;
208
209 if (wd->img)
210 {
211 evas_object_del(wd->img);
212 wd->img = NULL;
213 }
214 if (!file)
215 {
216 eina_stringshare_del(wd->file);
217 wd->file = NULL;
218 eina_stringshare_del(wd->group);
219 wd->group = NULL;
220 return EINA_TRUE;
221 }
222 eina_stringshare_replace(&wd->file, file);
223 eina_stringshare_replace(&wd->group, group);
224 if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
225 {
226 wd->img = edje_object_add(evas_object_evas_get(wd->base));
227 edje_object_file_set(wd->img, file, group);
228 }
229 else
230 {
231 wd->img = evas_object_image_add(evas_object_evas_get(wd->base));
232 if ((wd->load_opts.w > 0) && (wd->load_opts.h > 0))
233 evas_object_image_load_size_set(wd->img, wd->load_opts.w, wd->load_opts.h);
234 evas_object_image_file_set(wd->img, file, group);
235 }
236 evas_object_repeat_events_set(wd->img, EINA_TRUE);
237 edje_object_part_swallow(wd->base, "elm.swallow.background", wd->img);
238 elm_widget_sub_object_add(obj, wd->img);
239 _custom_resize(wd, NULL, NULL, NULL);
240
241 return EINA_TRUE;
242}
243
244EAPI void
245elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group)
246{
247 ELM_CHECK_WIDTYPE(obj, widtype);
248 Widget_Data *wd = elm_widget_data_get(obj);
249 if (file) *file = wd->file;
250 if (group) *group = wd->group;
251
252 return;
253}
254
255EAPI void
256elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option)
257{
258 ELM_CHECK_WIDTYPE(obj, widtype);
259 Widget_Data *wd;
260
261 wd = elm_widget_data_get(obj);
262 wd->option = option;
263 _custom_resize(wd, NULL, NULL, NULL);
264
265 return;
266}
267
268EAPI Elm_Bg_Option
269elm_bg_option_get(const Evas_Object *obj)
270{
271 ELM_CHECK_WIDTYPE(obj, widtype) ELM_BG_OPTION_LAST;
272 Widget_Data *wd;
273
274 wd = elm_widget_data_get(obj);
275 return wd->option;
276}
277
278EAPI void
279elm_bg_color_set(Evas_Object *obj, int r, int g, int b)
280{
281 ELM_CHECK_WIDTYPE(obj, widtype);
282 Widget_Data *wd;
283
284 wd = elm_widget_data_get(obj);
285 if (!wd->rect)
286 {
287 wd->rect = evas_object_rectangle_add(evas_object_evas_get(wd->base));
288 edje_object_part_swallow(wd->base, "elm.swallow.rectangle", wd->rect);
289 elm_widget_sub_object_add(obj, wd->rect);
290 _custom_resize(wd, NULL, NULL, NULL);
291 }
292 evas_object_color_set(wd->rect, r, g, b, 255);
293
294 return;
295}
296
297EAPI void
298elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b)
299{
300 ELM_CHECK_WIDTYPE(obj, widtype);
301 Widget_Data *wd;
302
303 wd = elm_widget_data_get(obj);
304 evas_object_color_get(wd->rect, r, g, b, NULL);
305
306 return;
307}
308
309EAPI void
310elm_bg_load_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
311{
312 ELM_CHECK_WIDTYPE(obj, widtype);
313 Widget_Data *wd = elm_widget_data_get(obj);
314 const char *p;
315 if (!wd) return;
316 wd->load_opts.w = w;
317 wd->load_opts.h = h;
318 if (!wd->img) return;
319 if (!(((p = strrchr(wd->file, '.'))) && (!strcasecmp(p, ".edj"))))
320 evas_object_image_load_size_set(wd->img, w, h);
321
322 return;
323}
324
diff --git a/libraries/elementary/src/lib/elm_bg.h b/libraries/elementary/src/lib/elm_bg.h
new file mode 100644
index 0000000..6ba62b1
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_bg.h
@@ -0,0 +1,199 @@
1/**
2 * @defgroup Bg Bg
3 * @ingroup Elementary
4 *
5 * @image html img/widget/bg/preview-00.png
6 * @image latex img/widget/bg/preview-00.eps
7 *
8 * @brief Background object, used for setting a solid color, image or
9 * Edje group as a background to a window or any container object.
10 *
11 * The bg (background) widget is used for setting (solid) background
12 * decorations to a window (unless it has transparency enabled) or to
13 * any container object. It works just like an image, but has some
14 * properties useful to a background, like setting it to tiled,
15 * centered, scaled or stretched.
16 *
17 * Default content parts of the bg widget that you can use for are:
18 * @li "overlay" - overlay of the bg
19 *
20 * Supported elm_object common APIs.
21 * @li @ref elm_object_part_content_set
22 * @li @ref elm_object_part_content_get
23 * @li @ref elm_object_part_content_unset
24 *
25 * Here is some sample code using it:
26 * @li @ref bg_01_example_page
27 * @li @ref bg_02_example_page
28 * @li @ref bg_03_example_page
29 */
30
31/**
32 * Identifiers on how a background widget is to display its image --
33 * if it was set to use an image file.
34 *
35 * @see elm_bg_option_set()
36 * @see elm_bg_option_get()
37 *
38 * @ingroup Bg
39 */
40typedef enum
41{
42 ELM_BG_OPTION_CENTER, /**< center the background image */
43 ELM_BG_OPTION_SCALE, /**< scale the background image, retaining aspect ratio */
44 ELM_BG_OPTION_STRETCH, /**< stretch the background image to fill the widget's area */
45 ELM_BG_OPTION_TILE, /**< tile background image at its original size */
46 ELM_BG_OPTION_LAST /**< sentinel value, also used to indicate errors */
47} Elm_Bg_Option;
48
49/**
50 * Add a new background to the parent
51 *
52 * @param parent The parent object
53 * @return The new object or NULL if it cannot be created
54 *
55 * @ingroup Bg
56 */
57EAPI Evas_Object *elm_bg_add(Evas_Object *parent);
58
59/**
60 * Set the file (image or edje collection) to give life for the
61 * background
62 *
63 * @param obj The background object handle
64 * @param file The file path
65 * @param group Optional key (group in Edje) within the file
66 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
67 *
68 * This sets the image file used in the background object. If the
69 * image comes from an Edje group, it will be stretched to completely
70 * fill the background object. If it comes from a traditional image file, it
71 * will by default be centered in this widget's are (thus retaining
72 * its aspect), what could lead to some parts being not visible. You
73 * may change the mode of exhibition for a real image file with
74 * elm_bg_option_set().
75 *
76 * @note Once the image of @p obj is set, a previously set one will be
77 * deleted, even if @p file is NULL.
78 *
79 * @note This will only affect the contents of one of the background's
80 * swallow spots, namely @c "elm.swallow.background". If you want to
81 * achieve the @c Layout's file setting behavior, you'll have to call
82 * that method on this object.
83 *
84 * @ingroup Bg
85 */
86EAPI Eina_Bool elm_bg_file_set(Evas_Object *obj, const char *file, const char *group);
87
88/**
89 * Get the file (image or edje collection) set on a given background
90 * widget
91 *
92 * @param obj The background object handle
93 * @param file Where to store the requested file's path
94 * @param group Where to store the optional key within @a file, @b if
95 * it's an Edje file
96 *
97 * @note Use @c NULL pointers on the file components you're not
98 * interested in: they'll be ignored by the function.
99 *
100 * @ingroup Bg
101 */
102EAPI void elm_bg_file_get(const Evas_Object *obj, const char **file, const char **group);
103
104/**
105 * Set the mode of display for a given background widget's image
106 *
107 * @param obj The background object handle
108 * @param option The desired background option (see #Elm_Bg_Option)
109 *
110 * This sets how the background widget will display its image. This
111 * will only work if the elm_bg_file_set() was previously called with
112 * an image file on @a obj. The image can be display tiled, scaled,
113 * centered or stretched.
114 *
115 * @see elm_bg_option_get()
116 *
117 * @ingroup Bg
118 */
119EAPI void elm_bg_option_set(Evas_Object *obj, Elm_Bg_Option option);
120
121/**
122 * Get the mode of display for a given background widget's image
123 *
124 * @param obj The background object handle
125 * @return The image displaying mode in use for @a obj or
126 * #ELM_BG_OPTION_LAST, on errors.
127 *
128 * @see elm_bg_option_set() for more details
129 *
130 * @ingroup Bg
131 */
132EAPI Elm_Bg_Option elm_bg_option_get(const Evas_Object *obj);
133
134/**
135 * Set the color on a given background widget
136 *
137 * @param obj The background object handle
138 * @param r The red color component's value
139 * @param g The green color component's value
140 * @param b The blue color component's value
141 *
142 * This sets the color used for the background rectangle, in RGB
143 * format. Each color component's range is from 0 to 255.
144 *
145 * @note You probably only want to use this function if you haven't
146 * previously called elm_bg_file_set(), so that you just want a solid
147 * color background.
148 *
149 * @see elm_bg_color_get()
150 *
151 * @ingroup Bg
152 */
153EAPI void elm_bg_color_set(Evas_Object *obj, int r, int g, int b);
154
155/**
156 * Get the color set on a given background widget
157 *
158 * @param obj The background object handle
159 * @param r Where to store the red color component's value
160 * @param g Where to store the green color component's value
161 * @param b Where to store the blue color component's value
162 *
163 * @note Use @c NULL pointers on the file components you're not
164 * interested in: they'll be ignored by the function.
165 *
166 * @see elm_bg_color_get() for more details
167 *
168 * @ingroup Bg
169 */
170EAPI void elm_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b);
171
172/**
173 * Set the size of the pixmap representation of the image set on a
174 * given background widget.
175 *
176 * @param obj The background object handle
177 * @param w The new width of the image pixmap representation.
178 * @param h The new height of the image pixmap representation.
179 *
180 * @warning This function just makes sense if an image file was set on
181 * @p obj, with elm_bg_file_set().
182 *
183 * This function sets a new size for pixmap representation of the
184 * given bg image. It allows for the image to be loaded already in the
185 * specified size, reducing the memory usage and load time (for
186 * example, when loading a big image file with its load size set to a
187 * smaller size)
188 *
189 * @note This is just a hint for the underlying system. The real size
190 * of the pixmap may differ depending on the type of image being
191 * loaded, being bigger than requested.
192 *
193 * @ingroup Bg
194 */
195EAPI void elm_bg_load_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
196
197/**
198 * @}
199 */
diff --git a/libraries/elementary/src/lib/elm_box.c b/libraries/elementary/src/lib/elm_box.c
new file mode 100644
index 0000000..bcf0b38
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_box.c
@@ -0,0 +1,683 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_box.h"
4
5static const char SIG_CHILD_ADDED[] = "child,added";
6static const char SIG_CHILD_REMOVED[] = "child,removed";
7
8static const Evas_Smart_Cb_Description _signals[] = {
9 {SIG_CHILD_ADDED, ""},
10 {SIG_CHILD_REMOVED, ""},
11 {NULL, NULL}
12};
13
14
15typedef struct _Widget_Data Widget_Data;
16typedef struct _Transition_Animation_Data Transition_Animation_Data;
17
18struct _Widget_Data
19{
20 Evas_Object *box;
21 Eina_Bool horizontal:1;
22 Eina_Bool homogeneous:1;
23 Eina_Bool recalc:1;
24};
25
26struct _Elm_Box_Transition
27{
28 double initial_time;
29 double duration;
30 Eina_Bool animation_ended:1;
31 Eina_Bool recalculate:1;
32 Ecore_Animator *animator;
33
34 struct
35 {
36 Evas_Object_Box_Layout layout;
37 void *data;
38 void(*free_data)(void *data);
39 } start, end;
40
41 void(*transition_end_cb)(void *data);
42 void *transition_end_data;
43 void (*transition_end_free_data)(void *data);
44 Eina_List *objs;
45 Evas_Object *box;
46};
47
48struct _Transition_Animation_Data
49{
50 Evas_Object *obj;
51 struct
52 {
53 Evas_Coord x, y, w, h;
54 } start, end;
55};
56
57static const char *widtype = NULL;
58static void _del_hook(Evas_Object *obj);
59static void _sizing_eval(Evas_Object *obj);
60static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
61static void _sub_del(void *data, Evas_Object *obj, void *event_info);
62
63static void
64_del_pre_hook(Evas_Object *obj)
65{
66 Widget_Data *wd = elm_widget_data_get(obj);
67 if (!wd) return;
68 evas_object_event_callback_del_full
69 (wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
70 evas_object_box_remove_all(wd->box, EINA_FALSE);
71}
72
73static void
74_del_hook(Evas_Object *obj)
75{
76 Widget_Data *wd = elm_widget_data_get(obj);
77 if (!wd) return;
78 free(wd);
79}
80
81static void *
82_elm_box_list_data_get(const Eina_List *list)
83{
84 Evas_Object_Box_Option *opt = eina_list_data_get(list);
85 return opt->obj;
86}
87
88static void
89_cb_proxy_child_added(void *data, Evas_Object *o __UNUSED__, void *event_info)
90{
91 Evas_Object *box = data;
92 Evas_Object_Box_Option *opt = event_info;
93 evas_object_smart_callback_call(box, SIG_CHILD_ADDED, opt->obj);
94}
95
96static void
97_cb_proxy_child_removed(void *data, Evas_Object *o __UNUSED__, void *event_info)
98{
99 Evas_Object *box = data;
100 Evas_Object *child = event_info;
101 evas_object_smart_callback_call(box, SIG_CHILD_REMOVED, child);
102}
103
104static Eina_Bool
105_elm_box_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
106{
107 Widget_Data *wd = elm_widget_data_get(obj);
108 const Eina_List *items;
109 void *(*list_data_get) (const Eina_List *list);
110
111 if ((!wd) || (!wd->box))
112 return EINA_FALSE;
113
114 /* Focus chain */
115 /* TODO: Change this to use other chain */
116 if ((items = elm_widget_focus_custom_chain_get(obj)))
117 list_data_get = eina_list_data_get;
118 else
119 {
120 Evas_Object_Box_Data *bd = evas_object_smart_data_get(wd->box);
121 items = bd->children;
122 list_data_get = _elm_box_list_data_get;
123
124 if (!items) return EINA_FALSE;
125 }
126
127 return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
128}
129
130static void
131_theme_hook(Evas_Object *obj)
132{
133 Widget_Data *wd = elm_widget_data_get(obj);
134 if (!wd) return;
135 _elm_widget_mirrored_reload(obj);
136 evas_object_smart_calculate(wd->box);
137}
138
139static void
140_sizing_eval(Evas_Object *obj)
141{
142 Widget_Data *wd = elm_widget_data_get(obj);
143 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
144 Evas_Coord w, h;
145 if (!wd) return;
146 evas_object_size_hint_min_get(wd->box, &minw, &minh);
147 evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
148 evas_object_size_hint_min_set(obj, minw, minh);
149 evas_object_size_hint_max_set(obj, maxw, maxh);
150 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
151 if (w < minw) w = minw;
152 if (h < minh) h = minh;
153 if ((maxw >= 0) && (w > maxw)) w = maxw;
154 if ((maxh >= 0) && (h > maxh)) h = maxh;
155 evas_object_resize(obj, w, h);
156}
157
158static void
159_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
160{
161 _sizing_eval(data);
162}
163
164static void
165_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
166{
167 _sizing_eval(obj);
168}
169
170static void
171_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
172{
173 Evas_Object *obj = (Evas_Object *) data;
174 Widget_Data *wd = elm_widget_data_get(obj);
175 if (!wd) return;
176 _els_box_layout(o, priv, wd->horizontal, wd->homogeneous,
177 elm_widget_mirrored_get(obj));
178}
179
180static Eina_Bool
181_transition_animation(void *data)
182{
183 evas_object_smart_changed(data);
184 return ECORE_CALLBACK_RENEW;
185}
186
187static void
188_transition_layout_child_added(void *data, Evas_Object *obj __UNUSED__, void *event_info)
189{
190 Transition_Animation_Data *tad;
191 Evas_Object_Box_Option *opt = event_info;
192 Elm_Box_Transition *layout_data = data;
193
194 tad = calloc(1, sizeof(Transition_Animation_Data));
195 if (!tad) return;
196 tad->obj = opt->obj;
197 layout_data->objs = eina_list_append(layout_data->objs, tad);
198 layout_data->recalculate = EINA_TRUE;
199}
200
201static void
202_transition_layout_child_removed(void *data, Evas_Object *obj __UNUSED__, void *event_info)
203{
204 Eina_List *l;
205 Transition_Animation_Data *tad;
206 Elm_Box_Transition *layout_data = data;
207
208 EINA_LIST_FOREACH(layout_data->objs, l, tad)
209 {
210 if (tad->obj == event_info)
211 {
212 free(eina_list_data_get(l));
213 layout_data->objs = eina_list_remove_list(layout_data->objs, l);
214 layout_data->recalculate = EINA_TRUE;
215 break;
216 }
217 }
218}
219
220static void
221_transition_layout_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
222{
223 Elm_Box_Transition *layout_data = data;
224 layout_data->recalculate = EINA_TRUE;
225}
226
227static void
228_transition_layout_calculate_coords(Evas_Object *obj, Evas_Object_Box_Data *priv,
229 Elm_Box_Transition *layout_data)
230{
231 Eina_List *l;
232 Transition_Animation_Data *tad;
233 Evas_Coord x, y, w, h;
234 const double curtime = ecore_loop_time_get();
235
236 layout_data->duration =
237 layout_data->duration - (curtime - layout_data->initial_time);
238 layout_data->initial_time = curtime;
239
240 evas_object_geometry_get(obj, &x, &y, &w, &h);
241 EINA_LIST_FOREACH(layout_data->objs, l, tad)
242 {
243 evas_object_geometry_get(tad->obj, &tad->start.x, &tad->start.y,
244 &tad->start.w, &tad->start.h);
245 tad->start.x = tad->start.x - x;
246 tad->start.y = tad->start.y - y;
247 }
248 layout_data->end.layout(obj, priv, layout_data->end.data);
249 EINA_LIST_FOREACH(layout_data->objs, l, tad)
250 {
251 evas_object_geometry_get(tad->obj, &tad->end.x, &tad->end.y,
252 &tad->end.w, &tad->end.h);
253 tad->end.x = tad->end.x - x;
254 tad->end.y = tad->end.y - y;
255 }
256}
257
258static Eina_Bool
259_transition_layout_load_children_list(Evas_Object_Box_Data *priv,
260 Elm_Box_Transition *layout_data)
261{
262 Eina_List *l;
263 Evas_Object_Box_Option *opt;
264 Transition_Animation_Data *tad;
265
266 EINA_LIST_FREE(layout_data->objs, tad)
267 free(tad);
268
269 EINA_LIST_FOREACH(priv->children, l, opt)
270 {
271 tad = calloc(1, sizeof(Transition_Animation_Data));
272 if (!tad)
273 {
274 EINA_LIST_FREE(layout_data->objs, tad)
275 free(tad);
276 layout_data->objs = NULL;
277 return EINA_FALSE;
278 }
279 tad->obj = opt->obj;
280 layout_data->objs = eina_list_append(layout_data->objs, tad);
281 }
282 return EINA_TRUE;
283}
284
285static Eina_Bool
286_transition_layout_animation_start(Evas_Object *obj, Evas_Object_Box_Data *priv,
287 Elm_Box_Transition *layout_data, Eina_Bool(*transition_animation_cb)(void *data))
288{
289 layout_data->start.layout(obj, priv, layout_data->start.data);
290 layout_data->box = obj;
291 layout_data->initial_time = ecore_loop_time_get();
292
293 if (!_transition_layout_load_children_list(priv, layout_data))
294 return EINA_FALSE;
295 _transition_layout_calculate_coords(obj, priv, layout_data);
296
297 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
298 _transition_layout_obj_resize_cb, layout_data);
299 evas_object_smart_callback_add(obj, SIG_CHILD_ADDED,
300 _transition_layout_child_added, layout_data);
301 evas_object_smart_callback_add(obj, SIG_CHILD_REMOVED,
302 _transition_layout_child_removed, layout_data);
303 if (!layout_data->animator)
304 layout_data->animator = ecore_animator_add(transition_animation_cb, obj);
305 layout_data->animation_ended = EINA_FALSE;
306 return EINA_TRUE;
307}
308
309static void
310_transition_layout_animation_stop(Elm_Box_Transition *layout_data)
311{
312 layout_data->animation_ended = EINA_TRUE;
313 if (layout_data->animator)
314 {
315 ecore_animator_del(layout_data->animator);
316 layout_data->animator = NULL;
317 }
318
319 if (layout_data->transition_end_cb)
320 layout_data->transition_end_cb(layout_data->transition_end_data);
321}
322
323static void
324_transition_layout_animation_exec(Evas_Object *obj, Evas_Object_Box_Data *priv __UNUSED__,
325 Elm_Box_Transition *layout_data, const double curtime)
326{
327 Eina_List *l;
328 Transition_Animation_Data *tad;
329 Evas_Coord x, y, w, h;
330 Evas_Coord cur_x, cur_y, cur_w, cur_h;
331 double progress = 0.0;
332
333 progress = (curtime - layout_data->initial_time) / layout_data->duration;
334 evas_object_geometry_get(obj, &x, &y, &w, &h);
335
336 EINA_LIST_FOREACH(layout_data->objs, l, tad)
337 {
338 cur_x = x + tad->start.x + ((tad->end.x - tad->start.x) * progress);
339 cur_y = y + tad->start.y + ((tad->end.y - tad->start.y) * progress);
340 cur_w = tad->start.w + ((tad->end.w - tad->start.w) * progress);
341 cur_h = tad->start.h + ((tad->end.h - tad->start.h) * progress);
342 evas_object_move(tad->obj, cur_x, cur_y);
343 evas_object_resize(tad->obj, cur_w, cur_h);
344 }
345}
346
347EAPI Evas_Object *
348elm_box_add(Evas_Object *parent)
349{
350 Evas_Object *obj;
351 Evas *e;
352 Widget_Data *wd;
353
354 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
355
356 ELM_SET_WIDTYPE(widtype, "box");
357 elm_widget_type_set(obj, "box");
358 elm_widget_sub_object_add(parent, obj);
359 elm_widget_data_set(obj, wd);
360 elm_widget_del_hook_set(obj, _del_hook);
361 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
362 elm_widget_focus_next_hook_set(obj, _elm_box_focus_next_hook);
363 elm_widget_can_focus_set(obj, EINA_FALSE);
364 elm_widget_highlight_ignore_set(obj, EINA_TRUE);
365 elm_widget_theme_hook_set(obj, _theme_hook);
366
367 wd->box = evas_object_box_add(e);
368 /*evas_object_box_layout_set(wd->box, evas_object_box_layout_vertical,
369 NULL, NULL);*/
370 evas_object_box_layout_set(wd->box, _layout, obj, NULL);
371
372 evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
373 _changed_size_hints, obj);
374 elm_widget_resize_object_set(obj, wd->box);
375
376 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
377
378 evas_object_smart_callbacks_descriptions_set(obj, _signals);
379 evas_object_smart_callback_add
380 (wd->box, SIG_CHILD_ADDED, _cb_proxy_child_added, obj);
381 evas_object_smart_callback_add
382 (wd->box, SIG_CHILD_REMOVED, _cb_proxy_child_removed, obj);
383
384 return obj;
385}
386
387EAPI void
388elm_box_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
389{
390 ELM_CHECK_WIDTYPE(obj, widtype);
391 Widget_Data *wd = elm_widget_data_get(obj);
392 if (!wd) return;
393 wd->horizontal = !!horizontal;
394 evas_object_smart_calculate(wd->box);
395 /*if (wd->horizontal)
396 {
397 if (wd->homogeneous)
398 evas_object_box_layout_set(wd->box,
399 evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
400 else
401 evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
402 NULL, NULL);
403 }
404 else
405 {
406 if (wd->homogeneous)
407 evas_object_box_layout_set(wd->box,
408 evas_object_box_layout_homogeneous_vertical, NULL, NULL);
409 else
410 evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
411 NULL, NULL);
412 } */
413}
414
415EAPI Eina_Bool
416elm_box_horizontal_get(const Evas_Object *obj)
417{
418 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
419 Widget_Data *wd = elm_widget_data_get(obj);
420 if (!wd) return EINA_FALSE;
421 return wd->horizontal;
422}
423
424EAPI void
425elm_box_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
426{
427 ELM_CHECK_WIDTYPE(obj, widtype);
428 Widget_Data *wd = elm_widget_data_get(obj);
429 if (!wd) return;
430 wd->homogeneous = !!homogeneous;
431 evas_object_smart_calculate(wd->box);
432 /*if (wd->horizontal)
433 {
434 if (wd->homogeneous)
435 evas_object_box_layout_set(wd->box,
436 evas_object_box_layout_homogeneous_horizontal, NULL, NULL);
437 else
438 evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
439 NULL, NULL);
440 }
441 else
442 {
443 if (wd->homogeneous)
444 evas_object_box_layout_set(wd->box,
445 evas_object_box_layout_homogeneous_vertical, NULL, NULL);
446 else
447 evas_object_box_layout_set(wd->box, evas_object_box_layout_horizontal,
448 NULL, NULL);
449 } */
450}
451
452EAPI Eina_Bool
453elm_box_homogeneous_get(const Evas_Object *obj)
454{
455 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
456 Widget_Data *wd = elm_widget_data_get(obj);
457 if (!wd) return EINA_FALSE;
458 return wd->homogeneous;
459}
460
461EAPI void
462elm_box_pack_start(Evas_Object *obj, Evas_Object *subobj)
463{
464 ELM_CHECK_WIDTYPE(obj, widtype);
465 Widget_Data *wd = elm_widget_data_get(obj);
466 if (!wd) return;
467 elm_widget_sub_object_add(obj, subobj);
468 evas_object_box_prepend(wd->box, subobj);
469}
470
471EAPI void
472elm_box_pack_end(Evas_Object *obj, Evas_Object *subobj)
473{
474 ELM_CHECK_WIDTYPE(obj, widtype);
475 Widget_Data *wd = elm_widget_data_get(obj);
476 if (!wd) return;
477 elm_widget_sub_object_add(obj, subobj);
478 evas_object_box_append(wd->box, subobj);
479}
480
481EAPI void
482elm_box_pack_before(Evas_Object *obj, Evas_Object *subobj, Evas_Object *before)
483{
484 ELM_CHECK_WIDTYPE(obj, widtype);
485 Widget_Data *wd = elm_widget_data_get(obj);
486 if (!wd) return;
487 elm_widget_sub_object_add(obj, subobj);
488 evas_object_box_insert_before(wd->box, subobj, before);
489}
490
491EAPI void
492elm_box_pack_after(Evas_Object *obj, Evas_Object *subobj, Evas_Object *after)
493{
494 ELM_CHECK_WIDTYPE(obj, widtype);
495 Widget_Data *wd = elm_widget_data_get(obj);
496 if (!wd) return;
497 elm_widget_sub_object_add(obj, subobj);
498 evas_object_box_insert_after(wd->box, subobj, after);
499}
500
501EAPI void
502elm_box_clear(Evas_Object *obj)
503{
504 ELM_CHECK_WIDTYPE(obj, widtype);
505 Widget_Data *wd = elm_widget_data_get(obj);
506 if (!wd) return;
507 evas_object_box_remove_all(wd->box, EINA_TRUE);
508}
509
510EAPI void
511elm_box_unpack(Evas_Object *obj, Evas_Object *subobj)
512{
513 ELM_CHECK_WIDTYPE(obj, widtype);
514 Widget_Data *wd = elm_widget_data_get(obj);
515 if (!wd) return;
516 evas_object_box_remove(wd->box, subobj);
517}
518
519EAPI void
520elm_box_unpack_all(Evas_Object *obj)
521{
522 ELM_CHECK_WIDTYPE(obj, widtype);
523 Widget_Data *wd = elm_widget_data_get(obj);
524 if (!wd) return;
525 evas_object_box_remove_all(wd->box, EINA_FALSE);
526}
527
528EAPI void
529elm_box_layout_set(Evas_Object *obj, Evas_Object_Box_Layout cb, const void *data, Ecore_Cb free_data)
530{
531 ELM_CHECK_WIDTYPE(obj, widtype);
532 Widget_Data *wd = elm_widget_data_get(obj);
533 if (!wd) return;
534
535 if (cb)
536 evas_object_box_layout_set(wd->box, cb, data, free_data);
537 else
538 evas_object_box_layout_set(wd->box, _layout, obj, NULL);
539}
540
541EAPI void
542elm_box_layout_transition(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data)
543{
544 Elm_Box_Transition *box_data = data;
545 const double curtime = ecore_loop_time_get();
546
547 if (box_data->animation_ended)
548 {
549 box_data->end.layout(obj, priv, box_data->end.data);
550 return;
551 }
552
553 if (!box_data->animator)
554 {
555 if (!_transition_layout_animation_start(obj, priv, box_data,
556 _transition_animation))
557 return;
558 }
559 else
560 {
561 if (box_data->recalculate)
562 {
563 _transition_layout_calculate_coords(obj, priv, box_data);
564 box_data->recalculate = EINA_FALSE;
565 }
566 }
567
568 if ((curtime >= box_data->duration + box_data->initial_time))
569 _transition_layout_animation_stop(box_data);
570 else
571 _transition_layout_animation_exec(obj, priv, box_data, curtime);
572}
573
574EAPI Elm_Box_Transition *
575elm_box_transition_new(const double duration,
576 Evas_Object_Box_Layout start_layout, void *start_layout_data,
577 Ecore_Cb start_layout_free_data,
578 Evas_Object_Box_Layout end_layout, void *end_layout_data,
579 Ecore_Cb end_layout_free_data,
580 Ecore_Cb transition_end_cb,
581 void *transition_end_data)
582{
583 Elm_Box_Transition *box_data;
584
585 EINA_SAFETY_ON_NULL_RETURN_VAL(start_layout, NULL);
586 EINA_SAFETY_ON_NULL_RETURN_VAL(end_layout, NULL);
587
588 box_data = calloc(1, sizeof(Elm_Box_Transition));
589 if (!box_data)
590 return NULL;
591
592 box_data->start.layout = start_layout;
593 box_data->start.data = start_layout_data;
594 box_data->start.free_data = start_layout_free_data;
595 box_data->end.layout = end_layout;
596 box_data->end.data = end_layout_data;
597 box_data->end.free_data = end_layout_free_data;
598 box_data->duration = duration;
599 box_data->transition_end_cb = transition_end_cb;
600 box_data->transition_end_data = transition_end_data;
601 return box_data;
602}
603
604EAPI void
605elm_box_transition_free(void *data)
606{
607 EINA_SAFETY_ON_NULL_RETURN(data);
608
609 Transition_Animation_Data *tad;
610 Elm_Box_Transition *box_data = data;
611 if ((box_data->start.free_data) && (box_data->start.data))
612 box_data->start.free_data(box_data->start.data);
613 if ((box_data->end.free_data) && (box_data->end.data))
614 box_data->end.free_data(box_data->end.data);
615 EINA_LIST_FREE(box_data->objs, tad)
616 free(tad);
617 evas_object_event_callback_del(box_data->box, EVAS_CALLBACK_RESIZE, _transition_layout_obj_resize_cb);
618 evas_object_smart_callback_del(box_data->box, SIG_CHILD_ADDED, _transition_layout_child_added);
619 evas_object_smart_callback_del(box_data->box, SIG_CHILD_REMOVED, _transition_layout_child_removed);
620 if (box_data->animator)
621 {
622 ecore_animator_del(box_data->animator);
623 box_data->animator = NULL;
624 }
625 free(data);
626}
627
628EAPI Eina_List *
629elm_box_children_get(const Evas_Object *obj)
630{
631 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
632 Widget_Data *wd = elm_widget_data_get(obj);
633 if (!wd) return NULL;
634 return evas_object_box_children_get(wd->box);
635}
636
637EAPI void
638elm_box_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
639{
640 ELM_CHECK_WIDTYPE(obj, widtype);
641 Widget_Data *wd = elm_widget_data_get(obj);
642 if (!wd) return;
643 evas_object_box_padding_set(wd->box, horizontal, vertical);
644}
645
646EAPI void
647elm_box_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical)
648{
649 ELM_CHECK_WIDTYPE(obj, widtype);
650 Widget_Data *wd = elm_widget_data_get(obj);
651 if (!wd) return;
652 evas_object_box_padding_get(wd->box, horizontal, vertical);
653}
654
655EAPI void
656elm_box_align_set(Evas_Object *obj, double horizontal, double vertical)
657{
658 ELM_CHECK_WIDTYPE(obj, widtype);
659 Widget_Data *wd = elm_widget_data_get(obj);
660 if (!wd) return;
661 evas_object_size_hint_align_set(wd->box, horizontal, vertical);
662}
663
664EAPI void
665elm_box_align_get(const Evas_Object *obj, double *horizontal, double *vertical)
666{
667 ELM_CHECK_WIDTYPE(obj, widtype);
668 Widget_Data *wd = elm_widget_data_get(obj);
669 if (!wd) return;
670 evas_object_size_hint_align_get(wd->box, horizontal, vertical);
671}
672
673EAPI void
674elm_box_recalculate(Evas_Object *obj)
675{
676 ELM_CHECK_WIDTYPE(obj, widtype);
677 Widget_Data *wd = elm_widget_data_get(obj);
678 if ((!wd) || (wd->recalc)) return;
679 evas_object_smart_need_recalculate_set(wd->box, EINA_TRUE);
680 wd->recalc++;
681 evas_object_smart_calculate(wd->box);
682 wd->recalc--;
683}
diff --git a/libraries/elementary/src/lib/elm_box.h b/libraries/elementary/src/lib/elm_box.h
new file mode 100644
index 0000000..43011ab
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_box.h
@@ -0,0 +1,498 @@
1/**
2 * @defgroup Box Box
3 * @ingroup Elementary
4 *
5 * @image html img/widget/box/preview-00.png
6 * @image latex img/widget/box/preview-00.eps width=\textwidth
7 *
8 * @image html img/box.png
9 * @image latex img/box.eps width=\textwidth
10 *
11 * A box arranges objects in a linear fashion, governed by a layout function
12 * that defines the details of this arrangement.
13 *
14 * By default, the box will use an internal function to set the layout to
15 * a single row, either vertical or horizontal. This layout is affected
16 * by a number of parameters, such as the homogeneous flag set by
17 * elm_box_homogeneous_set(), the values given by elm_box_padding_set() and
18 * elm_box_align_set() and the hints set to each object in the box.
19 *
20 * For this default layout, it's possible to change the orientation with
21 * elm_box_horizontal_set(). The box will start in the vertical orientation,
22 * placing its elements ordered from top to bottom. When horizontal is set,
23 * the order will go from left to right. If the box is set to be
24 * homogeneous, every object in it will be assigned the same space, that
25 * of the largest object. Padding can be used to set some spacing between
26 * the cell given to each object. The alignment of the box, set with
27 * elm_box_align_set(), determines how the bounding box of all the elements
28 * will be placed within the space given to the box widget itself.
29 *
30 * The size hints of each object also affect how they are placed and sized
31 * within the box. evas_object_size_hint_min_set() will give the minimum
32 * size the object can have, and the box will use it as the basis for all
33 * latter calculations. Elementary widgets set their own minimum size as
34 * needed, so there's rarely any need to use it manually.
35 *
36 * evas_object_size_hint_weight_set(), when not in homogeneous mode, is
37 * used to tell whether the object will be allocated the minimum size it
38 * needs or if the space given to it should be expanded. It's important
39 * to realize that expanding the size given to the object is not the same
40 * thing as resizing the object. It could very well end being a small
41 * widget floating in a much larger empty space. If not set, the weight
42 * for objects will normally be 0.0 for both axis, meaning the widget will
43 * not be expanded. To take as much space possible, set the weight to
44 * EVAS_HINT_EXPAND (defined to 1.0) for the desired axis to expand.
45 *
46 * Besides how much space each object is allocated, it's possible to control
47 * how the widget will be placed within that space using
48 * evas_object_size_hint_align_set(). By default, this value will be 0.5
49 * for both axis, meaning the object will be centered, but any value from
50 * 0.0 (left or top, for the @c x and @c y axis, respectively) to 1.0
51 * (right or bottom) can be used. The special value EVAS_HINT_FILL, which
52 * is -1.0, means the object will be resized to fill the entire space it
53 * was allocated.
54 *
55 * In addition, customized functions to define the layout can be set, which
56 * allow the application developer to organize the objects within the box
57 * in any number of ways.
58 *
59 * The special elm_box_layout_transition() function can be used
60 * to switch from one layout to another, animating the motion of the
61 * children of the box.
62 *
63 * @note Objects should not be added to box objects using _add() calls.
64 *
65 * Some examples on how to use boxes follow:
66 * @li @ref box_example_01
67 * @li @ref box_example_02
68 *
69 * @{
70 */
71/**
72 * @typedef Elm_Box_Transition
73 *
74 * Opaque handler containing the parameters to perform an animated
75 * transition of the layout the box uses.
76 *
77 * @see elm_box_transition_new()
78 * @see elm_box_layout_set()
79 * @see elm_box_layout_transition()
80 */
81typedef struct _Elm_Box_Transition Elm_Box_Transition;
82
83/**
84 * Add a new box to the parent
85 *
86 * By default, the box will be in vertical mode and non-homogeneous.
87 *
88 * @param parent The parent object
89 * @return The new object or NULL if it cannot be created
90 *
91 * @ingroup Box
92 */
93EAPI Evas_Object *elm_box_add(Evas_Object *parent);
94
95/**
96 * Set the horizontal orientation
97 *
98 * By default, box object arranges their contents vertically from top to
99 * bottom.
100 * By calling this function with @p horizontal as EINA_TRUE, the box will
101 * become horizontal, arranging contents from left to right.
102 *
103 * @note This flag is ignored if a custom layout function is set.
104 *
105 * @param obj The box object
106 * @param horizontal The horizontal flag (EINA_TRUE = horizontal,
107 * EINA_FALSE = vertical)
108 *
109 * @ingroup Box
110 */
111EAPI void elm_box_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
112
113/**
114 * Get the horizontal orientation
115 *
116 * @param obj The box object
117 * @return EINA_TRUE if the box is set to horizontal mode, EINA_FALSE otherwise
118 */
119EAPI Eina_Bool elm_box_horizontal_get(const Evas_Object *obj);
120
121/**
122 * Set the box to arrange its children homogeneously
123 *
124 * If enabled, homogeneous layout makes all items the same size, according
125 * to the size of the largest of its children.
126 *
127 * @note This flag is ignored if a custom layout function is set.
128 *
129 * @param obj The box object
130 * @param homogeneous The homogeneous flag
131 *
132 * @ingroup Box
133 */
134EAPI void elm_box_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous);
135
136/**
137 * Get whether the box is using homogeneous mode or not
138 *
139 * @param obj The box object
140 * @return EINA_TRUE if it's homogeneous, EINA_FALSE otherwise
141 *
142 * @ingroup Box
143 */
144EAPI Eina_Bool elm_box_homogeneous_get(const Evas_Object *obj);
145
146/**
147 * Add an object to the beginning of the pack list
148 *
149 * Pack @p subobj into the box @p obj, placing it first in the list of
150 * children objects. The actual position the object will get on screen
151 * depends on the layout used. If no custom layout is set, it will be at
152 * the top or left, depending if the box is vertical or horizontal,
153 * respectively.
154 *
155 * @param obj The box object
156 * @param subobj The object to add to the box
157 *
158 * @see elm_box_pack_end()
159 * @see elm_box_pack_before()
160 * @see elm_box_pack_after()
161 * @see elm_box_unpack()
162 * @see elm_box_unpack_all()
163 * @see elm_box_clear()
164 *
165 * @ingroup Box
166 */
167EAPI void elm_box_pack_start(Evas_Object *obj, Evas_Object *subobj);
168
169/**
170 * Add an object at the end of the pack list
171 *
172 * Pack @p subobj into the box @p obj, placing it last in the list of
173 * children objects. The actual position the object will get on screen
174 * depends on the layout used. If no custom layout is set, it will be at
175 * the bottom or right, depending if the box is vertical or horizontal,
176 * respectively.
177 *
178 * @param obj The box object
179 * @param subobj The object to add to the box
180 *
181 * @see elm_box_pack_start()
182 * @see elm_box_pack_before()
183 * @see elm_box_pack_after()
184 * @see elm_box_unpack()
185 * @see elm_box_unpack_all()
186 * @see elm_box_clear()
187 *
188 * @ingroup Box
189 */
190EAPI void elm_box_pack_end(Evas_Object *obj, Evas_Object *subobj);
191
192/**
193 * Adds an object to the box before the indicated object
194 *
195 * This will add the @p subobj to the box indicated before the object
196 * indicated with @p before. If @p before is not already in the box, results
197 * are undefined. Before means either to the left of the indicated object or
198 * above it depending on orientation.
199 *
200 * @param obj The box object
201 * @param subobj The object to add to the box
202 * @param before The object before which to add it
203 *
204 * @see elm_box_pack_start()
205 * @see elm_box_pack_end()
206 * @see elm_box_pack_after()
207 * @see elm_box_unpack()
208 * @see elm_box_unpack_all()
209 * @see elm_box_clear()
210 *
211 * @ingroup Box
212 */
213EAPI void elm_box_pack_before(Evas_Object *obj, Evas_Object *subobj, Evas_Object *before);
214
215/**
216 * Adds an object to the box after the indicated object
217 *
218 * This will add the @p subobj to the box indicated after the object
219 * indicated with @p after. If @p after is not already in the box, results
220 * are undefined. After means either to the right of the indicated object or
221 * below it depending on orientation.
222 *
223 * @param obj The box object
224 * @param subobj The object to add to the box
225 * @param after The object after which to add it
226 *
227 * @see elm_box_pack_start()
228 * @see elm_box_pack_end()
229 * @see elm_box_pack_before()
230 * @see elm_box_unpack()
231 * @see elm_box_unpack_all()
232 * @see elm_box_clear()
233 *
234 * @ingroup Box
235 */
236EAPI void elm_box_pack_after(Evas_Object *obj, Evas_Object *subobj, Evas_Object *after);
237
238/**
239 * Clear the box of all children
240 *
241 * Remove all the elements contained by the box, deleting the respective
242 * objects.
243 *
244 * @param obj The box object
245 *
246 * @see elm_box_unpack()
247 * @see elm_box_unpack_all()
248 *
249 * @ingroup Box
250 */
251EAPI void elm_box_clear(Evas_Object *obj);
252
253/**
254 * Unpack a box item
255 *
256 * Remove the object given by @p subobj from the box @p obj without
257 * deleting it.
258 *
259 * @param obj The box object
260 * @param subobj The object to unpack
261 *
262 * @see elm_box_unpack_all()
263 * @see elm_box_clear()
264 *
265 * @ingroup Box
266 */
267EAPI void elm_box_unpack(Evas_Object *obj, Evas_Object *subobj);
268
269/**
270 * Remove all items from the box, without deleting them
271 *
272 * Clear the box from all children, but don't delete the respective objects.
273 * If no other references of the box children exist, the objects will never
274 * be deleted, and thus the application will leak the memory. Make sure
275 * when using this function that you hold a reference to all the objects
276 * in the box @p obj.
277 *
278 * @param obj The box object
279 *
280 * @see elm_box_clear()
281 * @see elm_box_unpack()
282 *
283 * @ingroup Box
284 */
285EAPI void elm_box_unpack_all(Evas_Object *obj);
286
287/**
288 * Retrieve a list of the objects packed into the box
289 *
290 * Returns a new @c Eina_List with a pointer to @c Evas_Object in its nodes.
291 * The order of the list corresponds to the packing order the box uses.
292 *
293 * You must free this list with eina_list_free() once you are done with it.
294 *
295 * @param obj The box object
296 *
297 * @ingroup Box
298 */
299EAPI Eina_List *elm_box_children_get(const Evas_Object *obj);
300
301/**
302 * Set the space (padding) between the box's elements.
303 *
304 * Extra space in pixels that will be added between a box child and its
305 * neighbors after its containing cell has been calculated. This padding
306 * is set for all elements in the box, besides any possible padding that
307 * individual elements may have through their size hints.
308 *
309 * @param obj The box object
310 * @param horizontal The horizontal space between elements
311 * @param vertical The vertical space between elements
312 *
313 * @ingroup Box
314 */
315EAPI void elm_box_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical);
316
317/**
318 * Get the space (padding) between the box's elements.
319 *
320 * @param obj The box object
321 * @param horizontal The horizontal space between elements
322 * @param vertical The vertical space between elements
323 *
324 * @see elm_box_padding_set()
325 *
326 * @ingroup Box
327 */
328EAPI void elm_box_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical);
329
330/**
331 * Set the alignment of the whole bounding box of contents.
332 *
333 * Sets how the bounding box containing all the elements of the box, after
334 * their sizes and position has been calculated, will be aligned within
335 * the space given for the whole box widget.
336 *
337 * @param obj The box object
338 * @param horizontal The horizontal alignment of elements
339 * @param vertical The vertical alignment of elements
340 *
341 * @ingroup Box
342 */
343EAPI void elm_box_align_set(Evas_Object *obj, double horizontal, double vertical);
344
345/**
346 * Get the alignment of the whole bounding box of contents.
347 *
348 * @param obj The box object
349 * @param horizontal The horizontal alignment of elements
350 * @param vertical The vertical alignment of elements
351 *
352 * @see elm_box_align_set()
353 *
354 * @ingroup Box
355 */
356EAPI void elm_box_align_get(const Evas_Object *obj, double *horizontal, double *vertical);
357
358/**
359 * Force the box to recalculate its children packing.
360 *
361 * If any children was added or removed, box will not calculate the
362 * values immediately rather leaving it to the next main loop
363 * iteration. While this is great as it would save lots of
364 * recalculation, whenever you need to get the position of a just
365 * added item you must force recalculate before doing so.
366 *
367 * @param obj The box object.
368 *
369 * @ingroup Box
370 */
371EAPI void elm_box_recalculate(Evas_Object *obj);
372
373/**
374 * Set the layout defining function to be used by the box
375 *
376 * Whenever anything changes that requires the box in @p obj to recalculate
377 * the size and position of its elements, the function @p cb will be called
378 * to determine what the layout of the children will be.
379 *
380 * Once a custom function is set, everything about the children layout
381 * is defined by it. The flags set by elm_box_horizontal_set() and
382 * elm_box_homogeneous_set() no longer have any meaning, and the values
383 * given by elm_box_padding_set() and elm_box_align_set() are up to this
384 * layout function to decide if they are used and how. These last two
385 * will be found in the @c priv parameter, of type @c Evas_Object_Box_Data,
386 * passed to @p cb. The @c Evas_Object the function receives is not the
387 * Elementary widget, but the internal Evas Box it uses, so none of the
388 * functions described here can be used on it.
389 *
390 * Any of the layout functions in @c Evas can be used here, as well as the
391 * special elm_box_layout_transition().
392 *
393 * The final @p data argument received by @p cb is the same @p data passed
394 * here, and the @p free_data function will be called to free it
395 * whenever the box is destroyed or another layout function is set.
396 *
397 * Setting @p cb to NULL will revert back to the default layout function.
398 *
399 * @param obj The box object
400 * @param cb The callback function used for layout
401 * @param data Data that will be passed to layout function
402 * @param free_data Function called to free @p data
403 *
404 * @see elm_box_layout_transition()
405 *
406 * @ingroup Box
407 */
408EAPI void elm_box_layout_set(Evas_Object *obj, Evas_Object_Box_Layout cb, const void *data, Ecore_Cb free_data);
409
410/**
411 * Special layout function that animates the transition from one layout to another
412 *
413 * Normally, when switching the layout function for a box, this will be
414 * reflected immediately on screen on the next render, but it's also
415 * possible to do this through an animated transition.
416 *
417 * This is done by creating an ::Elm_Box_Transition and setting the box
418 * layout to this function.
419 *
420 * For example:
421 * @code
422 * Elm_Box_Transition *t = elm_box_transition_new(1.0,
423 * evas_object_box_layout_vertical, // start
424 * NULL, // data for initial layout
425 * NULL, // free function for initial data
426 * evas_object_box_layout_horizontal, // end
427 * NULL, // data for final layout
428 * NULL, // free function for final data
429 * anim_end, // will be called when animation ends
430 * NULL); // data for anim_end function\
431 * elm_box_layout_set(box, elm_box_layout_transition, t,
432 * elm_box_transition_free);
433 * @endcode
434 *
435 * @note This function can only be used with elm_box_layout_set(). Calling
436 * it directly will not have the expected results.
437 *
438 * @see elm_box_transition_new
439 * @see elm_box_transition_free
440 * @see elm_box_layout_set
441 *
442 * @ingroup Box
443 */
444EAPI void elm_box_layout_transition(Evas_Object *obj, Evas_Object_Box_Data *priv, void *data);
445
446/**
447 * Create a new ::Elm_Box_Transition to animate the switch of layouts
448 *
449 * If you want to animate the change from one layout to another, you need
450 * to set the layout function of the box to elm_box_layout_transition(),
451 * passing as user data to it an instance of ::Elm_Box_Transition with the
452 * necessary information to perform this animation. The free function to
453 * set for the layout is elm_box_transition_free().
454 *
455 * The parameters to create an ::Elm_Box_Transition sum up to how long
456 * will it be, in seconds, a layout function to describe the initial point,
457 * another for the final position of the children and one function to be
458 * called when the whole animation ends. This last function is useful to
459 * set the definitive layout for the box, usually the same as the end
460 * layout for the animation, but could be used to start another transition.
461 *
462 * @param duration The duration of the transition in seconds
463 * @param start_layout The layout function that will be used to start the animation
464 * @param start_layout_data The data to be passed the @p start_layout function
465 * @param start_layout_free_data Function to free @p start_layout_data
466 * @param end_layout The layout function that will be used to end the animation
467 * @param end_layout_data Data param passed to @p end_layout
468 * @param end_layout_free_data The data to be passed the @p end_layout function
469 * @param end_layout_free_data Function to free @p end_layout_data
470 * @param transition_end_cb Callback function called when animation ends
471 * @param transition_end_data Data to be passed to @p transition_end_cb
472 * @return An instance of ::Elm_Box_Transition
473 *
474 * @see elm_box_transition_new
475 * @see elm_box_layout_transition
476 *
477 * @ingroup Box
478 */
479EAPI Elm_Box_Transition *elm_box_transition_new(const double duration, Evas_Object_Box_Layout start_layout, void *start_layout_data, Ecore_Cb start_layout_free_data, Evas_Object_Box_Layout end_layout, void *end_layout_data, Ecore_Cb end_layout_free_data, Ecore_Cb transition_end_cb, void *transition_end_data);
480
481/**
482 * Free a Elm_Box_Transition instance created with elm_box_transition_new().
483 *
484 * This function is mostly useful as the @c free_data parameter in
485 * elm_box_layout_set() when elm_box_layout_transition().
486 *
487 * @param data The Elm_Box_Transition instance to be freed.
488 *
489 * @see elm_box_transition_new
490 * @see elm_box_layout_transition
491 *
492 * @ingroup Box
493 */
494EAPI void elm_box_transition_free(void *data);
495
496/**
497 * @}
498 */
diff --git a/libraries/elementary/src/lib/elm_bubble.c b/libraries/elementary/src/lib/elm_bubble.c
new file mode 100644
index 0000000..0f35578
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_bubble.c
@@ -0,0 +1,368 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *bbl;
9 Evas_Object *content, *icon;
10 const char *label, *info, *corner;
11 Elm_Bubble_Pos pos;
12};
13
14static const char *widtype = NULL;
15static void _del_hook(Evas_Object *obj);
16static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
17static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
18static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
19static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
20static void _theme_hook(Evas_Object *obj);
21static void _sizing_eval(Evas_Object *obj);
22static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
23static void _sub_del(void *data, Evas_Object *obj, void *event_info);
24
25static const char SIG_CLICKED[] = "clicked";
26
27static const Evas_Smart_Cb_Description _signals[] =
28{
29 {SIG_CLICKED, ""},
30 {NULL, NULL}
31};
32
33static const char *corner_string[] =
34{
35 "top_left",
36 "top_right",
37 "bottom_left",
38 "bottom_right"
39};
40
41static void
42_del_hook(Evas_Object *obj)
43{
44 Widget_Data *wd = elm_widget_data_get(obj);
45 if (!wd) return;
46 if (wd->label) eina_stringshare_del(wd->label);
47 if (wd->info) eina_stringshare_del(wd->info);
48 if (wd->corner) eina_stringshare_del(wd->corner);
49 free(wd);
50}
51
52static void
53_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
54{
55 Widget_Data *wd = elm_widget_data_get(obj);
56 if (!wd) return;
57 edje_object_mirrored_set(wd->bbl, rtl);
58}
59
60static void
61_theme_hook(Evas_Object *obj)
62{
63 Widget_Data *wd = elm_widget_data_get(obj);
64 if (!wd) return;
65 _elm_widget_mirrored_reload(obj);
66 _mirrored_set(obj, elm_widget_mirrored_get(obj));
67 _elm_theme_object_set(obj, wd->bbl, "bubble", corner_string[wd->pos],
68 elm_widget_style_get(obj));
69 edje_object_part_text_escaped_set(wd->bbl, "elm.text", wd->label);
70 if (wd->label) edje_object_signal_emit(wd->bbl, "elm,state,text,visible", "elm");
71 else edje_object_signal_emit(wd->bbl, "elm,state,text,hidden", "elm");
72 edje_object_part_text_escaped_set(wd->bbl, "elm.info", wd->info);
73 if (wd->info) edje_object_signal_emit(wd->bbl, "elm,state,info,visible", "elm");
74 else edje_object_signal_emit(wd->bbl, "elm,state,info,hidden", "elm");
75 if (wd->content)
76 {
77 edje_object_part_swallow(wd->bbl, "elm.swallow.content", wd->content);
78 edje_object_message_signal_process(wd->bbl);
79 }
80 if (wd->icon)
81 edje_object_signal_emit(wd->bbl, "elm,state,icon,visible", "elm");
82 else
83 edje_object_signal_emit(wd->bbl, "elm,state,icon,hidden", "elm");
84 edje_object_scale_set(wd->bbl,
85 elm_widget_scale_get(obj) * _elm_config->scale);
86 _sizing_eval(obj);
87}
88
89static void
90_content_set(Evas_Object *obj, Evas_Object *content)
91{
92 Widget_Data *wd = elm_widget_data_get(obj);
93 if (!wd) return;
94
95 if (wd->content == content) return;
96 if (wd->content) evas_object_del(wd->content);
97 wd->content = content;
98 if (content)
99 {
100 elm_widget_sub_object_add(obj, content);
101 evas_object_event_callback_add(content,
102 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
103 _changed_size_hints, obj);
104 edje_object_part_swallow(wd->bbl, "elm.swallow.content", content);
105 }
106 _sizing_eval(obj);
107}
108
109static Evas_Object *
110_content_unset(Evas_Object *obj)
111{
112 Widget_Data *wd = elm_widget_data_get(obj);
113 Evas_Object *content;
114 if (!wd) return NULL;
115 if (!wd->content) return NULL;
116 content = wd->content;
117 elm_widget_sub_object_del(obj, content);
118 evas_object_event_callback_del_full(content,
119 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
120 _changed_size_hints, obj);
121 edje_object_part_unswallow(wd->bbl, content);
122 wd->content = NULL;
123 return content;
124}
125
126static void
127_icon_set(Evas_Object *obj, Evas_Object* icon)
128{
129 Widget_Data *wd = elm_widget_data_get(obj);
130 if (!wd) return;
131 if (wd->icon == icon) return;
132 if (wd->icon) evas_object_del(wd->icon);
133 wd->icon = icon;
134 if (icon)
135 {
136 elm_widget_sub_object_add(obj, icon);
137 edje_object_part_swallow(wd->bbl, "elm.swallow.icon", icon);
138 evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
139 _changed_size_hints, obj);
140 edje_object_signal_emit(wd->bbl, "elm,state,icon,visible", "elm");
141 edje_object_message_signal_process(wd->bbl);
142 }
143 _sizing_eval(obj);
144}
145
146static Evas_Object *
147_icon_unset(Evas_Object *obj)
148{
149 Widget_Data *wd = elm_widget_data_get(obj);
150 Evas_Object *icon;
151 if (!wd) return NULL;
152 if (!wd->icon) return NULL;
153 icon = wd->icon;
154 elm_widget_sub_object_del(obj, icon);
155 evas_object_event_callback_del_full(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
156 _changed_size_hints, obj);
157 edje_object_part_unswallow(wd->bbl, icon);
158 wd->icon = NULL;
159 return icon;
160}
161
162static void
163_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
164{
165 ELM_CHECK_WIDTYPE(obj, widtype);
166 Widget_Data *wd = elm_widget_data_get(obj);
167 if (!wd) return;
168
169 if (!part || !strcmp(part, "default"))
170 _content_set(obj, content);
171 else if (!strcmp(part, "icon"))
172 _icon_set(obj, content);
173}
174
175static Evas_Object *
176_content_get_hook(const Evas_Object *obj, const char *part)
177{
178 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
179 Widget_Data *wd = elm_widget_data_get(obj);
180 if (!wd) return NULL;
181 if (!part || !strcmp(part, "default"))
182 return wd->content;
183 else if (!strcmp(part, "icon"))
184 return wd->icon;
185 return NULL;
186}
187
188static Evas_Object *
189_content_unset_hook(Evas_Object *obj, const char *part)
190{
191 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
192 Widget_Data *wd = elm_widget_data_get(obj);
193 if (!wd) return NULL;
194 if (!part || !strcmp(part, "default"))
195 return _content_unset(obj);
196 else if (!strcmp(part, "icon"))
197 return _icon_unset(obj);
198 return NULL;
199}
200
201static Eina_Bool
202_elm_bubble_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
203{
204 Widget_Data *wd = elm_widget_data_get(obj);
205 Evas_Object *cur;
206
207 if ((!wd) || (!wd->content))
208 return EINA_FALSE;
209
210 cur = wd->content;
211
212 /* Try Focus cycle in subitem */
213 return elm_widget_focus_next_get(cur, dir, next);
214}
215
216static void
217_sizing_eval(Evas_Object *obj)
218{
219 Widget_Data *wd = elm_widget_data_get(obj);
220 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
221 if (!wd) return;
222 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
223 edje_object_size_min_restricted_calc(wd->bbl, &minw, &minh, minw, minh);
224 evas_object_size_hint_min_set(obj, minw, minh);
225 evas_object_size_hint_max_set(obj, maxw, maxh);
226}
227
228static void
229_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
230{
231 Widget_Data *wd = elm_widget_data_get(data);
232 if (!wd) return;
233 _sizing_eval(data);
234}
235
236static void
237_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
238{
239 Widget_Data *wd = elm_widget_data_get(obj);
240 Evas_Object *sub = event_info;
241 if (!wd) return;
242 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
243 _changed_size_hints, obj);
244 if (sub == wd->content) wd->content = NULL;
245 else if (sub == wd->icon)
246 {
247 edje_object_signal_emit(wd->bbl, "elm,state,icon,hidden", "elm");
248 wd->icon = NULL;
249 edje_object_message_signal_process(wd->bbl);
250 }
251 _sizing_eval(obj);
252}
253
254static void
255_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
256{
257 Evas_Event_Mouse_Up *ev = event_info;
258 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
259 return;
260 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
261}
262
263static void
264_elm_bubble_label_set(Evas_Object *obj, const char *item, const char *label)
265{
266 ELM_CHECK_WIDTYPE(obj, widtype);
267 Widget_Data *wd = elm_widget_data_get(obj);
268 if (!wd) return;
269
270 if (!item || !strcmp(item, "default"))
271 {
272 eina_stringshare_replace(&wd->label, label);
273 edje_object_part_text_escaped_set(wd->bbl, "elm.text", label);
274 if (label) edje_object_signal_emit(wd->bbl, "elm,state,text,visible",
275 "elm");
276 else edje_object_signal_emit(wd->bbl, "elm,state,text,hidden", "elm");
277 _sizing_eval(obj);
278 }
279 else if (!strcmp(item, "info"))
280 {
281 eina_stringshare_replace(&wd->info, label);
282 edje_object_part_text_escaped_set(wd->bbl, "elm.info", label);
283 if (label) edje_object_signal_emit(wd->bbl, "elm,state,info,visible",
284 "elm");
285 else edje_object_signal_emit(wd->bbl, "elm,state,info,hidden", "elm");
286 _sizing_eval(obj);
287 }
288}
289
290static const char*
291_elm_bubble_label_get(const Evas_Object *obj, const char *item)
292{
293 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
294 Widget_Data *wd = elm_widget_data_get(obj);
295 if (!wd) return NULL;
296
297 if (!item || !strcmp(item, "default"))
298 {
299 return wd->label;
300 }
301 else if (!strcmp(item, "info"))
302 {
303 return wd->info;
304 }
305
306 return NULL;
307}
308
309EAPI Evas_Object *
310elm_bubble_add(Evas_Object *parent)
311{
312 Evas_Object *obj;
313 Evas *e;
314 Widget_Data *wd;
315
316 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
317
318 ELM_SET_WIDTYPE(widtype, "bubble");
319 elm_widget_type_set(obj, "bubble");
320 elm_widget_sub_object_add(parent, obj);
321 elm_widget_data_set(obj, wd);
322 elm_widget_del_hook_set(obj, _del_hook);
323 elm_widget_theme_hook_set(obj, _theme_hook);
324 elm_widget_focus_next_hook_set(obj, _elm_bubble_focus_next_hook);
325 elm_widget_can_focus_set(obj, EINA_FALSE);
326 elm_widget_text_set_hook_set(obj, _elm_bubble_label_set);
327 elm_widget_text_get_hook_set(obj, _elm_bubble_label_get);
328 elm_widget_content_set_hook_set(obj, _content_set_hook);
329 elm_widget_content_get_hook_set(obj, _content_get_hook);
330 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
331
332 wd->corner = eina_stringshare_add("base");
333 wd->pos = ELM_BUBBLE_POS_TOP_LEFT; //default
334
335 wd->bbl = edje_object_add(e);
336 elm_widget_resize_object_set(obj, wd->bbl);
337
338 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
339 evas_object_event_callback_add(wd->bbl, EVAS_CALLBACK_MOUSE_UP,
340 _mouse_up, obj);
341
342 evas_object_smart_callbacks_descriptions_set(obj, _signals);
343 _mirrored_set(obj, elm_widget_mirrored_get(obj));
344 _elm_theme_object_set(obj, wd->bbl, "bubble", wd->corner,
345 elm_widget_style_get(obj));
346 _sizing_eval(obj);
347 return obj;
348}
349
350EAPI void
351elm_bubble_pos_set(Evas_Object *obj, Elm_Bubble_Pos pos)
352{
353 ELM_CHECK_WIDTYPE(obj, widtype);
354 Widget_Data *wd = elm_widget_data_get(obj);
355 if (!wd) return;
356 if (pos<ELM_BUBBLE_POS_TOP_LEFT || pos>ELM_BUBBLE_POS_BOTTOM_RIGHT) return;
357 wd->pos = pos;
358 _theme_hook(obj);
359}
360
361EAPI Elm_Bubble_Pos
362elm_bubble_pos_get(const Evas_Object *obj)
363{
364 ELM_CHECK_WIDTYPE(obj, widtype) ELM_BUBBLE_POS_INVALID;
365 Widget_Data *wd = elm_widget_data_get(obj);
366 if (!wd) return ELM_BUBBLE_POS_INVALID;
367 return wd->pos;
368}
diff --git a/libraries/elementary/src/lib/elm_bubble.h b/libraries/elementary/src/lib/elm_bubble.h
new file mode 100644
index 0000000..9f97ec1
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_bubble.h
@@ -0,0 +1,111 @@
1/**
2 * @defgroup Bubble Bubble
3 * @ingroup Elementary
4 *
5 * @image html img/widget/bubble/preview-00.png
6 * @image latex img/widget/bubble/preview-00.eps
7 * @image html img/widget/bubble/preview-01.png
8 * @image latex img/widget/bubble/preview-01.eps
9 * @image html img/widget/bubble/preview-02.png
10 * @image latex img/widget/bubble/preview-02.eps
11 *
12 * @brief The Bubble is a widget to show text similar to how speech is
13 * represented in comics.
14 *
15 * The bubble widget contains 5 important visual elements:
16 * @li The frame is a rectangle with rounded edjes and an "arrow".
17 * @li The @p icon is an image to which the frame's arrow points to.
18 * @li The @p label is a text which appears to the right of the icon if the
19 * corner is "top_left" or "bottom_left" and is right aligned to the frame
20 * otherwise.
21 * @li The @p info is a text which appears to the right of the label. Info's
22 * font is of a lighter color than label.
23 * @li The @p content is an evas object that is shown inside the frame.
24 *
25 * The position of the arrow, icon, label and info depends on which corner is
26 * selected. The four available corners are:
27 * @li "top_left" - Default
28 * @li "top_right"
29 * @li "bottom_left"
30 * @li "bottom_right"
31 *
32 * Signals that you can add callbacks for are:
33 * @li "clicked" - This is called when a user has clicked the bubble.
34 *
35 * Default content parts of the bubble that you can use for are:
36 * @li "default" - A content of the bubble
37 * @li "icon" - An icon of the bubble
38 *
39 * Default text parts of the button widget that you can use for are:
40 * @li "default" - Label of the bubble
41 * @li "info" - info of the bubble
42 *
43 * Supported elm_object common APIs.
44 * @li @ref elm_object_part_text_set
45 * @li @ref elm_object_part_text_get
46 * @li @ref elm_object_part_content_set
47 * @li @ref elm_object_part_content_get
48 * @li @ref elm_object_part_content_unset
49 *
50 * For an example of using a bubble see @ref bubble_01_example_page "this".
51 *
52 * @{
53 */
54
55/**
56 * Defines the corner values for a bubble.
57 *
58 * The corner will be used to determine where the arrow of the
59 * bubble points to.
60 */
61typedef enum
62{
63 ELM_BUBBLE_POS_INVALID = -1,
64 ELM_BUBBLE_POS_TOP_LEFT,
65 ELM_BUBBLE_POS_TOP_RIGHT,
66 ELM_BUBBLE_POS_BOTTOM_LEFT,
67 ELM_BUBBLE_POS_BOTTOM_RIGHT,
68} Elm_Bubble_Pos;
69
70/**
71 * Add a new bubble to the parent
72 *
73 * @param parent The parent object
74 * @return The new object or NULL if it cannot be created
75 *
76 * This function adds a text bubble to the given parent evas object.
77 *
78 * @ingroup Bubble
79 */
80EAPI Evas_Object *elm_bubble_add(Evas_Object *parent);
81
82/**
83 * Set the corner of the bubble
84 *
85 * @param obj The bubble object.
86 * @param pos The given corner for the bubble.
87 *
88 * This function sets the corner of the bubble. The corner will be used to
89 * determine where the arrow in the frame points to and where label, icon and
90 * info are shown.
91 *
92 *
93 * @ingroup Bubble
94 */
95EAPI void elm_bubble_pos_set(Evas_Object *obj, Elm_Bubble_Pos pos);
96
97/**
98 * Get the corner of the bubble
99 *
100 * @param obj The bubble object.
101 * @return The given corner for the bubble.
102 *
103 * This function gets the selected corner of the bubble.
104 *
105 * @ingroup Bubble
106 */
107EAPI Elm_Bubble_Pos elm_bubble_pos_get(const Evas_Object *obj);
108
109/**
110 * @}
111 */
diff --git a/libraries/elementary/src/lib/elm_button.c b/libraries/elementary/src/lib/elm_button.c
new file mode 100644
index 0000000..be2506b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_button.c
@@ -0,0 +1,534 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *btn, *icon;
9 const char *label;
10 double ar_threshold;
11 double ar_interval;
12 Ecore_Timer *timer;
13 Eina_Bool autorepeat : 1;
14 Eina_Bool repeating : 1;
15 Eina_Bool delete_me : 1;
16};
17
18static const char *widtype = NULL;
19static void _del_hook(Evas_Object *obj);
20static void _del_pre_hook(Evas_Object *obj);
21static void _theme_hook(Evas_Object *obj);
22static void _disable_hook(Evas_Object *obj);
23static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
24static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
25static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
26static void _sizing_eval(Evas_Object *obj);
27static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
28static void _sub_del(void *data, Evas_Object *obj, void *event_info);
29static void _signal_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
30static void _signal_pressed(void *data, Evas_Object *obj, const char *emission, const char *source);
31static void _signal_unpressed(void *data, Evas_Object *obj, const char *emission, const char *source);
32static void _on_focus_hook(void *data, Evas_Object *obj);
33static void _activate(Evas_Object *obj);
34static void _activate_hook(Evas_Object *obj);
35static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
36 Evas_Callback_Type type, void *event_info);
37
38static const char SIG_CLICKED[] = "clicked";
39static const char SIG_REPEATED[] = "repeated";
40static const char SIG_PRESSED[] = "pressed";
41static const char SIG_UNPRESSED[] = "unpressed";
42static const Evas_Smart_Cb_Description _signals[] = {
43 {SIG_CLICKED, ""},
44 {SIG_REPEATED, ""},
45 {SIG_PRESSED, ""},
46 {SIG_UNPRESSED, ""},
47 {NULL, NULL}
48};
49
50static Eina_Bool
51_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
52{
53 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
54 Evas_Event_Key_Down *ev = event_info;
55 Widget_Data *wd = elm_widget_data_get(obj);
56 if (!wd) return EINA_FALSE;
57 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
58 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
59 if ((strcmp(ev->keyname, "Return")) &&
60 (strcmp(ev->keyname, "KP_Enter")) &&
61 (strcmp(ev->keyname, "space")))
62 return EINA_FALSE;
63 _activate(obj);
64 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
65 edje_object_signal_emit(wd->btn, "elm,anim,activate", "elm");
66 return EINA_TRUE;
67}
68
69static void
70_del_pre_hook(Evas_Object *obj)
71{
72 Widget_Data *wd = elm_widget_data_get(obj);
73 if (!wd) return;
74 wd->delete_me = EINA_TRUE;
75}
76
77static void
78_del_hook(Evas_Object *obj)
79{
80 Widget_Data *wd = elm_widget_data_get(obj);
81 if (!wd) return;
82 if (wd->label) eina_stringshare_del(wd->label);
83 free(wd);
84}
85
86static void
87_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
88{
89 Widget_Data *wd = elm_widget_data_get(obj);
90 if (!wd) return;
91 if (elm_widget_focus_get(obj))
92 {
93 edje_object_signal_emit(wd->btn, "elm,action,focus", "elm");
94 evas_object_focus_set(wd->btn, EINA_TRUE);
95 }
96 else
97 {
98 edje_object_signal_emit(wd->btn, "elm,action,unfocus", "elm");
99 evas_object_focus_set(wd->btn, EINA_FALSE);
100 }
101}
102
103static void
104_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
105{
106 Widget_Data *wd = elm_widget_data_get(obj);
107 if (!wd) return;
108 edje_object_mirrored_set(wd->btn, rtl);
109}
110
111static void
112_theme_hook(Evas_Object *obj)
113{
114 Widget_Data *wd = elm_widget_data_get(obj);
115 const char *str;
116 if (!wd) return;
117 _elm_widget_mirrored_reload(obj);
118 _mirrored_set(obj, elm_widget_mirrored_get(obj));
119 _elm_theme_object_set(obj, wd->btn, "button", "base", elm_widget_style_get(obj));
120 if (wd->icon)
121 edje_object_part_swallow(wd->btn, "elm.swallow.content", wd->icon);
122 if (wd->label)
123 edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
124 else
125 edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
126 if (wd->icon)
127 edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
128 else
129 edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
130 edje_object_part_text_escaped_set(wd->btn, "elm.text", wd->label);
131 if (elm_object_disabled_get(obj))
132 edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
133 edje_object_message_signal_process(wd->btn);
134 edje_object_scale_set(wd->btn, elm_widget_scale_get(obj) * _elm_config->scale);
135 str = edje_object_data_get(wd->btn, "focus_highlight");
136 if ((str) && (!strcmp(str, "on")))
137 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
138 else
139 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
140 _sizing_eval(obj);
141}
142
143static void
144_disable_hook(Evas_Object *obj)
145{
146 Widget_Data *wd = elm_widget_data_get(obj);
147 if (!wd) return;
148 if (elm_widget_disabled_get(obj))
149 edje_object_signal_emit(wd->btn, "elm,state,disabled", "elm");
150 else
151 edje_object_signal_emit(wd->btn, "elm,state,enabled", "elm");
152}
153
154static void
155_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
156{
157 Widget_Data *wd = elm_widget_data_get(obj);
158 if (!wd) return;
159 edje_object_signal_emit(wd->btn, emission, source);
160}
161
162static void
163_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
164{
165 Widget_Data *wd = elm_widget_data_get(obj);
166 if (!wd) return;
167 edje_object_signal_callback_add(wd->btn, emission, source, func_cb, data);
168}
169
170static void
171_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
172{
173 Widget_Data *wd = elm_widget_data_get(obj);
174 edje_object_signal_callback_del_full(wd->btn, emission, source, func_cb,
175 data);
176}
177
178static void
179_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
180{
181 ELM_CHECK_WIDTYPE(obj, widtype);
182 Widget_Data *wd = elm_widget_data_get(obj);
183 if (!wd) return;
184 if (part && strcmp(part, "icon")) return;
185 if (wd->icon == content) return;
186 if (wd->icon) evas_object_del(wd->icon);
187 wd->icon = content;
188 if (content)
189 {
190 elm_widget_sub_object_add(obj, content);
191 evas_object_event_callback_add(content,
192 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
193 _changed_size_hints, obj);
194 edje_object_part_swallow(wd->btn, "elm.swallow.content", content);
195 edje_object_signal_emit(wd->btn, "elm,state,icon,visible", "elm");
196 edje_object_message_signal_process(wd->btn);
197 }
198 _sizing_eval(obj);
199}
200
201static Evas_Object *
202_content_get_hook(const Evas_Object *obj, const char *part)
203{
204 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
205 Widget_Data *wd;
206
207 if (part && strcmp(part, "icon")) return NULL;
208 wd = elm_widget_data_get(obj);
209 if (!wd) return NULL;
210 return wd->icon;
211}
212
213static Evas_Object *
214_content_unset_hook(Evas_Object *obj, const char *part)
215{
216 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
217 Widget_Data *wd;
218
219 if (part && strcmp(part, "icon")) return NULL;
220 wd = elm_widget_data_get(obj);
221 if (!wd) return NULL;
222 if (!wd->icon) return NULL;
223 Evas_Object *icon = wd->icon;
224 elm_widget_sub_object_del(obj, wd->icon);
225 edje_object_part_unswallow(wd->btn, icon);
226 return icon;
227}
228
229static void
230_sizing_eval(Evas_Object *obj)
231{
232 Widget_Data *wd = elm_widget_data_get(obj);
233 Evas_Coord minw = -1, minh = -1;
234
235 if (!wd) return;
236 if (wd->delete_me) return;
237 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
238 edje_object_size_min_restricted_calc(wd->btn, &minw, &minh, minw, minh);
239 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
240 evas_object_size_hint_min_set(obj, minw, minh);
241}
242
243static void
244_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
245{
246 Widget_Data *wd = elm_widget_data_get(data);
247 if (!wd) return;
248 if (obj != wd->icon) return;
249 _sizing_eval(data);
250}
251
252static void
253_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
254{
255 Widget_Data *wd = elm_widget_data_get(obj);
256 Evas_Object *sub = event_info;
257 if (!wd) return;
258 if (sub == wd->icon)
259 {
260 edje_object_signal_emit(wd->btn, "elm,state,icon,hidden", "elm");
261 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
262 _changed_size_hints, obj);
263 wd->icon = NULL;
264 edje_object_message_signal_process(wd->btn);
265 _sizing_eval(obj);
266 }
267}
268
269static void
270_activate(Evas_Object *obj)
271{
272 Widget_Data *wd = elm_widget_data_get(obj);
273 if (!wd) return;
274 if (wd->timer)
275 {
276 ecore_timer_del(wd->timer);
277 wd->timer = NULL;
278 }
279 wd->repeating = EINA_FALSE;
280 if ((_elm_config->access_mode == ELM_ACCESS_MODE_OFF) ||
281 (_elm_access_2nd_click_timeout(obj)))
282 {
283 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
284 _elm_access_say(E_("Clicked"));
285 if (!elm_widget_disabled_get(obj) &&
286 !evas_object_freeze_events_get(obj))
287 evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
288 }
289}
290
291static void
292_activate_hook(Evas_Object *obj)
293{
294 _activate(obj);
295}
296
297static void
298_signal_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
299{
300 _activate(data);
301}
302
303static Eina_Bool
304_autorepeat_send(void *data)
305{
306 Widget_Data *wd = elm_widget_data_get(data);
307 if (!wd) return ECORE_CALLBACK_CANCEL;
308
309 evas_object_smart_callback_call(data, SIG_REPEATED, NULL);
310 if (!wd->repeating)
311 {
312 wd->timer = NULL;
313 return ECORE_CALLBACK_CANCEL;
314 }
315
316 return ECORE_CALLBACK_RENEW;
317}
318
319static Eina_Bool
320_autorepeat_initial_send(void *data)
321{
322 Widget_Data *wd = elm_widget_data_get(data);
323 if (!wd) return ECORE_CALLBACK_CANCEL;
324
325 if (wd->timer) ecore_timer_del(wd->timer);
326 wd->repeating = EINA_TRUE;
327 _autorepeat_send(data);
328 wd->timer = ecore_timer_add(wd->ar_interval, _autorepeat_send, data);
329
330 return ECORE_CALLBACK_CANCEL;
331}
332
333static void
334_signal_pressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
335{
336 Widget_Data *wd = elm_widget_data_get(data);
337 if (!wd) return;
338
339 if ((wd->autorepeat) && (!wd->repeating))
340 {
341 if (wd->ar_threshold <= 0.0)
342 _autorepeat_initial_send(data); /* call immediately */
343 else
344 wd->timer = ecore_timer_add(wd->ar_threshold, _autorepeat_initial_send, data);
345 }
346
347 evas_object_smart_callback_call(data, SIG_PRESSED, NULL);
348}
349
350static void
351_signal_unpressed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
352{
353 Widget_Data *wd = elm_widget_data_get(data);
354 if (!wd) return;
355
356 if (wd->timer)
357 {
358 ecore_timer_del(wd->timer);
359 wd->timer = NULL;
360 }
361 wd->repeating = EINA_FALSE;
362 evas_object_smart_callback_call(data, SIG_UNPRESSED, NULL);
363}
364
365static void
366_elm_button_label_set(Evas_Object *obj, const char *item, const char *label)
367{
368 ELM_CHECK_WIDTYPE(obj, widtype);
369 Widget_Data *wd = elm_widget_data_get(obj);
370 if (item && strcmp(item, "default")) return;
371 if (!wd) return;
372 eina_stringshare_replace(&wd->label, label);
373 if (label)
374 edje_object_signal_emit(wd->btn, "elm,state,text,visible", "elm");
375 else
376 edje_object_signal_emit(wd->btn, "elm,state,text,hidden", "elm");
377 edje_object_message_signal_process(wd->btn);
378 edje_object_part_text_escaped_set(wd->btn, "elm.text", label);
379 _sizing_eval(obj);
380}
381
382static const char *
383_elm_button_label_get(const Evas_Object *obj, const char *item)
384{
385 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
386 Widget_Data *wd = elm_widget_data_get(obj);
387 if (item && strcmp(item, "default")) return NULL;
388 if (!wd) return NULL;
389 return wd->label;
390}
391
392static char *
393_access_info_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Widget_Item *item __UNUSED__)
394{
395 const char *txt = elm_widget_access_info_get(obj);
396 if (!txt) txt = _elm_button_label_get(obj, NULL);
397 if (txt) return strdup(txt);
398 return NULL;
399}
400
401static char *
402_access_state_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Widget_Item *item __UNUSED__)
403{
404 if (elm_widget_disabled_get(obj))
405 return strdup(E_("State: Disabled"));
406 return NULL;
407}
408
409EAPI Evas_Object *
410elm_button_add(Evas_Object *parent)
411{
412 Evas_Object *obj;
413 Evas *e;
414 Widget_Data *wd;
415
416 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
417
418 ELM_SET_WIDTYPE(widtype, "button");
419 elm_widget_type_set(obj, "button");
420 elm_widget_sub_object_add(parent, obj);
421 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
422 elm_widget_data_set(obj, wd);
423 elm_widget_del_hook_set(obj, _del_hook);
424 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
425 elm_widget_theme_hook_set(obj, _theme_hook);
426 elm_widget_disable_hook_set(obj, _disable_hook);
427 elm_widget_can_focus_set(obj, EINA_TRUE);
428 elm_widget_activate_hook_set(obj, _activate_hook);
429 elm_widget_event_hook_set(obj, _event_hook);
430 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
431 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
432 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
433 elm_widget_text_set_hook_set(obj, _elm_button_label_set);
434 elm_widget_text_get_hook_set(obj, _elm_button_label_get);
435 elm_widget_content_set_hook_set(obj, _content_set_hook);
436 elm_widget_content_get_hook_set(obj, _content_get_hook);
437 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
438
439 wd->btn = edje_object_add(e);
440 _elm_theme_object_set(obj, wd->btn, "button", "base", "default");
441 edje_object_signal_callback_add(wd->btn, "elm,action,click", "",
442 _signal_clicked, obj);
443 edje_object_signal_callback_add(wd->btn, "elm,action,press", "",
444 _signal_pressed, obj);
445 edje_object_signal_callback_add(wd->btn, "elm,action,unpress", "",
446 _signal_unpressed, obj);
447 elm_widget_resize_object_set(obj, wd->btn);
448
449 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
450
451 _theme_hook(obj);
452
453 // TODO: convert Elementary to subclassing of Evas_Smart_Class
454 // TODO: and save some bytes, making descriptions per-class and not instance!
455 evas_object_smart_callbacks_descriptions_set(obj, _signals);
456
457 _elm_access_object_register(obj, wd->btn);
458 _elm_access_text_set(_elm_access_object_get(obj),
459 ELM_ACCESS_TYPE, E_("Button"));
460 _elm_access_callback_set(_elm_access_object_get(obj),
461 ELM_ACCESS_INFO, _access_info_cb, obj);
462 _elm_access_callback_set(_elm_access_object_get(obj),
463 ELM_ACCESS_STATE, _access_state_cb, obj);
464 return obj;
465}
466
467EAPI void
468elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on)
469{
470 ELM_CHECK_WIDTYPE(obj, widtype);
471 Widget_Data *wd = elm_widget_data_get(obj);
472 if (!wd) return;
473 if (wd->timer)
474 {
475 ecore_timer_del(wd->timer);
476 wd->timer = NULL;
477 }
478 wd->autorepeat = on;
479 wd->repeating = EINA_FALSE;
480}
481
482EAPI Eina_Bool
483elm_button_autorepeat_get(const Evas_Object *obj)
484{
485 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
486 Widget_Data *wd = elm_widget_data_get(obj);
487 if (!wd) return EINA_FALSE;
488 return wd->autorepeat;
489}
490
491EAPI void
492elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t)
493{
494 ELM_CHECK_WIDTYPE(obj, widtype);
495 Widget_Data *wd = elm_widget_data_get(obj);
496 if (!wd) return;
497 if (wd->ar_threshold == t) return;
498 if (wd->timer)
499 {
500 ecore_timer_del(wd->timer);
501 wd->timer = NULL;
502 }
503 wd->ar_threshold = t;
504}
505
506EAPI double
507elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj)
508{
509 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
510 Widget_Data *wd = elm_widget_data_get(obj);
511 if (!wd) return 0.0;
512 return wd->ar_threshold;
513}
514
515EAPI void
516elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t)
517{
518 ELM_CHECK_WIDTYPE(obj, widtype);
519 Widget_Data *wd = elm_widget_data_get(obj);
520 if (!wd) return;
521 if (wd->ar_interval == t) return;
522
523 wd->ar_interval = t;
524 if ((wd->repeating) && (wd->timer)) ecore_timer_interval_set(wd->timer, t);
525}
526
527EAPI double
528elm_button_autorepeat_gap_timeout_get(const Evas_Object *obj)
529{
530 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
531 Widget_Data *wd = elm_widget_data_get(obj);
532 if (!wd) return 0.0;
533 return wd->ar_interval;
534}
diff --git a/libraries/elementary/src/lib/elm_button.h b/libraries/elementary/src/lib/elm_button.h
new file mode 100644
index 0000000..5893898
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_button.h
@@ -0,0 +1,159 @@
1/**
2 * @defgroup Button Button
3 * @ingroup Elementary
4 *
5 * @image html img/widget/button/preview-00.png
6 * @image latex img/widget/button/preview-00.eps
7 * @image html img/widget/button/preview-01.png
8 * @image latex img/widget/button/preview-01.eps
9 * @image html img/widget/button/preview-02.png
10 * @image latex img/widget/button/preview-02.eps
11 *
12 * This is a push-button. Press it and run some function. It can contain
13 * a simple label and icon object and it also has an autorepeat feature.
14 *
15 * This widget emits the following signals:
16 * @li "clicked": the user clicked the button (press/release).
17 * @li "repeated": the user pressed the button without releasing it.
18 * @li "pressed": button was pressed.
19 * @li "unpressed": button was released after being pressed.
20 * In all cases, the @c event parameter of the callback will be
21 * @c NULL.
22 *
23 * Also, defined in the default theme, the button has the following styles
24 * available:
25 * @li default: a normal button.
26 * @li anchor: Like default, but the button fades away when the mouse is not
27 * over it, leaving only the text or icon.
28 * @li hoversel_vertical: Internally used by @ref Hoversel to give a
29 * continuous look across its options.
30 * @li hoversel_vertical_entry: Another internal for @ref Hoversel.
31 * @li naviframe: Internally used by @ref Naviframe for its back button.
32 * @li colorselector: Internally used by @ref Colorselector
33 * for its left and right buttons.
34 *
35 * Default content parts of the button widget that you can use for are:
36 * @li "icon" - An icon of the button
37 *
38 * Default text parts of the button widget that you can use for are:
39 * @li "default" - Label of the button
40 *
41 * Supported elm_object common APIs.
42 * @li @ref elm_object_part_text_set
43 * @li @ref elm_object_part_text_get
44 * @li @ref elm_object_part_content_set
45 * @li @ref elm_object_part_content_get
46 * @li @ref elm_object_part_content_unset
47 * @li @ref elm_object_signal_emit
48 * @li @ref elm_object_signal_callback_add
49 * @li @ref elm_object_signal_callback_del
50 *
51 * Here is some sample code using it:
52 * @li @ref button_example_00
53 * @li @ref button_example_01
54 */
55
56/**
57 * @addtogroup Button
58 * @{
59 */
60
61/**
62 * Add a new button to the parent's canvas
63 *
64 * @param parent The parent object
65 * @return The new object or NULL if it cannot be created
66 *
67 * @ingroup Button
68 */
69EAPI Evas_Object *elm_button_add(Evas_Object *parent);
70
71/**
72 * Turn on/off the autorepeat event generated when the button is kept pressed
73 *
74 * When off, no autorepeat is performed and buttons emit a normal @c clicked
75 * signal when they are clicked.
76 *
77 * When on, keeping a button pressed will continuously emit a @c repeated
78 * signal until the button is released. The time it takes until it starts
79 * emitting the signal is given by
80 * elm_button_autorepeat_initial_timeout_set(), and the time between each
81 * new emission by elm_button_autorepeat_gap_timeout_set().
82 *
83 * @param obj The button object
84 * @param on A bool to turn on/off the event
85 *
86 * @ingroup Button
87 */
88EAPI void elm_button_autorepeat_set(Evas_Object *obj, Eina_Bool on);
89
90/**
91 * Get whether the autorepeat feature is enabled
92 *
93 * @param obj The button object
94 * @return EINA_TRUE if autorepeat is on, EINA_FALSE otherwise
95 *
96 * @see elm_button_autorepeat_set()
97 *
98 * @ingroup Button
99 */
100EAPI Eina_Bool elm_button_autorepeat_get(const Evas_Object *obj);
101
102/**
103 * Set the initial timeout before the autorepeat event is generated
104 *
105 * Sets the timeout, in seconds, since the button is pressed until the
106 * first @c repeated signal is emitted. If @p t is 0.0 or less, there
107 * won't be any delay and the event will be fired the moment the button is
108 * pressed.
109 *
110 * @param obj The button object
111 * @param t Timeout in seconds
112 *
113 * @see elm_button_autorepeat_set()
114 * @see elm_button_autorepeat_gap_timeout_set()
115 *
116 * @ingroup Button
117 */
118EAPI void elm_button_autorepeat_initial_timeout_set(Evas_Object *obj, double t);
119
120/**
121 * Get the initial timeout before the autorepeat event is generated
122 *
123 * @param obj The button object
124 * @return Timeout in seconds
125 *
126 * @see elm_button_autorepeat_initial_timeout_set()
127 *
128 * @ingroup Button
129 */
130EAPI double elm_button_autorepeat_initial_timeout_get(const Evas_Object *obj);
131
132/**
133 * Set the interval between each generated autorepeat event
134 *
135 * After the first @c repeated event is fired, all subsequent ones will
136 * follow after a delay of @p t seconds for each.
137 *
138 * @param obj The button object
139 * @param t Interval in seconds
140 *
141 * @see elm_button_autorepeat_initial_timeout_set()
142 *
143 * @ingroup Button
144 */
145EAPI void elm_button_autorepeat_gap_timeout_set(Evas_Object *obj, double t);
146
147/**
148 * Get the interval between each generated autorepeat event
149 *
150 * @param obj The button object
151 * @return Interval in seconds
152 *
153 * @ingroup Button
154 */
155EAPI double elm_button_autorepeat_gap_timeout_get(const Evas_Object *obj);
156
157/**
158 * @}
159 */
diff --git a/libraries/elementary/src/lib/elm_cache.h b/libraries/elementary/src/lib/elm_cache.h
new file mode 100644
index 0000000..7546f6b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_cache.h
@@ -0,0 +1,31 @@
1/**
2 * @defgroup Caches Caches
3 * @ingroup Elementary
4 *
5 * These are functions which let one fine-tune some cache values for
6 * Elementary applications, thus allowing for performance adjustments.
7 *
8 * @{
9 */
10
11/**
12 * @brief Flush all caches.
13 *
14 * Frees all data that was in cache and is not currently being used to reduce
15 * memory usage. This frees Edje's, Evas' and Eet's cache. This is equivalent
16 * to calling all of the following functions:
17 * @li edje_file_cache_flush()
18 * @li edje_collection_cache_flush()
19 * @li eet_clearcache()
20 * @li evas_image_cache_flush()
21 * @li evas_font_cache_flush()
22 * @li evas_render_dump()
23 * @note Evas caches are flushed for every canvas associated with a window.
24 *
25 * @ingroup Caches
26 */
27EAPI void elm_cache_all_flush(void);
28
29/**
30 * @}
31 */
diff --git a/libraries/elementary/src/lib/elm_calendar.c b/libraries/elementary/src/lib/elm_calendar.c
new file mode 100644
index 0000000..2e41c5f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_calendar.c
@@ -0,0 +1,1029 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#include <Elementary.h>
10#include "elm_priv.h"
11
12typedef enum _Day_Color // EINA_DEPRECATED
13{
14 DAY_WEEKDAY = 0,
15 DAY_SATURDAY = 1,
16 DAY_SUNDAY = 2
17} Day_Color;
18
19typedef struct _Widget_Data Widget_Data;
20
21struct _Widget_Data
22{
23 Evas_Object *calendar;
24 Eina_List *marks;
25 double interval, first_interval;
26 int year_min, year_max, spin_speed;
27 int today_it, selected_it, first_day_it;
28 Elm_Calendar_Weekday first_week_day;
29 Ecore_Timer *spin, *update_timer;
30 Elm_Calendar_Format_Cb format_func;
31 const char *weekdays[ELM_DAY_LAST];
32 struct tm current_time, selected_time;
33 Day_Color day_color[42]; // EINA_DEPRECATED
34 Elm_Calendar_Select_Mode select_mode;
35};
36
37struct _Elm_Calendar_Mark
38{
39 Evas_Object *obj;
40 Eina_List *node;
41 struct tm mark_time;
42 const char *mark_type;
43 Elm_Calendar_Mark_Repeat_Type repeat;
44};
45
46static const char *widtype = NULL;
47static void _on_focus_hook(void *data, Evas_Object *obj);
48static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
49
50static const char SIG_CHANGED[] = "changed";
51
52static const Evas_Smart_Cb_Description _signals[] = {
53 {SIG_CHANGED, ""},
54 {NULL, NULL}
55};
56
57
58/* Should not be translated, it's used if we failed
59 * getting from locale. */
60static const char *_days_abbrev[] =
61{
62 "Sun", "Mon", "Tue", "Wed",
63 "Thu", "Fri", "Sat"
64};
65
66static int _days_in_month[2][12] =
67{
68 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
69 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
70};
71
72static Elm_Calendar_Mark *
73_mark_new(Evas_Object *obj, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat_Type repeat)
74{
75 Widget_Data *wd = elm_widget_data_get(obj);
76 Elm_Calendar_Mark *mark;
77
78 if (!wd) return NULL;
79 mark = calloc(1, sizeof(Elm_Calendar_Mark));
80 if (!mark) return NULL;
81 mark->obj = obj;
82 mark->mark_type = eina_stringshare_add(mark_type);
83 mark->mark_time = *mark_time;
84 mark->repeat = repeat;
85 return mark;
86}
87
88static inline void
89_mark_free(Elm_Calendar_Mark *mark)
90{
91 eina_stringshare_del(mark->mark_type);
92 free(mark);
93}
94
95static void
96_sizing_eval(Evas_Object *obj)
97{
98 Widget_Data *wd = elm_widget_data_get(obj);
99 Evas_Coord minw = -1, minh = -1;
100 if (!wd) return;
101 elm_coords_finger_size_adjust(8, &minw, 7, &minh);
102 edje_object_size_min_restricted_calc(wd->calendar, &minw, &minh, minw, minh);
103 evas_object_size_hint_min_set(obj, minw, minh);
104 evas_object_size_hint_max_set(obj, -1, -1);
105}
106
107static inline int
108_maxdays_get(struct tm *selected_time)
109{
110 int month, year;
111
112 month = selected_time->tm_mon;
113 year = selected_time->tm_year + 1900;
114
115 return _days_in_month[((!(year % 4)) &&
116 ((!(year % 400)) ||
117 (year % 100)))]
118 [month];
119}
120
121static inline void
122_unselect(Widget_Data *wd, int selected)
123{
124 char emission[32];
125 snprintf(emission, sizeof(emission), "cit_%i,unselected", selected);
126 edje_object_signal_emit(wd->calendar, emission, "elm");
127}
128
129static inline void
130_select(Widget_Data *wd, int selected)
131{
132 char emission[32];
133 snprintf(emission, sizeof(emission), "cit_%i,selected", selected);
134 edje_object_signal_emit(wd->calendar, emission, "elm");
135}
136
137static inline void
138_not_today(Widget_Data *wd)
139{
140 char emission[32];
141 snprintf(emission, sizeof(emission), "cit_%i,not_today", wd->today_it);
142 edje_object_signal_emit(wd->calendar, emission, "elm");
143 wd->today_it = -1;
144}
145
146static inline void
147_today(Widget_Data *wd, int it)
148{
149 char emission[32];
150 snprintf(emission, sizeof(emission), "cit_%i,today", it);
151 edje_object_signal_emit(wd->calendar, emission, "elm");
152 wd->today_it = it;
153}
154
155static char *
156_format_month_year(struct tm *selected_time)
157{
158 char buf[32];
159 if (!strftime(buf, sizeof(buf), E_("%B %Y"), selected_time)) return NULL;
160 return strdup(buf);
161}
162
163static inline void
164_cit_mark(Evas_Object *cal, int cit, const char *mtype)
165{
166 char sign[64];
167 snprintf(sign, sizeof(sign), "cit_%i,%s", cit, mtype);
168 edje_object_signal_emit(cal, sign, "elm");
169}
170
171static inline int
172_weekday_get(int first_week_day, int day)
173{
174 return (day + first_week_day - 1) % ELM_DAY_LAST;
175}
176
177// EINA_DEPRECATED
178static void
179_text_day_color_update(Widget_Data *wd, int pos)
180{
181 char emission[32];
182
183 switch (wd->day_color[pos])
184 {
185 case DAY_WEEKDAY:
186 snprintf(emission, sizeof(emission), "cit_%i,weekday", pos);
187 break;
188 case DAY_SATURDAY:
189 snprintf(emission, sizeof(emission), "cit_%i,saturday", pos);
190 break;
191 case DAY_SUNDAY:
192 snprintf(emission, sizeof(emission), "cit_%i,sunday", pos);
193 break;
194 default:
195 return;
196 }
197
198 edje_object_signal_emit(wd->calendar, emission, "elm");
199}
200
201static void
202_set_month_year(Widget_Data *wd)
203{
204 char *buf;
205
206 /* Set selected month */
207 buf = wd->format_func(&wd->selected_time);
208 if (buf)
209 {
210 edje_object_part_text_escaped_set(wd->calendar, "month_text", buf);
211 free(buf);
212 }
213 else
214 edje_object_part_text_escaped_set(wd->calendar, "month_text", "");
215}
216
217static void
218_populate(Evas_Object *obj)
219{
220 int maxdays, day, mon, yr, i;
221 Elm_Calendar_Mark *mark;
222 char part[12], day_s[3];
223 struct tm first_day;
224 Eina_List *l;
225 Eina_Bool last_row = EINA_TRUE;
226 Widget_Data *wd = elm_widget_data_get(obj);
227
228 if (!wd) return;
229
230 if (wd->today_it > 0) _not_today(wd);
231
232 maxdays = _maxdays_get(&wd->selected_time);
233 mon = wd->selected_time.tm_mon;
234 yr = wd->selected_time.tm_year;
235
236 _set_month_year(wd);
237
238 /* Set days */
239 day = 0;
240 first_day = wd->selected_time;
241 first_day.tm_mday = 1;
242 mktime(&first_day);
243
244 // Layout of the calendar is changed for removing the unfilled last row.
245 if (first_day.tm_wday < (int)wd->first_week_day)
246 wd->first_day_it = first_day.tm_wday + ELM_DAY_LAST - wd->first_week_day;
247 else
248 wd->first_day_it = first_day.tm_wday - wd->first_week_day;
249
250 if ((35 - wd->first_day_it) > (maxdays - 1)) last_row = EINA_FALSE;
251
252 if (!last_row)
253 {
254 char emission[32];
255
256 for (i = 0; i < 5; i++)
257 {
258 snprintf(emission, sizeof(emission), "cseph_%i,row_hide", i);
259 edje_object_signal_emit(wd->calendar, emission, "elm");
260 }
261 snprintf(emission, sizeof(emission), "cseph_%i,row_invisible", 5);
262 edje_object_signal_emit(wd->calendar, emission, "elm");
263 for (i = 0; i < 35; i++)
264 {
265 snprintf(emission, sizeof(emission), "cit_%i,cell_expanded", i);
266 edje_object_signal_emit(wd->calendar, emission, "elm");
267 }
268 for (i = 35; i < 42; i++)
269 {
270 snprintf(emission, sizeof(emission), "cit_%i,cell_invisible", i);
271 edje_object_signal_emit(wd->calendar, emission, "elm");
272 }
273 }
274 else
275 {
276 char emission[32];
277
278 for (i = 0; i < 6; i++)
279 {
280 snprintf(emission, sizeof(emission), "cseph_%i,row_show", i);
281 edje_object_signal_emit(wd->calendar, emission, "elm");
282 }
283 for (i = 0; i < 42; i++)
284 {
285 snprintf(emission, sizeof(emission), "cit_%i,cell_default", i);
286 edje_object_signal_emit(wd->calendar, emission, "elm");
287 }
288 }
289
290 for (i = 0; i < 42; i++)
291 {
292 _text_day_color_update(wd, i); // EINA_DEPRECATED
293 if ((!day) && (i == wd->first_day_it)) day = 1;
294
295 if ((day == wd->current_time.tm_mday)
296 && (mon == wd->current_time.tm_mon)
297 && (yr == wd->current_time.tm_year))
298 _today(wd, i);
299
300 if (day == wd->selected_time.tm_mday)
301 {
302 if ((wd->selected_it > -1) && (wd->selected_it != i))
303 _unselect(wd, wd->selected_it);
304
305 if (wd->select_mode != ELM_CALENDAR_SELECT_MODE_NONE)
306 _select(wd, i);
307
308 wd->selected_it = i;
309 }
310
311 if ((day) && (day <= maxdays))
312 snprintf(day_s, sizeof(day_s), "%i", day++);
313 else
314 day_s[0] = 0;
315
316 snprintf(part, sizeof(part), "cit_%i.text", i);
317 edje_object_part_text_set(wd->calendar, part, day_s);
318 /* Clear previous marks */
319 _cit_mark(wd->calendar, i, "clear");
320 }
321
322 /* Set marks */
323 EINA_LIST_FOREACH(wd->marks, l, mark)
324 {
325 struct tm *mtime = &mark->mark_time;
326 int month = wd->selected_time.tm_mon;
327 int year = wd->selected_time.tm_year;
328 int mday_it = mtime->tm_mday + wd->first_day_it - 1;
329
330 switch (mark->repeat)
331 {
332 case ELM_CALENDAR_UNIQUE:
333 if ((mtime->tm_mon == month) && (mtime->tm_year == year))
334 _cit_mark(wd->calendar, mday_it, mark->mark_type);
335 break;
336 case ELM_CALENDAR_DAILY:
337 if (((mtime->tm_year == year) && (mtime->tm_mon < month)) ||
338 (mtime->tm_year < year))
339 day = 1;
340 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
341 day = mtime->tm_mday;
342 else
343 break;
344 for (; day <= maxdays; day++)
345 _cit_mark(wd->calendar, day + wd->first_day_it - 1,
346 mark->mark_type);
347 break;
348 case ELM_CALENDAR_WEEKLY:
349 if (((mtime->tm_year == year) && (mtime->tm_mon < month)) ||
350 (mtime->tm_year < year))
351 day = 1;
352 else if ((mtime->tm_year == year) && (mtime->tm_mon == month))
353 day = mtime->tm_mday;
354 else
355 break;
356 for (; day <= maxdays; day++)
357 if (mtime->tm_wday == _weekday_get(wd->first_day_it, day))
358 _cit_mark(wd->calendar, day + wd->first_day_it - 1,
359 mark->mark_type);
360 break;
361 case ELM_CALENDAR_MONTHLY:
362 if (((mtime->tm_year < year) ||
363 ((mtime->tm_year == year) && (mtime->tm_mon <= month))) &&
364 (mtime->tm_mday <= maxdays))
365 _cit_mark(wd->calendar, mday_it, mark->mark_type);
366 break;
367 case ELM_CALENDAR_ANNUALLY:
368 if ((mtime->tm_year <= year) && (mtime->tm_mon == month) &&
369 (mtime->tm_mday <= maxdays))
370 _cit_mark(wd->calendar, mday_it, mark->mark_type);
371 break;
372 }
373 }
374}
375
376static void
377_set_headers(Evas_Object *obj)
378{
379 static char part[] = "ch_0.text";
380 int i;
381 Widget_Data *wd = elm_widget_data_get(obj);
382 if (!wd) return;
383
384 for (i = 0; i < ELM_DAY_LAST; i++)
385 {
386 part[3] = i + '0';
387 edje_object_part_text_escaped_set
388 (wd->calendar, part,
389 wd->weekdays[(i + wd->first_week_day) % ELM_DAY_LAST]);
390 }
391}
392
393static void
394_del_hook(Evas_Object *obj)
395{
396 int i;
397 Elm_Calendar_Mark *mark;
398 Widget_Data *wd = elm_widget_data_get(obj);
399
400 if (!wd) return;
401
402 if (wd->spin) ecore_timer_del(wd->spin);
403 if (wd->update_timer) ecore_timer_del(wd->update_timer);
404
405 if (wd->marks)
406 {
407 EINA_LIST_FREE(wd->marks, mark)
408 {
409 _mark_free(mark);
410 }
411 }
412
413 for (i = 0; i < ELM_DAY_LAST; i++)
414 eina_stringshare_del(wd->weekdays[i]);
415
416 free(wd);
417}
418
419static void
420_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
421{
422 Widget_Data *wd = elm_widget_data_get(obj);
423 if (!wd) return;
424 if (elm_widget_focus_get(obj))
425 {
426 edje_object_signal_emit(wd->calendar, "elm,action,focus", "elm");
427 evas_object_focus_set(wd->calendar, EINA_TRUE);
428 }
429 else
430 {
431 edje_object_signal_emit(wd->calendar, "elm,action,unfocus", "elm");
432 evas_object_focus_set(wd->calendar, EINA_FALSE);
433 }
434}
435
436static void
437_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
438{
439 Widget_Data *wd = elm_widget_data_get(obj);
440 if (!wd) return;
441 edje_object_mirrored_set(wd->calendar, rtl);
442}
443
444static void
445_theme_hook(Evas_Object *obj)
446{
447 Widget_Data *wd = elm_widget_data_get(obj);
448 if (!wd) return;
449 _elm_widget_mirrored_reload(obj);
450 _elm_theme_object_set(obj, wd->calendar, "calendar", "base",
451 elm_widget_style_get(obj));
452 _mirrored_set(obj, elm_widget_mirrored_get(obj));
453 _set_headers(obj);
454 _populate(obj);
455 edje_object_message_signal_process(wd->calendar);
456 edje_object_scale_set(wd->calendar,
457 elm_widget_scale_get(obj) * _elm_config->scale);
458 _sizing_eval(obj);
459}
460
461static void
462_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
463{
464 Widget_Data *wd = elm_widget_data_get(obj);
465 if (!wd) return;
466 edje_object_signal_emit(wd->calendar, emission, source);
467}
468
469static void
470_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
471{
472 Widget_Data *wd = elm_widget_data_get(obj);
473 if (!wd) return;
474 edje_object_signal_callback_add(wd->calendar, emission,
475 source, func_cb, data);
476}
477
478static void
479_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
480{
481 Widget_Data *wd = elm_widget_data_get(obj);
482 if (!wd) return;
483 edje_object_signal_callback_del_full(wd->calendar, emission, source, func_cb,
484 data);
485}
486
487/* Set correct tm_wday and tm_yday after other fields changes*/
488static inline void
489_fix_selected_time(Widget_Data *wd)
490{
491 mktime(&wd->selected_time);
492}
493
494static Eina_Bool
495_update_month(Evas_Object *obj, int delta)
496{
497 struct tm time_check;
498 int maxdays;
499 Widget_Data *wd = elm_widget_data_get(obj);
500 if (!wd) return EINA_FALSE;
501
502 /* check if it's a valid time. for 32 bits, year greater than 2037 is not */
503 time_check = wd->selected_time;
504 time_check.tm_mon += delta;
505 if (mktime(&time_check) == -1)
506 return EINA_FALSE;
507
508 wd->selected_time.tm_mon += delta;
509 if (wd->selected_time.tm_mon < 0)
510 {
511 if (wd->selected_time.tm_year == wd->year_min)
512 {
513 wd->selected_time.tm_mon++;
514 return EINA_FALSE;
515 }
516 wd->selected_time.tm_mon = 11;
517 wd->selected_time.tm_year--;
518 }
519 else if (wd->selected_time.tm_mon > 11)
520 {
521 if (wd->selected_time.tm_year == wd->year_max)
522 {
523 wd->selected_time.tm_mon--;
524 return EINA_FALSE;
525 }
526 wd->selected_time.tm_mon = 0;
527 wd->selected_time.tm_year++;
528 }
529
530 maxdays = _maxdays_get(&wd->selected_time);
531 if (wd->selected_time.tm_mday > maxdays)
532 wd->selected_time.tm_mday = maxdays;
533
534 _fix_selected_time(wd);
535 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
536
537 return EINA_TRUE;
538}
539
540static Eina_Bool
541_spin_value(void *data)
542{
543 Widget_Data *wd = elm_widget_data_get(data);
544 if (!wd) return ECORE_CALLBACK_CANCEL;
545 if (_update_month(data, wd->spin_speed)) _populate(data);
546 wd->interval = wd->interval / 1.05;
547 ecore_timer_interval_set(wd->spin, wd->interval);
548 return ECORE_CALLBACK_RENEW;
549}
550
551static void
552_button_inc_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
553{
554 Widget_Data *wd = elm_widget_data_get(data);
555 if (!wd) return;
556 wd->interval = wd->first_interval;
557 wd->spin_speed = 1;
558 if (wd->spin) ecore_timer_del(wd->spin);
559 wd->spin = ecore_timer_add(wd->interval, _spin_value, data);
560 _spin_value(data);
561}
562
563static void
564_button_dec_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
565{
566 Widget_Data *wd = elm_widget_data_get(data);
567 if (!wd) return;
568 wd->interval = wd->first_interval;
569 wd->spin_speed = -1;
570 if (wd->spin) ecore_timer_del(wd->spin);
571 wd->spin = ecore_timer_add(wd->interval, _spin_value, data);
572 _spin_value(data);
573}
574
575static void
576_button_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
577{
578 Widget_Data *wd = elm_widget_data_get(data);
579 if (!wd) return;
580 wd->interval = wd->first_interval;
581 if (wd->spin) ecore_timer_del(wd->spin);
582 wd->spin = NULL;
583}
584
585static int
586_get_item_day(Evas_Object *obj, int selected_it)
587{
588 int day;
589 Widget_Data *wd = elm_widget_data_get(obj);
590 if (!wd) return 0;
591
592 day = selected_it - wd->first_day_it + 1;
593 if ((day < 0) || (day > _maxdays_get(&wd->selected_time)))
594 return 0;
595
596 return day;
597}
598
599static void
600_update_sel_it(Evas_Object *obj, int sel_it)
601{
602 int day;
603 Widget_Data *wd = elm_widget_data_get(obj);
604 if ((!wd) || (wd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE))
605 return;
606
607 day = _get_item_day(obj, sel_it);
608 if (!day)
609 return;
610
611 _unselect(wd, wd->selected_it);
612
613 wd->selected_it = sel_it;
614 wd->selected_time.tm_mday = day;
615 _select(wd, wd->selected_it);
616 _fix_selected_time(wd);
617 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
618}
619
620static void
621_day_selected(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source)
622{
623 int sel_it;
624 Widget_Data *wd = elm_widget_data_get(data);
625 if ((!wd) || (wd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE))
626 return;
627 sel_it = atoi(source);
628
629 _update_sel_it(data, sel_it);
630}
631
632static inline int
633_time_to_next_day(struct tm *t)
634{
635 return ((((24 - t->tm_hour) * 60) - t->tm_min) * 60) - t->tm_sec;
636}
637
638static Eina_Bool
639_update_cur_date(void *data)
640{
641 time_t current_time;
642 int t, day;
643 Widget_Data *wd = elm_widget_data_get(data);
644 if (!wd) return ECORE_CALLBACK_RENEW;
645
646 if (wd->today_it > 0) _not_today(wd);
647
648 current_time = time(NULL);
649 localtime_r(&current_time, &wd->current_time);
650 t = _time_to_next_day(&wd->current_time);
651 ecore_timer_interval_set(wd->update_timer, t);
652
653 if ((wd->current_time.tm_mon != wd->selected_time.tm_mon) ||
654 (wd->current_time.tm_year!= wd->selected_time.tm_year))
655 return ECORE_CALLBACK_RENEW;
656
657 day = wd->current_time.tm_mday + wd->first_day_it - 1;
658 _today(wd, day);
659
660 return ECORE_CALLBACK_RENEW;
661}
662
663static Eina_Bool
664_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
665{
666 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
667 Evas_Event_Key_Down *ev = event_info;
668 Widget_Data *wd = elm_widget_data_get(obj);
669
670 if (!wd) return EINA_FALSE;
671 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
672 if (wd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE) return EINA_FALSE;
673
674 if ((!strcmp(ev->keyname, "Left")) ||
675 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
676 {
677 _update_sel_it(obj, wd->selected_it-1);
678 }
679 else if ((!strcmp(ev->keyname, "Right")) ||
680 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
681 {
682 _update_sel_it(obj, wd->selected_it+1);
683 }
684 else if ((!strcmp(ev->keyname, "Up")) ||
685 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
686 {
687 _update_sel_it(obj, wd->selected_it-ELM_DAY_LAST);
688 }
689 else if ((!strcmp(ev->keyname, "Down")) ||
690 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
691 {
692 _update_sel_it(obj, wd->selected_it+ELM_DAY_LAST);
693 }
694 else if ((!strcmp(ev->keyname, "Prior")) ||
695 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
696 {
697 if (_update_month(obj, -1)) _populate(obj);
698 }
699 else if ((!strcmp(ev->keyname, "Next")) ||
700 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
701 {
702 if (_update_month(obj, 1)) _populate(obj);
703 }
704 else return EINA_FALSE;
705
706 return EINA_TRUE;
707}
708
709EAPI Evas_Object *
710elm_calendar_add(Evas_Object *parent)
711{
712 time_t current_time;
713 time_t weekday = 259200; /* Just the first sunday since epoch */
714 Evas_Object *obj;
715 Widget_Data *wd;
716 int i, t;
717 Evas *e;
718
719 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
720
721 ELM_SET_WIDTYPE(widtype, "calendar");
722 elm_widget_type_set(obj, "calendar");
723 elm_widget_sub_object_add(parent, obj);
724 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
725 elm_widget_data_set(obj, wd);
726 elm_widget_del_hook_set(obj, _del_hook);
727 elm_widget_theme_hook_set(obj, _theme_hook);
728 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
729 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
730 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
731 elm_widget_can_focus_set(obj, EINA_TRUE);
732 elm_widget_event_hook_set(obj, _event_hook);
733
734 wd->first_interval = 0.85;
735 wd->year_min = 2;
736 wd->year_max = -1;
737 wd->today_it = -1;
738 wd->selected_it = -1;
739 wd->first_day_it = -1;
740 wd->format_func = _format_month_year;
741 wd->marks = NULL;
742
743 wd->calendar = edje_object_add(e);
744 _elm_theme_object_set(obj, wd->calendar, "calendar", "base", "default");
745 elm_widget_resize_object_set(obj, wd->calendar);
746
747 edje_object_signal_callback_add(wd->calendar, "elm,action,increment,start",
748 "*", _button_inc_start, obj);
749 edje_object_signal_callback_add(wd->calendar, "elm,action,decrement,start",
750 "*", _button_dec_start, obj);
751 edje_object_signal_callback_add(wd->calendar, "elm,action,stop",
752 "*", _button_stop, obj);
753 edje_object_signal_callback_add(wd->calendar, "elm,action,selected",
754 "*", _day_selected, obj);
755
756 evas_object_smart_callbacks_descriptions_set(obj, _signals);
757
758 for (i = 0; i < ELM_DAY_LAST; i++)
759 {
760 /* FIXME: I'm not aware of a known max, so if it fails,
761 * just make it larger. :| */
762 char buf[20];
763 /* I don't know of a better way of doing it */
764 if (strftime(buf, sizeof(buf), "%a", gmtime(&weekday)))
765 {
766 wd->weekdays[i] = eina_stringshare_add(buf);
767 }
768 else
769 {
770 /* If we failed getting day, get a default value */
771 wd->weekdays[i] = _days_abbrev[i];
772 WRN("Failed getting weekday name for '%s' from locale.",
773 _days_abbrev[i]);
774 }
775 weekday += 86400; /* Advance by a day */
776 }
777
778 current_time = time(NULL);
779 localtime_r(&current_time, &wd->selected_time);
780 wd->current_time = wd->selected_time;
781 t = _time_to_next_day(&wd->current_time);
782 wd->update_timer = ecore_timer_add(t, _update_cur_date, obj);
783
784 _set_headers(obj);
785 _populate(obj);
786 _mirrored_set(obj, elm_widget_mirrored_get(obj));
787 _sizing_eval(obj);
788 return obj;
789}
790
791EAPI void
792elm_calendar_weekdays_names_set(Evas_Object *obj, const char *weekdays[])
793{
794 int i;
795 ELM_CHECK_WIDTYPE(obj, widtype);
796 Widget_Data *wd = elm_widget_data_get(obj);
797 if (!wd) return;
798
799 EINA_SAFETY_ON_NULL_RETURN(weekdays);
800
801 for (i = 0; i < ELM_DAY_LAST; i++)
802 {
803 eina_stringshare_replace(&wd->weekdays[i], weekdays[i]);
804 }
805 _set_headers(obj);
806}
807
808EAPI const char **
809elm_calendar_weekdays_names_get(const Evas_Object *obj)
810{
811 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
812 Widget_Data *wd = elm_widget_data_get(obj);
813 if (!wd) return NULL;
814 return wd->weekdays;
815}
816
817EAPI void
818elm_calendar_interval_set(Evas_Object *obj, double interval)
819{
820 ELM_CHECK_WIDTYPE(obj, widtype);
821 Widget_Data *wd = elm_widget_data_get(obj);
822 if (!wd) return;
823 wd->first_interval = interval;
824}
825
826EAPI double
827elm_calendar_interval_get(const Evas_Object *obj)
828{
829 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
830 Widget_Data *wd = elm_widget_data_get(obj);
831 if (!wd) return 0.0;
832 return wd->first_interval;
833}
834
835EAPI void
836elm_calendar_min_max_year_set(Evas_Object *obj, int min, int max)
837{
838 ELM_CHECK_WIDTYPE(obj, widtype);
839 Widget_Data *wd = elm_widget_data_get(obj);
840 if (!wd) return;
841 min -= 1900;
842 max -= 1900;
843 if ((wd->year_min == min) && (wd->year_max == max)) return;
844 wd->year_min = min > 2 ? min : 2;
845 if (max > wd->year_min)
846 wd->year_max = max;
847 else
848 wd->year_max = wd->year_min;
849 if (wd->selected_time.tm_year > wd->year_max)
850 wd->selected_time.tm_year = wd->year_max;
851 if (wd->selected_time.tm_year < wd->year_min)
852 wd->selected_time.tm_year = wd->year_min;
853 _fix_selected_time(wd);
854 _populate(obj);
855}
856
857EAPI void
858elm_calendar_min_max_year_get(const Evas_Object *obj, int *min, int *max)
859{
860 ELM_CHECK_WIDTYPE(obj, widtype);
861 Widget_Data *wd = elm_widget_data_get(obj);
862 if (!wd) return;
863 if (min) *min = wd->year_min + 1900;
864 if (max) *max = wd->year_max + 1900;
865}
866
867EINA_DEPRECATED EAPI void
868elm_calendar_day_selection_disabled_set(Evas_Object *obj, Eina_Bool disabled)
869{
870 if (disabled)
871 elm_calendar_select_mode_set(obj, ELM_CALENDAR_SELECT_MODE_NONE);
872 else
873 elm_calendar_select_mode_set(obj, ELM_CALENDAR_SELECT_MODE_DEFAULT);
874}
875
876EINA_DEPRECATED EAPI Eina_Bool
877elm_calendar_day_selection_disabled_get(const Evas_Object *obj)
878{
879 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
880 Widget_Data *wd = elm_widget_data_get(obj);
881 if (!wd) return EINA_FALSE;
882 return !!(wd->select_mode == ELM_CALENDAR_SELECT_MODE_NONE);
883}
884
885EAPI void
886elm_calendar_selected_time_set(Evas_Object *obj, struct tm *selected_time)
887{
888 ELM_CHECK_WIDTYPE(obj, widtype);
889 Widget_Data *wd = elm_widget_data_get(obj);
890 if (!wd) return;
891
892 EINA_SAFETY_ON_NULL_RETURN(selected_time);
893 wd->selected_time = *selected_time;
894 _populate(obj);
895 return;
896}
897
898EAPI Eina_Bool
899elm_calendar_selected_time_get(const Evas_Object *obj, struct tm *selected_time)
900{
901 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
902 Widget_Data *wd = elm_widget_data_get(obj);
903 if (!wd) return EINA_FALSE;
904 EINA_SAFETY_ON_NULL_RETURN_VAL(selected_time, EINA_FALSE);
905 *selected_time = wd->selected_time;
906 return EINA_TRUE;
907}
908
909EAPI void
910elm_calendar_format_function_set(Evas_Object *obj, Elm_Calendar_Format_Cb format_function)
911{
912 ELM_CHECK_WIDTYPE(obj, widtype);
913 Widget_Data *wd = elm_widget_data_get(obj);
914 if (!wd) return;
915 wd->format_func = format_function;
916 _set_month_year(wd);
917}
918
919EAPI Elm_Calendar_Mark *
920elm_calendar_mark_add(Evas_Object *obj, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat_Type repeat)
921{
922 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
923 Widget_Data *wd = elm_widget_data_get(obj);
924 Elm_Calendar_Mark *mark;
925 if (!wd) return NULL;
926
927 mark = _mark_new(obj, mark_type, mark_time, repeat);
928 wd->marks = eina_list_append(wd->marks, mark);
929 mark->node = eina_list_last(wd->marks);
930 return mark;
931}
932
933EAPI void
934elm_calendar_mark_del(Elm_Calendar_Mark *mark)
935{
936 Evas_Object *obj;
937 Widget_Data *wd;
938
939 EINA_SAFETY_ON_NULL_RETURN(mark);
940
941 obj = mark->obj;
942 wd = elm_widget_data_get(obj);
943 if (!wd) return;
944
945 wd->marks = eina_list_remove_list(wd->marks, mark->node);
946 _mark_free(mark);
947}
948
949EAPI void
950elm_calendar_marks_clear(Evas_Object *obj)
951{
952 ELM_CHECK_WIDTYPE(obj, widtype);
953 Widget_Data *wd = elm_widget_data_get(obj);
954 Elm_Calendar_Mark *mark;
955
956 if (!wd) return;
957 EINA_LIST_FREE(wd->marks, mark)
958 _mark_free(mark);
959}
960
961EAPI const Eina_List *
962elm_calendar_marks_get(const Evas_Object *obj)
963{
964 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
965 Widget_Data *wd = elm_widget_data_get(obj);
966 if (!wd) return NULL;
967 return wd->marks;
968}
969
970EAPI void
971elm_calendar_marks_draw(Evas_Object *obj)
972{
973 ELM_CHECK_WIDTYPE(obj, widtype);
974 Widget_Data *wd = elm_widget_data_get(obj);
975 if (!wd) return;
976 _populate(obj);
977}
978
979EAPI void
980elm_calendar_first_day_of_week_set(Evas_Object *obj, Elm_Calendar_Weekday day)
981{
982 ELM_CHECK_WIDTYPE(obj, widtype);
983 Widget_Data *wd = elm_widget_data_get(obj);
984 if (!wd) return;
985 if (day >= ELM_DAY_LAST) return;
986 if (wd->first_week_day != day)
987 {
988 wd->first_week_day = day;
989 _set_headers(obj);
990 _populate(obj);
991 }
992}
993
994EAPI Elm_Calendar_Weekday
995elm_calendar_first_day_of_week_get(const Evas_Object *obj)
996{
997 ELM_CHECK_WIDTYPE(obj, widtype) -1;
998 Widget_Data *wd = elm_widget_data_get(obj);
999 if (!wd) return -1;
1000 return wd->first_week_day;
1001}
1002
1003EAPI void
1004elm_calendar_select_mode_set(Evas_Object *obj, Elm_Calendar_Select_Mode mode)
1005{
1006 ELM_CHECK_WIDTYPE(obj, widtype);
1007 Widget_Data *wd = elm_widget_data_get(obj);
1008 if (!wd) return;
1009 if ((mode <= ELM_CALENDAR_SELECT_MODE_ONDEMAND)
1010 && (wd->select_mode != mode))
1011 {
1012 wd->select_mode = mode;
1013 if (wd->select_mode == ELM_CALENDAR_SELECT_MODE_ALWAYS)
1014 _select(wd, wd->selected_it);
1015 else
1016 _unselect(wd, wd->selected_it);
1017 }
1018}
1019
1020EAPI Elm_Calendar_Select_Mode
1021elm_calendar_select_mode_get(const Evas_Object *obj)
1022{
1023 ELM_CHECK_WIDTYPE(obj, widtype) -1;
1024 Widget_Data *wd = elm_widget_data_get(obj);
1025 if (!wd) return -1;
1026 return wd->select_mode;
1027}
1028
1029
diff --git a/libraries/elementary/src/lib/elm_calendar.h b/libraries/elementary/src/lib/elm_calendar.h
new file mode 100644
index 0000000..6778018
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_calendar.h
@@ -0,0 +1,510 @@
1/**
2 * @defgroup Calendar Calendar
3 * @ingroup Elementary
4 *
5 * This is a Calendar widget. Calender widget helps applications to flexibly
6 * display a calender with day of the week, day, year and month. Applications will be
7 * able to choose a specific date that will be reported in the smart_callbacks for
8 * the calendar widget. The APIs of calendar widget let the applications perform
9 * other functions like,
10 * placing marks on specific dates
11 * Setting the bounds for the calendar (minimum and maximum years)
12 * Setting the day names of the week. ( for ex. Thu. or Thursday)
13 * Setting the year and month format.
14 *
15 * Signals that you can add callbacks for are:
16 * - @c "changed" - emitted when the date in the calendar is changed.
17 *
18 * Supported elm_object common APIs.
19 * @li @ref elm_object_signal_emit
20 * @li @ref elm_object_signal_callback_add
21 * @li @ref elm_object_signal_callback_del
22 *
23 * Here is some sample code using it:
24 * @li @ref calendar_example_01
25 * @li @ref calendar_example_02
26 * @li @ref calendar_example_03
27 * @li @ref calendar_example_04
28 * @li @ref calendar_example_05
29 * @li @ref calendar_example_06
30 */
31
32/**
33 * @addtogroup Calendar
34 * @{
35 */
36
37typedef enum
38{
39 ELM_CALENDAR_UNIQUE, /**< Default value. Marks will be displayed only on event day. */
40 ELM_CALENDAR_DAILY, /**< Marks will be displayed every day after event day (inclusive). */
41 ELM_CALENDAR_WEEKLY, /**< Marks will be displayed every week after event day (inclusive) - i.e. each seven days. */
42 ELM_CALENDAR_MONTHLY, /**< Marks will be displayed every month day that coincides to event day. E.g.: if an event is set to 30th Jan, no marks will be displayed on Feb, but will be displayed on 30th Mar*/
43 ELM_CALENDAR_ANNUALLY /**< Marks will be displayed every year that coincides to event day (and month). E.g. an event added to 30th Jan 2012 will be repeated on 30th Jan 2013. */
44} _Elm_Calendar_Mark_Repeat_Type;
45
46/**
47 * @enum _Elm_Calendar_Mark_Repeat_Type
48 * @typedef Elm_Calendar_Mark_Repeat_Type
49 *
50 * Event periodicity, used to define if a mark should be repeated
51 * @b beyond event's day. It's set when a mark is added.
52 *
53 * So, for a mark added to 13th May with periodicity set to WEEKLY,
54 * there will be marks every week after this date. Marks will be displayed
55 * at 13th, 20th, 27th, 3rd June ...
56 *
57 * Values don't work as bitmask, only one can be chosen.
58 *
59 * @see elm_calendar_mark_add()
60 *
61 * @ingroup Calendar
62 */
63typedef _Elm_Calendar_Mark_Repeat_Type Elm_Calendar_Mark_Repeat_Type;
64
65typedef enum
66{
67 ELM_DAY_SUNDAY,
68 ELM_DAY_MONDAY,
69 ELM_DAY_TUESDAY,
70 ELM_DAY_WEDNESDAY,
71 ELM_DAY_THURSDAY,
72 ELM_DAY_FRIDAY,
73 ELM_DAY_SATURDAY,
74 ELM_DAY_LAST
75} _Elm_Calendar_Weekday;
76
77/**
78 * @enum _Elm_Calendar_Weekday
79 * @typedef Elm_Calendar_Weekday
80 *
81 * a weekday
82 *
83 * @see elm_calendar_first_day_of_week_set()
84 *
85 * @ingroup Calendar
86 */
87typedef _Elm_Calendar_Weekday Elm_Calendar_Weekday;
88
89
90typedef enum
91{
92 ELM_CALENDAR_SELECT_MODE_DEFAULT = 0, /**< Default value. a day is always selected. */
93 ELM_CALENDAR_SELECT_MODE_ALWAYS, /**< a day is always selected. */
94 ELM_CALENDAR_SELECT_MODE_NONE, /**< None of the days can be selected. */
95 ELM_CALENDAR_SELECT_MODE_ONDEMAND /**< User may have selected a day or not. (not supported yet)*/
96} _Elm_Calendar_Select_Mode;
97
98/**
99 * @enum _Elm_Calendar_Select_Mode
100 * @typedef Elm_Calendar_Select_Mode
101 *
102 * the mode, who determine how user could select a day
103 *
104 * @see elm_calendar_select_mode_set()
105 *
106 * @ingroup Calendar
107 */
108typedef _Elm_Calendar_Select_Mode Elm_Calendar_Select_Mode;
109
110typedef struct _Elm_Calendar_Mark Elm_Calendar_Mark; /**< Item handle for a calendar mark. Created with elm_calendar_mark_add() and deleted with elm_calendar_mark_del(). */
111
112/**
113 * @typedef Elm_Calendar_Format_Cb
114 *
115 * This callback type is used to format the string that will be used
116 * to display month and year.
117 *
118 * @param stime Struct representing time.
119 * @return String representing time that will be set to calendar's text.
120 *
121 * @see elm_calendar_format_function_set()
122 *
123 * @ingroup Calendar
124 */
125typedef char * (*Elm_Calendar_Format_Cb)(struct tm *stime);
126
127/**
128 * Add a new calendar widget to the given parent Elementary
129 * (container) object.
130 *
131 * @param parent The parent object.
132 * @return a new calendar widget handle or @c NULL, on errors.
133 *
134 * This function inserts a new calendar widget on the canvas.
135 *
136 * @ref calendar_example_01
137 *
138 * @ingroup Calendar
139 */
140EAPI Evas_Object *elm_calendar_add(Evas_Object *parent);
141
142/**
143 * Get weekdays names displayed by the calendar.
144 *
145 * @param obj The calendar object.
146 * @return Array of seven strings to be used as weekday names.
147 *
148 * By default, weekdays abbreviations get from system are displayed:
149 * E.g. for an en_US locale: "Sun, Mon, Tue, Wed, Thu, Fri, Sat"
150 * The first string is related to Sunday, the second to Monday...
151 *
152 * @see elm_calendar_weekdays_name_set()
153 *
154 * @ref calendar_example_05
155 *
156 * @ingroup Calendar
157 */
158EAPI const char **elm_calendar_weekdays_names_get(const Evas_Object *obj);
159
160/**
161 * Set weekdays names to be displayed by the calendar.
162 *
163 * @param obj The calendar object.
164 * @param weekdays Array of seven strings to be used as weekday names.
165 * @warning It must have 7 elements, or it will access invalid memory.
166 * @warning The strings must be NULL terminated ('@\0').
167 *
168 * By default, weekdays abbreviations get from system are displayed:
169 * E.g. for an en_US locale: "Sun, Mon, Tue, Wed, Thu, Fri, Sat"
170 *
171 * The first string should be related to Sunday, the second to Monday...
172 *
173 * The usage should be like this:
174 * @code
175 * const char *weekdays[] =
176 * {
177 * "Sunday", "Monday", "Tuesday", "Wednesday",
178 * "Thursday", "Friday", "Saturday"
179 * };
180 * elm_calendar_weekdays_names_set(calendar, weekdays);
181 * @endcode
182 *
183 * @see elm_calendar_weekdays_name_get()
184 *
185 * @ref calendar_example_02
186 *
187 * @ingroup Calendar
188 */
189EAPI void elm_calendar_weekdays_names_set(Evas_Object *obj, const char *weekdays[]);
190
191/**
192 * Set the minimum and maximum values for the year
193 *
194 * @param obj The calendar object
195 * @param min The minimum year, greater than 1901;
196 * @param max The maximum year;
197 *
198 * Maximum must be greater than minimum, except if you don't want to set
199 * maximum year.
200 * Default values are 1902 and -1.
201 *
202 * If the maximum year is a negative value, it will be limited depending
203 * on the platform architecture (year 2037 for 32 bits);
204 *
205 * @see elm_calendar_min_max_year_get()
206 *
207 * @ref calendar_example_03
208 *
209 * @ingroup Calendar
210 */
211EAPI void elm_calendar_min_max_year_set(Evas_Object *obj, int min, int max);
212
213/**
214 * Get the minimum and maximum values for the year
215 *
216 * @param obj The calendar object.
217 * @param min The minimum year.
218 * @param max The maximum year.
219 *
220 * Default values are 1902 and -1.
221 *
222 * @see elm_calendar_min_max_year_get() for more details.
223 *
224 * @ref calendar_example_05
225 *
226 * @ingroup Calendar
227 */
228EAPI void elm_calendar_min_max_year_get(const Evas_Object *obj, int *min, int *max);
229
230/**
231 * Set select day mode to use.
232 *
233 * @param obj The calendar object.
234 * @param select_mdoe The select mode to use.
235 *
236 * Set the day selection mode used.
237 *
238 * @ingroup Calendar
239 */
240EAPI void elm_calendar_select_mode_set(Evas_Object *obj, Elm_Calendar_Select_Mode mode);
241
242/**
243 * Get the select day mode used.
244 *
245 * @param obj The calendar object.
246 *
247 * @return the selected mode
248 *
249 * Get the day selection mode used.
250 *
251 * @see elm_calendar_select_mode_set() for more details
252 *
253 * @ingroup Calendar
254 */
255EAPI Elm_Calendar_Select_Mode elm_calendar_select_mode_get(const Evas_Object *obj);
256
257/**
258 * Set selected date to be highlighted on calendar.
259 *
260 * @param obj The calendar object.
261 * @param selected_time A @b tm struct to represent the selected date.
262 *
263 * Set the selected date, changing the displayed month if needed.
264 * Selected date changes when the user goes to next/previous month or
265 * select a day pressing over it on calendar.
266 *
267 * @see elm_calendar_selected_time_get()
268 *
269 * @ref calendar_example_04
270 *
271 * @ingroup Calendar
272 */
273EAPI void elm_calendar_selected_time_set(Evas_Object *obj, struct tm *selected_time);
274
275/**
276 * Get selected date.
277 *
278 * @param obj The calendar object
279 * @param selected_time A @b tm struct to point to selected date
280 * @return EINA_FALSE means an error occurred and returned time shouldn't
281 * be considered.
282 *
283 * Get date selected by the user or set by function
284 * elm_calendar_selected_time_set().
285 * Selected date changes when the user goes to next/previous month or
286 * select a day pressing over it on calendar.
287 *
288 * @see elm_calendar_selected_time_get()
289 *
290 * @ref calendar_example_05
291 *
292 * @ingroup Calendar
293 */
294EAPI Eina_Bool elm_calendar_selected_time_get(const Evas_Object *obj, struct tm *selected_time);
295
296/**
297 * Set a function to format the string that will be used to display
298 * month and year;
299 *
300 * @param obj The calendar object
301 * @param format_func Function to set the month-year string given
302 * the selected date
303 *
304 * By default it uses strftime with "%B %Y" format string.
305 * It should allocate the memory that will be used by the string,
306 * that will be freed by the widget after usage.
307 * A pointer to the string and a pointer to the time struct will be provided.
308 *
309 * Example:
310 * @code
311 * static char *
312 * _format_month_year(struct tm *selected_time)
313 * {
314 * char buf[32];
315 * if (!strftime(buf, sizeof(buf), "%B %Y", selected_time)) return NULL;
316 * return strdup(buf);
317 * }
318 *
319 * elm_calendar_format_function_set(calendar, _format_month_year);
320 * @endcode
321 *
322 * @ref calendar_example_02
323 *
324 * @ingroup Calendar
325 */
326EAPI void elm_calendar_format_function_set(Evas_Object *obj, Elm_Calendar_Format_Cb format_func);
327
328/**
329 * Add a new mark to the calendar
330 *
331 * @param obj The calendar object
332 * @param mark_type A string used to define the type of mark. It will be
333 * emitted to the theme, that should display a related modification on these
334 * days representation.
335 * @param mark_time A time struct to represent the date of inclusion of the
336 * mark. For marks that repeats it will just be displayed after the inclusion
337 * date in the calendar.
338 * @param repeat Repeat the event following this periodicity. Can be a unique
339 * mark (that don't repeat), daily, weekly, monthly or annually.
340 * @return The created mark or @p NULL upon failure.
341 *
342 * Add a mark that will be drawn in the calendar respecting the insertion
343 * time and periodicity. It will emit the type as signal to the widget theme.
344 * Default theme supports "holiday" and "checked", but it can be extended.
345 *
346 * It won't immediately update the calendar, drawing the marks.
347 * For this, call elm_calendar_marks_draw(). However, when user selects
348 * next or previous month calendar forces marks drawn.
349 *
350 * Marks created with this method can be deleted with
351 * elm_calendar_mark_del().
352 *
353 * Example
354 * @code
355 * struct tm selected_time;
356 * time_t current_time;
357 *
358 * current_time = time(NULL) + 5 * 84600;
359 * localtime_r(&current_time, &selected_time);
360 * elm_calendar_mark_add(cal, "holiday", selected_time,
361 * ELM_CALENDAR_ANNUALLY);
362 *
363 * current_time = time(NULL) + 1 * 84600;
364 * localtime_r(&current_time, &selected_time);
365 * elm_calendar_mark_add(cal, "checked", selected_time, ELM_CALENDAR_UNIQUE);
366 *
367 * elm_calendar_marks_draw(cal);
368 * @endcode
369 *
370 * @see elm_calendar_marks_draw()
371 * @see elm_calendar_mark_del()
372 *
373 * @ref calendar_example_06
374 *
375 * @ingroup Calendar
376 */
377EAPI Elm_Calendar_Mark *elm_calendar_mark_add(Evas_Object *obj, const char *mark_type, struct tm *mark_time, Elm_Calendar_Mark_Repeat_Type repeat);
378
379/**
380 * Delete mark from the calendar.
381 *
382 * @param mark The mark to be deleted.
383 *
384 * If deleting all calendar marks is required, elm_calendar_marks_clear()
385 * should be used instead of getting marks list and deleting each one.
386 *
387 * @see elm_calendar_mark_add()
388 *
389 * @ref calendar_example_06
390 *
391 * @ingroup Calendar
392 */
393EAPI void elm_calendar_mark_del(Elm_Calendar_Mark *mark);
394
395/**
396 * Remove all calendar's marks
397 *
398 * @param obj The calendar object.
399 *
400 * @see elm_calendar_mark_add()
401 * @see elm_calendar_mark_del()
402 *
403 * @ingroup Calendar
404 */
405EAPI void elm_calendar_marks_clear(Evas_Object *obj);
406
407/**
408 * Get a list of all the calendar marks.
409 *
410 * @param obj The calendar object.
411 * @return An @c Eina_List of calendar marks objects, or @c NULL on failure.
412 *
413 * @see elm_calendar_mark_add()
414 * @see elm_calendar_mark_del()
415 * @see elm_calendar_marks_clear()
416 *
417 * @ingroup Calendar
418 */
419EAPI const Eina_List *elm_calendar_marks_get(const Evas_Object *obj);
420
421/**
422 * Draw calendar marks.
423 *
424 * @param obj The calendar object.
425 *
426 * Should be used after adding, removing or clearing marks.
427 * It will go through the entire marks list updating the calendar.
428 * If lots of marks will be added, add all the marks and then call
429 * this function.
430 *
431 * When the month is changed, i.e. user selects next or previous month,
432 * marks will be drawn.
433 *
434 * @see elm_calendar_mark_add()
435 * @see elm_calendar_mark_del()
436 * @see elm_calendar_marks_clear()
437 *
438 * @ref calendar_example_06
439 *
440 * @ingroup Calendar
441 */
442EAPI void elm_calendar_marks_draw(Evas_Object *obj);
443
444/**
445 * Set the interval on time updates for an user mouse button hold
446 * on calendar widgets' month selection.
447 *
448 * @param obj The calendar object
449 * @param interval The (first) interval value in seconds
450 *
451 * This interval value is @b decreased while the user holds the
452 * mouse pointer either selecting next or previous month.
453 *
454 * This helps the user to get to a given month distant from the
455 * current one easier/faster, as it will start to change quicker and
456 * quicker on mouse button holds.
457 *
458 * The calculation for the next change interval value, starting from
459 * the one set with this call, is the previous interval divided by
460 * 1.05, so it decreases a little bit.
461 *
462 * The default starting interval value for automatic changes is
463 * @b 0.85 seconds.
464 *
465 * @see elm_calendar_interval_get()
466 *
467 * @ingroup Calendar
468 */
469EAPI void elm_calendar_interval_set(Evas_Object *obj, double interval);
470
471/**
472 * Get the interval on time updates for an user mouse button hold
473 * on calendar widgets' month selection.
474 *
475 * @param obj The calendar object
476 * @return The (first) interval value, in seconds, set on it
477 *
478 * @see elm_calendar_interval_set() for more details
479 *
480 * @ingroup Calendar
481 */
482EAPI double elm_calendar_interval_get(const Evas_Object *obj);
483
484/**
485 * Set the first day of week to use on calendar widgets'.
486 *
487 * @param obj The calendar object
488 * @param day An int which correspond to the first day of the week (Sunday = 0, monday = 1,
489 * ..., saturday = 6)
490 *
491 * @ingroup Calendar
492 */
493EAPI void elm_calendar_first_day_of_week_set(Evas_Object *obj, Elm_Calendar_Weekday day);
494
495/**
496 * Get the first day of week, who are used on calendar widgets'.
497 *
498 * @param obj The calendar object
499 * @return An int which correspond to the first day of the week (Sunday = 0, monday = 1,
500 * ..., saturday = 6)
501 *
502 * @see elm_calendar_first_day_of_week_set() for more details
503 *
504 * @ingroup Calendar
505 */
506EAPI Elm_Calendar_Weekday elm_calendar_first_day_of_week_get(const Evas_Object *obj);
507
508/**
509 * @}
510 */
diff --git a/libraries/elementary/src/lib/elm_check.c b/libraries/elementary/src/lib/elm_check.c
new file mode 100644
index 0000000..e3f40b4
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_check.c
@@ -0,0 +1,518 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *chk, *icon;
9 Eina_Bool state;
10 Eina_Bool *statep;
11 const char *label;
12 const char *ontext, *offtext;
13};
14
15static const char *widtype = NULL;
16static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
17 Evas_Callback_Type type, void *event_info);
18static void _del_hook(Evas_Object *obj);
19static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
20static void _theme_hook(Evas_Object *obj);
21static void _disable_hook(Evas_Object *obj);
22static void _sizing_eval(Evas_Object *obj);
23static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj,
24 void *event_info);
25static void _sub_del(void *data, Evas_Object *obj, void *event_info);
26static void _signal_check_off(void *data, Evas_Object *obj,
27 const char *emission, const char *source);
28static void _signal_check_on(void *data, Evas_Object *obj,
29 const char *emission, const char *source);
30static void _signal_check_toggle(void *data, Evas_Object *obj,
31 const char *emission, const char *source);
32static void _on_focus_hook(void *data, Evas_Object *obj);
33static void _activate_hook(Evas_Object *obj);
34static void _content_set_hook(Evas_Object *obj, const char *part,
35 Evas_Object *content);
36static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
37static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
38static void _activate(Evas_Object *obj);
39static const char SIG_CHANGED[] = "changed";
40static const Evas_Smart_Cb_Description _signals[] = {
41 {SIG_CHANGED, ""},
42 {NULL, NULL}
43};
44
45static Eina_Bool
46_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
47 Evas_Callback_Type type, void *event_info)
48{
49 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
50 Evas_Event_Key_Down *ev = event_info;
51 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
52 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
53 if ((strcmp(ev->keyname, "Return")) &&
54 (strcmp(ev->keyname, "KP_Enter")) &&
55 (strcmp(ev->keyname, "space")))
56 return EINA_FALSE;
57 _activate(obj);
58 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
59 return EINA_TRUE;
60}
61
62static void
63_del_hook(Evas_Object *obj)
64{
65 Widget_Data *wd = elm_widget_data_get(obj);
66 if (!wd) return;
67 if (wd->label) eina_stringshare_del(wd->label);
68 if (wd->ontext) eina_stringshare_del(wd->ontext);
69 if (wd->offtext) eina_stringshare_del(wd->offtext);
70 free(wd);
71}
72
73static void
74_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
75{
76 Widget_Data *wd = elm_widget_data_get(obj);
77 if (!wd) return;
78 if (elm_widget_focus_get(obj))
79 {
80 edje_object_signal_emit(wd->chk, "elm,action,focus", "elm");
81 evas_object_focus_set(wd->chk, EINA_TRUE);
82 }
83 else
84 {
85 edje_object_signal_emit(wd->chk, "elm,action,unfocus", "elm");
86 evas_object_focus_set(wd->chk, EINA_FALSE);
87 }
88}
89
90static void
91_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
92{
93 Widget_Data *wd = elm_widget_data_get(obj);
94 if (!wd) return;
95 edje_object_mirrored_set(wd->chk, rtl);
96}
97
98static void
99_theme_hook(Evas_Object *obj)
100{
101 Widget_Data *wd = elm_widget_data_get(obj);
102 if (!wd) return;
103 _elm_widget_mirrored_reload(obj);
104 _mirrored_set(obj, elm_widget_mirrored_get(obj));
105 _elm_theme_object_set(obj, wd->chk, "check", "base", elm_widget_style_get(obj));
106 if (wd->icon)
107 edje_object_signal_emit(wd->chk, "elm,state,icon,visible", "elm");
108 else
109 edje_object_signal_emit(wd->chk, "elm,state,icon,hidden", "elm");
110 if (wd->state)
111 edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
112 else
113 edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
114 if (wd->label)
115 edje_object_signal_emit(wd->chk, "elm,state,text,visible", "elm");
116 else
117 edje_object_signal_emit(wd->chk, "elm,state,text,hidden", "elm");
118 edje_object_part_text_escaped_set(wd->chk, "elm.text", wd->label);
119 edje_object_part_text_escaped_set(wd->chk, "elm.ontext", wd->ontext);
120 edje_object_part_text_escaped_set(wd->chk, "elm.offtext", wd->offtext);
121 if (elm_widget_disabled_get(obj))
122 edje_object_signal_emit(wd->chk, "elm,state,disabled", "elm");
123 edje_object_message_signal_process(wd->chk);
124 edje_object_scale_set(wd->chk, elm_widget_scale_get(obj) * _elm_config->scale);
125 _sizing_eval(obj);
126}
127
128static void
129_disable_hook(Evas_Object *obj)
130{
131 Widget_Data *wd = elm_widget_data_get(obj);
132 if (!wd) return;
133 if (elm_widget_disabled_get(obj))
134 edje_object_signal_emit(wd->chk, "elm,state,disabled", "elm");
135 else
136 edje_object_signal_emit(wd->chk, "elm,state,enabled", "elm");
137}
138
139static void
140_sizing_eval(Evas_Object *obj)
141{
142 Widget_Data *wd = elm_widget_data_get(obj);
143 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
144 if (!wd) return;
145 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
146 edje_object_size_min_restricted_calc(wd->chk, &minw, &minh, minw, minh);
147 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
148 evas_object_size_hint_min_set(obj, minw, minh);
149 evas_object_size_hint_max_set(obj, maxw, maxh);
150}
151
152static void
153_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
154{
155 Widget_Data *wd = elm_widget_data_get(data);
156 if (!wd) return;
157 if (obj != wd->icon) return;
158 _sizing_eval(data);
159}
160
161static void
162_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
163{
164 Widget_Data *wd = elm_widget_data_get(obj);
165 Evas_Object *sub = event_info;
166 if (!wd) return;
167 if (sub == wd->icon)
168 {
169 edje_object_signal_emit(wd->chk, "elm,state,icon,hidden", "elm");
170 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
171 _changed_size_hints, obj);
172 wd->icon = NULL;
173 _sizing_eval(obj);
174 edje_object_message_signal_process(wd->chk);
175 }
176}
177
178static void
179_signal_check_off(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
180{
181 Widget_Data *wd = elm_widget_data_get(data);
182 if (!wd) return;
183 wd->state = EINA_FALSE;
184 if (wd->statep) *wd->statep = wd->state;
185 edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
186 evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
187}
188
189static void
190_signal_check_on(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
191{
192 Widget_Data *wd = elm_widget_data_get(data);
193 if (!wd) return;
194 wd->state = EINA_TRUE;
195 if (wd->statep) *wd->statep = wd->state;
196 edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
197 evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
198}
199
200static void
201_signal_check_toggle(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
202{
203 _activate(data);
204}
205
206static void
207_activate_hook(Evas_Object *obj)
208{
209 _activate(obj);
210}
211
212static void
213_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
214{
215 Widget_Data *wd = elm_widget_data_get(obj);
216 if (!wd) return;
217
218 edje_object_signal_emit(wd->chk, emission, source);
219}
220
221static void
222_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
223{
224 Widget_Data *wd = elm_widget_data_get(obj);
225 if (!wd) return;
226 edje_object_signal_callback_add(wd->chk, emission, source, func_cb, data);
227}
228
229static void
230_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
231{
232 Widget_Data *wd = elm_widget_data_get(obj);
233 edje_object_signal_callback_del_full(wd->chk, emission, source, func_cb,
234 data);
235}
236
237static void
238_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
239{
240 ELM_CHECK_WIDTYPE(obj, widtype);
241 Widget_Data *wd;
242
243 if (part && strcmp(part, "icon")) return;
244 wd = elm_widget_data_get(obj);
245 if (!wd) return;
246 if (wd->icon == content) return;
247 if (wd->icon) evas_object_del(wd->icon);
248 wd->icon = content;
249 if (content)
250 {
251 elm_widget_sub_object_add(obj, content);
252 evas_object_event_callback_add(content,
253 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
254 _changed_size_hints, obj);
255 edje_object_part_swallow(wd->chk, "elm.swallow.content", content);
256 edje_object_signal_emit(wd->chk, "elm,state,icon,visible", "elm");
257 edje_object_message_signal_process(wd->chk);
258 }
259 _sizing_eval(obj);
260}
261
262static Evas_Object *
263_content_get_hook(const Evas_Object *obj, const char *part)
264{
265 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
266 Widget_Data *wd;
267
268 if (part && strcmp(part, "icon")) return NULL;
269 wd = elm_widget_data_get(obj);
270 if (!wd) return NULL;
271 return wd->icon;
272}
273
274static Evas_Object *
275_content_unset_hook(Evas_Object *obj, const char *part)
276{
277 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
278 Widget_Data *wd;
279
280 if (part && strcmp(part, "icon")) return NULL;
281 wd = elm_widget_data_get(obj);
282 if (!wd) return NULL;
283 if (!wd->icon) return NULL;
284 Evas_Object *icon = wd->icon;
285 elm_widget_sub_object_del(obj, wd->icon);
286 edje_object_part_unswallow(wd->chk, icon);
287 return icon;
288}
289
290static void
291_activate(Evas_Object *obj)
292{
293 Widget_Data *wd = elm_widget_data_get(obj);
294 if (!wd) return;
295 if ((_elm_config->access_mode == ELM_ACCESS_MODE_OFF) ||
296 (_elm_access_2nd_click_timeout(obj)))
297 {
298 wd->state = !wd->state;
299 if (wd->statep) *wd->statep = wd->state;
300 if (wd->state)
301 {
302 edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
303 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
304 {
305 if (!wd->ontext)
306 {
307 _elm_access_say(E_("State: On"));
308 }
309 else
310 _elm_access_say(E_("State: On"));
311 }
312 }
313 else
314 {
315 edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
316 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
317 {
318 if (!wd->offtext)
319 {
320 _elm_access_say(E_("State: Off"));
321 }
322 else
323 _elm_access_say(E_("State: Off"));
324 }
325 }
326 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
327 }
328}
329
330static void
331_elm_check_label_set(Evas_Object *obj, const char *item, const char *label)
332{
333 ELM_CHECK_WIDTYPE(obj, widtype);
334 Widget_Data *wd = elm_widget_data_get(obj);
335 if (!wd) return;
336 if ((!item) || (!strcmp(item, "default")))
337 {
338 eina_stringshare_replace(&wd->label, label);
339 if (label)
340 edje_object_signal_emit(wd->chk, "elm,state,text,visible", "elm");
341 else
342 edje_object_signal_emit(wd->chk, "elm,state,text,hidden", "elm");
343 edje_object_message_signal_process(wd->chk);
344 edje_object_part_text_escaped_set(wd->chk, "elm.text", label);
345 }
346 else if ((item) && (!strcmp(item, "on")))
347 {
348 eina_stringshare_replace(&wd->ontext, label);
349 edje_object_part_text_escaped_set(wd->chk, "elm.ontext", wd->ontext);
350 }
351 else if ((item) && (!strcmp(item, "off")))
352 {
353 eina_stringshare_replace(&wd->offtext, label);
354 edje_object_part_text_escaped_set(wd->chk, "elm.offtext", wd->offtext);
355 }
356 _sizing_eval(obj);
357}
358
359static const char *
360_elm_check_label_get(const Evas_Object *obj, const char *item)
361{
362 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
363 Widget_Data *wd = elm_widget_data_get(obj);
364 if (!wd) return NULL;
365 if ((!item) || (!strcmp(item, "default")))
366 return wd->label;
367 else if ((item) && (!strcmp(item, "on")))
368 return wd->ontext;
369 else if ((item) && (!strcmp(item, "off")))
370 return wd->offtext;
371 return NULL;
372}
373
374static char *
375_access_info_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Widget_Item *item __UNUSED__)
376{
377 const char *txt = elm_widget_access_info_get(obj);
378 if (!txt) txt = _elm_check_label_get(obj, NULL);
379 if (txt) return strdup(txt);
380 return NULL;
381}
382
383static char *
384_access_state_cb(void *data, Evas_Object *obj, Elm_Widget_Item *item __UNUSED__)
385{
386 Evas_Object *o = data;
387 Widget_Data *wd = elm_widget_data_get(o);
388 if (!wd) return NULL;
389 if (elm_widget_disabled_get(obj))
390 return strdup(E_("State: Disabled"));
391 if (wd->state)
392 {
393 if (wd->ontext)
394 {
395 char buf[1024];
396
397 snprintf(buf, sizeof(buf), "%s: %s", E_("State"), wd->ontext);
398 return strdup(buf);
399 }
400 else
401 return strdup(E_("State: On"));
402 }
403 if (wd->offtext)
404 {
405 char buf[1024];
406
407 snprintf(buf, sizeof(buf), "%s: %s", E_("State"), wd->offtext);
408 return strdup(buf);
409 }
410 return strdup(E_("State: Off"));
411}
412
413EAPI Evas_Object *
414elm_check_add(Evas_Object *parent)
415{
416 Evas_Object *obj;
417 Evas *e;
418 Widget_Data *wd;
419
420 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
421
422 ELM_SET_WIDTYPE(widtype, "check");
423 elm_widget_type_set(obj, "check");
424 elm_widget_sub_object_add(parent, obj);
425 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
426 elm_widget_data_set(obj, wd);
427 elm_widget_del_hook_set(obj, _del_hook);
428 elm_widget_theme_hook_set(obj, _theme_hook);
429 elm_widget_disable_hook_set(obj, _disable_hook);
430 elm_widget_can_focus_set(obj, EINA_TRUE);
431 elm_widget_activate_hook_set(obj, _activate_hook);
432 elm_widget_event_hook_set(obj, _event_hook);
433 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
434 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
435 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
436 elm_widget_text_set_hook_set(obj, _elm_check_label_set);
437 elm_widget_text_get_hook_set(obj, _elm_check_label_get);
438 elm_widget_content_set_hook_set(obj, _content_set_hook);
439 elm_widget_content_get_hook_set(obj, _content_get_hook);
440 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
441
442 wd->chk = edje_object_add(e);
443 _elm_theme_object_set(obj, wd->chk, "check", "base", "default");
444 edje_object_signal_callback_add(wd->chk, "elm,action,check,on", "",
445 _signal_check_on, obj);
446 edje_object_signal_callback_add(wd->chk, "elm,action,check,off", "",
447 _signal_check_off, obj);
448 edje_object_signal_callback_add(wd->chk, "elm,action,check,toggle", "",
449 _signal_check_toggle, obj);
450 elm_widget_resize_object_set(obj, wd->chk);
451
452 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
453
454 _mirrored_set(obj, elm_widget_mirrored_get(obj));
455 _sizing_eval(obj);
456
457 // TODO: convert Elementary to subclassing of Evas_Smart_Class
458 // TODO: and save some bytes, making descriptions per-class and not instance!
459 evas_object_smart_callbacks_descriptions_set(obj, _signals);
460
461 _elm_access_object_register(obj, wd->chk);
462 _elm_access_text_set(_elm_access_object_get(obj),
463 ELM_ACCESS_TYPE, E_("Check"));
464 _elm_access_callback_set(_elm_access_object_get(obj),
465 ELM_ACCESS_INFO, _access_info_cb, obj);
466 _elm_access_callback_set(_elm_access_object_get(obj),
467 ELM_ACCESS_STATE, _access_state_cb, obj);
468 return obj;
469}
470
471EAPI void
472elm_check_state_set(Evas_Object *obj, Eina_Bool state)
473{
474 ELM_CHECK_WIDTYPE(obj, widtype);
475 Widget_Data *wd = elm_widget_data_get(obj);
476 if (!wd) return;
477 if (state != wd->state)
478 {
479 wd->state = state;
480 if (wd->statep) *wd->statep = wd->state;
481 if (wd->state)
482 edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
483 else
484 edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
485 }
486 edje_object_message_signal_process(wd->chk);
487}
488
489EAPI Eina_Bool
490elm_check_state_get(const Evas_Object *obj)
491{
492 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
493 Widget_Data *wd = elm_widget_data_get(obj);
494 if (!wd) return EINA_FALSE;
495 return wd->state;
496}
497
498EAPI void
499elm_check_state_pointer_set(Evas_Object *obj, Eina_Bool *statep)
500{
501 ELM_CHECK_WIDTYPE(obj, widtype);
502 Widget_Data *wd = elm_widget_data_get(obj);
503 if (!wd) return;
504 if (statep)
505 {
506 wd->statep = statep;
507 if (*wd->statep != wd->state)
508 {
509 wd->state = *wd->statep;
510 if (wd->state)
511 edje_object_signal_emit(wd->chk, "elm,state,check,on", "elm");
512 else
513 edje_object_signal_emit(wd->chk, "elm,state,check,off", "elm");
514 }
515 }
516 else
517 wd->statep = NULL;
518}
diff --git a/libraries/elementary/src/lib/elm_check.h b/libraries/elementary/src/lib/elm_check.h
new file mode 100644
index 0000000..7bdf13b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_check.h
@@ -0,0 +1,105 @@
1/**
2 * @defgroup Check Check
3 * @ingroup Elementary
4 *
5 * @image html img/widget/check/preview-00.png
6 * @image latex img/widget/check/preview-00.eps
7 * @image html img/widget/check/preview-01.png
8 * @image latex img/widget/check/preview-01.eps
9 * @image html img/widget/check/preview-02.png
10 * @image latex img/widget/check/preview-02.eps
11 *
12 * @brief The check widget allows for toggling a value between true and
13 * false.
14 *
15 * Check objects are a lot like radio objects in layout and functionality
16 * except they do not work as a group, but independently and only toggle the
17 * value of a boolean from false to true (0 or 1). elm_check_state_set() sets
18 * the boolean state (1 for true, 0 for false), and elm_check_state_get()
19 * returns the current state. For convenience, like the radio objects, you
20 * can set a pointer to a boolean directly with elm_check_state_pointer_set()
21 * for it to modify.
22 *
23 * Signals that you can add callbacks for are:
24 * "changed" - This is called whenever the user changes the state of the check
25 * objects(event_info is NULL).
26 *
27 * Default content parts of the check widget that you can use for are:
28 * @li "icon" - An icon of the check
29 *
30 * Default text parts of the check widget that you can use for are:
31 * @li "default" - A label of the check
32 * @li "on" - On state label of the check
33 * @li "off" - Off state label of the check
34 *
35 * Supported elm_object common APIs.
36 * @li @ref elm_object_disabled_set
37 * @li @ref elm_object_disabled_get
38 * @li @ref elm_object_part_text_set
39 * @li @ref elm_object_part_text_get
40 * @li @ref elm_object_part_content_set
41 * @li @ref elm_object_part_content_get
42 * @li @ref elm_object_part_content_unset
43 * @li @ref elm_object_signal_emit
44 * @li @ref elm_object_signal_callback_add
45 * @li @ref elm_object_signal_callback_del
46 *
47 * @ref tutorial_check should give you a firm grasp of how to use this widget.
48 *
49 * @{
50 */
51
52/**
53 * @brief Add a new Check object
54 *
55 * @param parent The parent object
56 * @return The new object or NULL if it cannot be created
57 *
58 * @ingroup Check
59 */
60EAPI Evas_Object * elm_check_add(Evas_Object *parent);
61
62/**
63 * @brief Set the on/off state of the check object
64 *
65 * @param obj The check object
66 * @param state The state to use (1 == on, 0 == off)
67 *
68 * This sets the state of the check. If set with elm_check_state_pointer_set()
69 * the state of that variable is also changed. Calling this @b doesn't cause
70 * the "changed" signal to be emitted.
71 *
72 * @ingroup Check
73 */
74EAPI void elm_check_state_set(Evas_Object *obj, Eina_Bool state);
75
76/**
77 * @brief Get the state of the check object
78 *
79 * @param obj The check object
80 * @return The boolean state
81 *
82 * @ingroup Check
83 */
84EAPI Eina_Bool elm_check_state_get(const Evas_Object *obj);
85
86/**
87 * @brief Set a convenience pointer to a boolean to change
88 *
89 * @param obj The check object
90 * @param statep Pointer to the boolean to modify
91 *
92 * This sets a pointer to a boolean, that, in addition to the check objects
93 * state will also be modified directly. To stop setting the object pointed
94 * to simply use NULL as the @p statep parameter. If @p statep is not NULL,
95 * then when this is called, the check objects state will also be modified to
96 * reflect the value of the boolean @p statep points to, just like calling
97 * elm_check_state_set().
98 *
99 * @ingroup Check
100 */
101EAPI void elm_check_state_pointer_set(Evas_Object *obj, Eina_Bool *statep);
102
103/**
104 * @}
105 */
diff --git a/libraries/elementary/src/lib/elm_clock.c b/libraries/elementary/src/lib/elm_clock.c
new file mode 100644
index 0000000..3bd0b2d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_clock.c
@@ -0,0 +1,681 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define DEFAULT_FIRST_INTERVAL 0.85
5typedef struct _Widget_Data Widget_Data;
6
7struct _Widget_Data
8{
9 Evas_Object *clk;
10 double interval, first_interval;
11 Eina_Bool seconds : 1;
12 Eina_Bool am_pm : 1;
13 Eina_Bool edit : 1;
14 Elm_Clock_Edit_Mode digedit;
15 int hrs, min, sec, timediff;
16 Evas_Object *digit[6];
17 Evas_Object *ampm;
18 Evas_Object *sel_obj;
19 Ecore_Timer *ticker, *spin;
20 struct
21 {
22 int hrs, min, sec;
23 char ampm;
24 Eina_Bool seconds : 1;
25 Eina_Bool am_pm : 1;
26 Eina_Bool edit : 1;
27 Elm_Clock_Edit_Mode digedit;
28 } cur;
29};
30
31static const char *widtype = NULL;
32static void _del_hook(Evas_Object *obj);
33static void _theme_hook(Evas_Object *obj);
34static void _on_focus_hook(void *data, Evas_Object *obj);
35static Eina_Bool _ticker(void *data);
36static Eina_Bool _signal_clock_val_up(void *data);
37static Eina_Bool _signal_clock_val_down(void *data);
38static void _time_update(Evas_Object *obj);
39
40static const char SIG_CHANGED[] = "changed";
41
42static const Evas_Smart_Cb_Description _signals[] = {
43 {SIG_CHANGED, ""},
44 {NULL, NULL}
45};
46
47
48static void
49_del_hook(Evas_Object *obj)
50{
51 Widget_Data *wd = elm_widget_data_get(obj);
52 if (!wd) return;
53 int i;
54 for (i = 0; i < 6; i++)
55 {
56 if (wd->digit[i]) evas_object_del(wd->digit[i]);
57 }
58 if (wd->ampm) evas_object_del(wd->ampm);
59 if (wd->ticker) ecore_timer_del(wd->ticker);
60 if (wd->spin) ecore_timer_del(wd->spin);
61 free(wd);
62}
63
64static void
65_theme_hook(Evas_Object *obj)
66{
67 Widget_Data *wd = elm_widget_data_get(obj);
68 if (!wd) return;
69 if (elm_widget_focus_get(obj))
70 edje_object_signal_emit(wd->clk, "elm,action,focus", "elm");
71 else
72 edje_object_signal_emit(wd->clk, "elm,action,unfocus", "elm");
73 wd->cur.am_pm = !wd->cur.am_pm; /* hack - force update */
74 _time_update(obj);
75}
76
77static void
78_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
79{
80 Widget_Data *wd = elm_widget_data_get(obj);
81 if (!wd) return;
82 if (elm_widget_focus_get(obj))
83 {
84 edje_object_signal_emit(wd->clk, "elm,action,focus", "elm");
85 evas_object_focus_set(wd->clk, EINA_TRUE);
86 }
87 else
88 {
89 edje_object_signal_emit(wd->clk, "elm,action,unfocus", "elm");
90 evas_object_focus_set(wd->clk, EINA_FALSE);
91 }
92}
93
94static void
95_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
96{
97 Widget_Data *wd = elm_widget_data_get(obj);
98 int i;
99 if (!wd) return;
100 edje_object_signal_emit(wd->clk, emission, source);
101 for (i = 0; i < 6; i++)
102 {
103 if (wd->digit[i])
104 edje_object_signal_emit(wd->digit[i], emission, source);
105 }
106}
107
108static void
109_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
110{
111 Widget_Data *wd = elm_widget_data_get(obj);
112 int i;
113 if (!wd) return;
114 edje_object_signal_callback_add(wd->clk, emission, source, func_cb, data);
115 for (i = 0; i < 6; i++)
116 {
117 if (wd->digit[i])
118 edje_object_signal_callback_add(wd->digit[i], emission, source,
119 func_cb, data);
120 }
121}
122
123static void
124_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
125{
126 Widget_Data *wd = elm_widget_data_get(obj);
127 int i;
128 for (i = 0; i < 6; i++)
129 {
130 edje_object_signal_callback_del_full(wd->digit[i], emission, source,
131 func_cb, data);
132 }
133 edje_object_signal_callback_del_full(wd->clk, emission, source, func_cb,
134 data);
135}
136
137static void
138_timediff_set(Widget_Data *wd)
139{
140 struct timeval timev;
141 struct tm *tm;
142 time_t tt;
143 gettimeofday(&timev, NULL);
144 tt = (time_t)(timev.tv_sec);
145 tzset();
146 tm = localtime(&tt);
147 wd->timediff = (((wd->hrs - tm->tm_hour) * 60 +
148 wd->min - tm->tm_min) * 60) + wd->sec - tm->tm_sec;
149}
150
151static Eina_Bool
152_ticker(void *data)
153{
154 Widget_Data *wd = elm_widget_data_get(data);
155 double t;
156 struct timeval timev;
157 struct tm *tm;
158 time_t tt;
159 if (!wd) return ECORE_CALLBACK_CANCEL;
160 gettimeofday(&timev, NULL);
161 t = ((double)(1000000 - timev.tv_usec)) / 1000000.0;
162 wd->ticker = ecore_timer_add(t, _ticker, data);
163 if (!wd->edit)
164 {
165 tt = (time_t)(timev.tv_sec) + wd->timediff;
166 tzset();
167 tm = localtime(&tt);
168 if (tm)
169 {
170 wd->hrs = tm->tm_hour;
171 wd->min = tm->tm_min;
172 wd->sec = tm->tm_sec;
173 _time_update(data);
174 }
175 }
176 return ECORE_CALLBACK_CANCEL;
177}
178
179static Eina_Bool
180_signal_clock_val_up(void *data)
181{
182 Widget_Data *wd = elm_widget_data_get(data);
183 if (!wd) goto clock_val_up_exit_on_error;
184 if (!wd->edit) goto clock_val_up_cancel;
185 if (!wd->sel_obj) goto clock_val_up_cancel;
186 if (wd->sel_obj == wd->digit[0])
187 {
188 wd->hrs = wd->hrs + 10;
189 if (wd->hrs >= 24) wd->hrs -= 24;
190 }
191 if (wd->sel_obj == wd->digit[1])
192 {
193 wd->hrs = wd->hrs + 1;
194 if (wd->hrs >= 24) wd->hrs -= 24;
195 }
196 if (wd->sel_obj == wd->digit[2])
197 {
198 wd->min = wd->min + 10;
199 if (wd->min >= 60) wd->min -= 60;
200 }
201 if (wd->sel_obj == wd->digit[3])
202 {
203 wd->min = wd->min + 1;
204 if (wd->min >= 60) wd->min -= 60;
205 }
206 if (wd->sel_obj == wd->digit[4])
207 {
208 wd->sec = wd->sec + 10;
209 if (wd->sec >= 60) wd->sec -= 60;
210 }
211 if (wd->sel_obj == wd->digit[5])
212 {
213 wd->sec = wd->sec + 1;
214 if (wd->sec >= 60) wd->sec -= 60;
215 }
216 if (wd->sel_obj == wd->ampm)
217 {
218 wd->hrs = wd->hrs + 12;
219 if (wd->hrs > 23) wd->hrs -= 24;
220 }
221 wd->interval = wd->interval / 1.05;
222 ecore_timer_interval_set(wd->spin, wd->interval);
223 _time_update(data);
224 evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
225 return ECORE_CALLBACK_RENEW;
226clock_val_up_cancel:
227 wd->spin = NULL;
228clock_val_up_exit_on_error:
229 return ECORE_CALLBACK_CANCEL;
230}
231
232static Eina_Bool
233_signal_clock_val_down(void *data)
234{
235 Widget_Data *wd = elm_widget_data_get(data);
236 if (!wd) goto clock_val_down_exit_on_error;
237 if (!wd->edit) goto clock_val_down_cancel;
238 if (!wd->sel_obj) goto clock_val_down_cancel;
239 if (wd->sel_obj == wd->digit[0])
240 {
241 wd->hrs = wd->hrs - 10;
242 if (wd->hrs < 0) wd->hrs += 24;
243 }
244 if (wd->sel_obj == wd->digit[1])
245 {
246 wd->hrs = wd->hrs - 1;
247 if (wd->hrs < 0) wd->hrs += 24;
248 }
249 if (wd->sel_obj == wd->digit[2])
250 {
251 wd->min = wd->min - 10;
252 if (wd->min < 0) wd->min += 60;
253 }
254 if (wd->sel_obj == wd->digit[3])
255 {
256 wd->min = wd->min - 1;
257 if (wd->min < 0) wd->min += 60;
258 }
259 if (wd->sel_obj == wd->digit[4])
260 {
261 wd->sec = wd->sec - 10;
262 if (wd->sec < 0) wd->sec += 60;
263 }
264 if (wd->sel_obj == wd->digit[5])
265 {
266 wd->sec = wd->sec - 1;
267 if (wd->sec < 0) wd->sec += 60;
268 }
269 if (wd->sel_obj == wd->ampm)
270 {
271 wd->hrs = wd->hrs - 12;
272 if (wd->hrs < 0) wd->hrs += 24;
273 }
274 wd->interval = wd->interval / 1.05;
275 ecore_timer_interval_set(wd->spin, wd->interval);
276 _time_update(data);
277 evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
278 return ECORE_CALLBACK_RENEW;
279clock_val_down_cancel:
280 wd->spin = NULL;
281clock_val_down_exit_on_error:
282 return ECORE_CALLBACK_CANCEL;
283}
284
285static void
286_signal_clock_val_up_start(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
287{
288 Widget_Data *wd = elm_widget_data_get(data);
289 if (!wd) return;
290 wd->interval = wd->first_interval;
291 wd->sel_obj = obj;
292 if (wd->spin) ecore_timer_del(wd->spin);
293 wd->spin = ecore_timer_add(wd->interval, _signal_clock_val_up, data);
294 _signal_clock_val_up(data);
295}
296
297static void
298_signal_clock_val_down_start(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
299{
300 Widget_Data *wd = elm_widget_data_get(data);
301 if (!wd) return;
302 wd->interval = wd->first_interval;
303 wd->sel_obj = obj;
304 if (wd->spin) ecore_timer_del(wd->spin);
305 wd->spin = ecore_timer_add(wd->interval, _signal_clock_val_down, data);
306 _signal_clock_val_down(data);
307}
308
309static void
310_signal_clock_val_change_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
311{
312 Widget_Data *wd = elm_widget_data_get(data);
313 if (!wd) return;
314 if (wd->spin) ecore_timer_del(wd->spin);
315 wd->spin = NULL;
316 wd->sel_obj = NULL;
317}
318
319static void
320_time_update(Evas_Object *obj)
321{
322 Widget_Data *wd = elm_widget_data_get(obj);
323 Edje_Message_Int msg;
324 int ampm = 0;
325 const char *style = elm_widget_style_get(obj);
326 if (!wd) return;
327 if ((wd->cur.seconds != wd->seconds) || (wd->cur.am_pm != wd->am_pm) ||
328 (wd->cur.edit != wd->edit) || (wd->cur.digedit != wd->digedit))
329 {
330 int i;
331 Evas_Coord mw, mh;
332
333 for (i = 0; i < 6; i++)
334 {
335 if (wd->digit[i])
336 {
337 evas_object_del(wd->digit[i]);
338 wd->digit[i] = NULL;
339 }
340 }
341 if (wd->ampm)
342 {
343 evas_object_del(wd->ampm);
344 wd->ampm = NULL;
345 }
346
347 if ((wd->seconds) && (wd->am_pm))
348 _elm_theme_object_set(obj, wd->clk, "clock", "base-all", style);
349 else if (wd->seconds)
350 _elm_theme_object_set(obj, wd->clk, "clock", "base-seconds", style);
351 else if (wd->am_pm)
352 _elm_theme_object_set(obj, wd->clk, "clock", "base-am_pm", style);
353 else
354 _elm_theme_object_set(obj, wd->clk, "clock", "base", style);
355 edje_object_scale_set(wd->clk, elm_widget_scale_get(obj) *
356 _elm_config->scale);
357
358 for (i = 0; i < 6; i++)
359 {
360 char buf[16];
361
362 if ((!wd->seconds) && (i >= 4)) break;
363 wd->digit[i] = edje_object_add(evas_object_evas_get(wd->clk));
364 _elm_theme_object_set(obj, wd->digit[i], "clock", "flipdigit", style);
365 edje_object_scale_set(wd->digit[i], elm_widget_scale_get(obj) *
366 _elm_config->scale);
367 if ((wd->edit) && (wd->digedit & (1 << i)))
368 edje_object_signal_emit(wd->digit[i], "elm,state,edit,on", "elm");
369 edje_object_signal_callback_add(wd->digit[i], "elm,action,up,start",
370 "", _signal_clock_val_up_start, obj);
371 edje_object_signal_callback_add(wd->digit[i], "elm,action,up,stop",
372 "", _signal_clock_val_change_stop, obj);
373 edje_object_signal_callback_add(wd->digit[i], "elm,action,down,start",
374 "", _signal_clock_val_down_start, obj);
375 edje_object_signal_callback_add(wd->digit[i], "elm,action,down,stop",
376 "", _signal_clock_val_change_stop, obj);
377 mw = mh = -1;
378 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
379 edje_object_size_min_restricted_calc(wd->digit[i], &mw, &mh, mw, mh);
380 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
381 edje_extern_object_min_size_set(wd->digit[i], mw, mh);
382 snprintf(buf, sizeof(buf), "d%i", i);
383 edje_object_part_swallow(wd->clk , buf, wd->digit[i]);
384 evas_object_show(wd->digit[i]);
385 }
386 if (wd->am_pm)
387 {
388 wd->ampm = edje_object_add(evas_object_evas_get(wd->clk));
389 _elm_theme_object_set(obj, wd->ampm, "clock", "flipampm", style);
390 edje_object_scale_set(wd->ampm, elm_widget_scale_get(obj) *
391 _elm_config->scale);
392 if (wd->edit)
393 edje_object_signal_emit(wd->ampm, "elm,state,edit,on", "elm");
394 edje_object_signal_callback_add(wd->ampm, "elm,action,up,start",
395 "", _signal_clock_val_up_start, obj);
396 edje_object_signal_callback_add(wd->ampm, "elm,action,up,stop",
397 "", _signal_clock_val_change_stop, obj);
398 edje_object_signal_callback_add(wd->ampm, "elm,action,down,start",
399 "", _signal_clock_val_down_start, obj);
400 edje_object_signal_callback_add(wd->ampm, "elm,action,down,stop",
401 "", _signal_clock_val_change_stop, obj);
402 mw = mh = -1;
403 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
404 edje_object_size_min_restricted_calc(wd->ampm, &mw, &mh, mw, mh);
405 elm_coords_finger_size_adjust(1, &mw, 2, &mh);
406 edje_extern_object_min_size_set(wd->ampm, mw, mh);
407 edje_object_part_swallow(wd->clk , "ampm", wd->ampm);
408 evas_object_show(wd->ampm);
409 }
410
411 edje_object_size_min_calc(wd->clk, &mw, &mh);
412 evas_object_size_hint_min_set(obj, mw, mh);
413
414 wd->cur.hrs = 0;
415 wd->cur.min = 0;
416 wd->cur.sec = 0;
417 wd->cur.ampm = -1;
418 wd->cur.seconds = wd->seconds;
419 wd->cur.am_pm = wd->am_pm;
420 wd->cur.edit = wd->edit;
421 wd->cur.digedit = wd->digedit;
422 }
423 if (wd->hrs != wd->cur.hrs)
424 {
425 int hrs;
426 int d1, d2, dc1, dc2;
427
428 hrs = wd->hrs;
429 if (wd->am_pm)
430 {
431 if (hrs >= 12)
432 {
433 if (hrs > 12) hrs -= 12;
434 ampm = 1;
435 }
436 else if (!hrs) hrs = 12;
437 }
438 d1 = hrs / 10;
439 d2 = hrs % 10;
440 dc1 = wd->cur.hrs / 10;
441 dc2 = wd->cur.hrs % 10;
442 if (d1 != dc1)
443 {
444 msg.val = d1;
445 edje_object_message_send(wd->digit[0], EDJE_MESSAGE_INT, 1, &msg);
446 }
447 if (d2 != dc2)
448 {
449 msg.val = d2;
450 edje_object_message_send(wd->digit[1], EDJE_MESSAGE_INT, 1, &msg);
451 }
452 wd->cur.hrs = hrs;
453 }
454 if (wd->min != wd->cur.min)
455 {
456 int d1, d2, dc1, dc2;
457
458 d1 = wd->min / 10;
459 d2 = wd->min % 10;
460 dc1 = wd->cur.min / 10;
461 dc2 = wd->cur.min % 10;
462 if (d1 != dc1)
463 {
464 msg.val = d1;
465 edje_object_message_send(wd->digit[2], EDJE_MESSAGE_INT, 1, &msg);
466 }
467 if (d2 != dc2)
468 {
469 msg.val = d2;
470 edje_object_message_send(wd->digit[3], EDJE_MESSAGE_INT, 1, &msg);
471 }
472 wd->cur.min = wd->min;
473 }
474 if (wd->seconds)
475 {
476 if (wd->sec != wd->cur.sec)
477 {
478 int d1, d2, dc1, dc2;
479
480 d1 = wd->sec / 10;
481 d2 = wd->sec % 10;
482 dc1 = wd->cur.sec / 10;
483 dc2 = wd->cur.sec % 10;
484 if (d1 != dc1)
485 {
486 msg.val = d1;
487 edje_object_message_send(wd->digit[4], EDJE_MESSAGE_INT, 1, &msg);
488 }
489 if (d2 != dc2)
490 {
491 msg.val = d2;
492 edje_object_message_send(wd->digit[5], EDJE_MESSAGE_INT, 1, &msg);
493 }
494 wd->cur.sec = wd->sec;
495 }
496 }
497 else
498 wd->cur.sec = -1;
499
500 if (wd->am_pm)
501 {
502 if (wd->hrs >= 12) ampm = 1;
503 if (ampm != wd->cur.ampm)
504 {
505 if (wd->cur.ampm != ampm)
506 {
507 msg.val = ampm;
508 edje_object_message_send(wd->ampm, EDJE_MESSAGE_INT, 1, &msg);
509 }
510 wd->cur.ampm = ampm;
511 }
512 }
513 else
514 wd->cur.ampm = -1;
515}
516
517EAPI Evas_Object *
518elm_clock_add(Evas_Object *parent)
519{
520 Evas_Object *obj;
521 Evas *e;
522 Widget_Data *wd;
523
524 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
525
526 ELM_SET_WIDTYPE(widtype, "clock");
527 elm_widget_type_set(obj, "clock");
528 elm_widget_sub_object_add(parent, obj);
529 elm_widget_data_set(obj, wd);
530 elm_widget_del_hook_set(obj, _del_hook);
531 elm_widget_theme_hook_set(obj, _theme_hook);
532 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
533 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
534 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
535 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
536 elm_widget_can_focus_set(obj, EINA_TRUE);
537
538 wd->clk = edje_object_add(e);
539 elm_widget_resize_object_set(obj, wd->clk);
540
541 wd->cur.ampm = -1;
542 wd->cur.seconds = EINA_TRUE;
543 wd->cur.am_pm = EINA_TRUE;
544 wd->cur.edit = EINA_TRUE;
545 wd->cur.digedit = ELM_CLOCK_EDIT_DEFAULT;
546 wd->first_interval = DEFAULT_FIRST_INTERVAL;
547 wd->timediff = 0;
548
549 _time_update(obj);
550 _ticker(obj);
551
552 evas_object_smart_callbacks_descriptions_set(obj, _signals);
553
554 return obj;
555}
556
557EAPI void
558elm_clock_time_set(Evas_Object *obj, int hrs, int min, int sec)
559{
560 ELM_CHECK_WIDTYPE(obj, widtype);
561 Widget_Data *wd = elm_widget_data_get(obj);
562 if (!wd) return;
563 wd->hrs = hrs;
564 wd->min = min;
565 wd->sec = sec;
566 _timediff_set(wd);
567 _time_update(obj);
568}
569
570EAPI void
571elm_clock_time_get(const Evas_Object *obj, int *hrs, int *min, int *sec)
572{
573 ELM_CHECK_WIDTYPE(obj, widtype);
574 Widget_Data *wd = elm_widget_data_get(obj);
575 if (!wd) return;
576 if (hrs) *hrs = wd->hrs;
577 if (min) *min = wd->min;
578 if (sec) *sec = wd->sec;
579}
580
581EAPI void
582elm_clock_edit_set(Evas_Object *obj, Eina_Bool edit)
583{
584 ELM_CHECK_WIDTYPE(obj, widtype);
585 Widget_Data *wd = elm_widget_data_get(obj);
586 if (!wd) return;
587 wd->edit = edit;
588 if (!edit)
589 _timediff_set(wd);
590 if ((edit) && (wd->digedit == ELM_CLOCK_EDIT_DEFAULT))
591 elm_clock_edit_mode_set(obj, ELM_CLOCK_EDIT_ALL);
592 else
593 _time_update(obj);
594}
595
596EAPI Eina_Bool
597elm_clock_edit_get(const Evas_Object *obj)
598{
599 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
600 Widget_Data *wd = elm_widget_data_get(obj);
601 if (!wd) return EINA_FALSE;
602 return wd->edit;
603}
604
605EAPI void
606elm_clock_edit_mode_set(Evas_Object *obj, Elm_Clock_Edit_Mode digedit)
607{
608 ELM_CHECK_WIDTYPE(obj, widtype);
609 Widget_Data *wd = elm_widget_data_get(obj);
610 if (!wd) return;
611 wd->digedit = digedit;
612 if (digedit == ELM_CLOCK_EDIT_DEFAULT)
613 elm_clock_edit_set(obj, EINA_FALSE);
614 else
615 _time_update(obj);
616}
617
618EAPI Elm_Clock_Edit_Mode
619elm_clock_edit_mode_get(const Evas_Object *obj)
620{
621 ELM_CHECK_WIDTYPE(obj, widtype) 0;
622 Widget_Data *wd = elm_widget_data_get(obj);
623 if (!wd) return 0;
624 return wd->digedit;
625}
626
627EAPI void
628elm_clock_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm)
629{
630 ELM_CHECK_WIDTYPE(obj, widtype);
631 Widget_Data *wd = elm_widget_data_get(obj);
632 if (!wd) return;
633 wd->am_pm = !!am_pm;
634 _time_update(obj);
635}
636
637EAPI Eina_Bool
638elm_clock_show_am_pm_get(const Evas_Object *obj)
639{
640 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
641 Widget_Data *wd = elm_widget_data_get(obj);
642 if (!wd) return EINA_FALSE;
643 return wd->am_pm;
644}
645
646EAPI void
647elm_clock_show_seconds_set(Evas_Object *obj, Eina_Bool seconds)
648{
649 ELM_CHECK_WIDTYPE(obj, widtype);
650 Widget_Data *wd = elm_widget_data_get(obj);
651 if (!wd) return;
652 wd->seconds = !!seconds;
653 _time_update(obj);
654}
655
656EAPI Eina_Bool
657elm_clock_show_seconds_get(const Evas_Object *obj)
658{
659 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
660 Widget_Data *wd = elm_widget_data_get(obj);
661 if (!wd) return EINA_FALSE;
662 return wd->seconds;
663}
664
665EAPI void
666elm_clock_first_interval_set(Evas_Object *obj, double interval)
667{
668 ELM_CHECK_WIDTYPE(obj, widtype);
669 Widget_Data *wd = elm_widget_data_get(obj);
670 if (!wd) return;
671 wd->first_interval = !!interval;
672}
673
674EAPI double
675elm_clock_first_interval_get(const Evas_Object *obj)
676{
677 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
678 Widget_Data *wd = elm_widget_data_get(obj);
679 if (!wd) return 0.0;
680 return wd->first_interval;
681}
diff --git a/libraries/elementary/src/lib/elm_clock.h b/libraries/elementary/src/lib/elm_clock.h
new file mode 100644
index 0000000..d8012ef
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_clock.h
@@ -0,0 +1,308 @@
1/**
2 * @defgroup Clock Clock
3 * @ingroup Elementary
4 *
5 * @image html img/widget/clock/preview-00.png
6 * @image latex img/widget/clock/preview-00.eps
7 *
8 * This is a @b digital clock widget. In its default theme, it has a
9 * vintage "flipping numbers clock" appearance, which will animate
10 * sheets of individual algarisms individually as time goes by.
11 *
12 * A newly created clock will fetch system's time (already
13 * considering local time adjustments) to start with, and will tick
14 * accordingly. It may or may not show seconds.
15 *
16 * Clocks have an @b edition mode. When in it, the sheets will
17 * display extra arrow indications on the top and bottom and the
18 * user may click on them to raise or lower the time values. After
19 * it's told to exit edition mode, it will keep ticking with that
20 * new time set (it keeps the difference from local time).
21 *
22 * Also, when under edition mode, user clicks on the cited arrows
23 * which are @b held for some time will make the clock to flip the
24 * sheet, thus editing the time, continuously and automatically for
25 * the user. The interval between sheet flips will keep growing in
26 * time, so that it helps the user to reach a time which is distant
27 * from the one set.
28 *
29 * The time display is, by default, in military mode (24h), but an
30 * am/pm indicator may be optionally shown, too, when it will
31 * switch to 12h.
32 *
33 * Smart callbacks one can register to:
34 * - "changed" - the clock's user changed the time
35 *
36 * Supported elm_object common APIs.
37 * @li @ref elm_object_signal_emit
38 * @li @ref elm_object_signal_callback_add
39 * @li @ref elm_object_signal_callback_del
40 *
41 * Here is an example on its usage:
42 * @li @ref clock_example
43 */
44
45/**
46 * @addtogroup Clock
47 * @{
48 */
49
50/**
51 * Identifiers for which clock digits should be editable, when a
52 * clock widget is in edition mode. Values may be OR-ed together to
53 * make a mask, naturally.
54 *
55 * @see elm_clock_edit_set()
56 * @see elm_clock_edit_mode_set()
57 */
58typedef enum
59{
60 ELM_CLOCK_EDIT_DEFAULT = 0, /**< Default value. Means that all digits are editable, when in edition mode. */
61 ELM_CLOCK_EDIT_HOUR_DECIMAL = 1 << 0, /**< Decimal algarism of hours value should be editable */
62 ELM_CLOCK_EDIT_HOUR_UNIT = 1 << 1, /**< Unit algarism of hours value should be editable */
63 ELM_CLOCK_EDIT_MIN_DECIMAL = 1 << 2, /**< Decimal algarism of minutes value should be editable */
64 ELM_CLOCK_EDIT_MIN_UNIT = 1 << 3, /**< Unit algarism of minutes value should be editable */
65 ELM_CLOCK_EDIT_SEC_DECIMAL = 1 << 4, /**< Decimal algarism of seconds value should be editable */
66 ELM_CLOCK_EDIT_SEC_UNIT = 1 << 5, /**< Unit algarism of seconds value should be editable */
67 ELM_CLOCK_EDIT_ALL = (1 << 6) - 1 /**< All digits should be editable */
68} Elm_Clock_Edit_Mode;
69
70/**
71 * Add a new clock widget to the given parent Elementary
72 * (container) object
73 *
74 * @param parent The parent object
75 * @return a new clock widget handle or @c NULL, on errors
76 *
77 * This function inserts a new clock widget on the canvas.
78 *
79 * @ingroup Clock
80 */
81EAPI Evas_Object *elm_clock_add(Evas_Object *parent);
82
83/**
84 * Set a clock widget's time, programmatically
85 *
86 * @param obj The clock widget object
87 * @param hrs The hours to set
88 * @param min The minutes to set
89 * @param sec The seconds to set
90 *
91 * This function updates the time that is showed by the clock
92 * widget.
93 *
94 * Values @b must be set within the following ranges:
95 * - 0 - 23, for hours
96 * - 0 - 59, for minutes
97 * - 0 - 59, for seconds,
98 *
99 * even if the clock is not in "military" mode.
100 *
101 * @warning The behavior for values set out of those ranges is @b
102 * undefined.
103 *
104 * @ingroup Clock
105 */
106EAPI void elm_clock_time_set(Evas_Object *obj, int hrs, int min, int sec);
107
108/**
109 * Get a clock widget's time values
110 *
111 * @param obj The clock object
112 * @param[out] hrs Pointer to the variable to get the hours value
113 * @param[out] min Pointer to the variable to get the minutes value
114 * @param[out] sec Pointer to the variable to get the seconds value
115 *
116 * This function gets the time set for @p obj, returning
117 * it on the variables passed as the arguments to function
118 *
119 * @note Use @c NULL pointers on the time values you're not
120 * interested in: they'll be ignored by the function.
121 *
122 * @ingroup Clock
123 */
124EAPI void elm_clock_time_get(const Evas_Object *obj, int *hrs, int *min, int *sec);
125
126/**
127 * Set whether a given clock widget is under <b>edition mode</b> or
128 * under (default) displaying-only mode.
129 *
130 * @param obj The clock object
131 * @param edit @c EINA_TRUE to put it in edition, @c EINA_FALSE to
132 * put it back to "displaying only" mode
133 *
134 * This function makes a clock's time to be editable or not <b>by
135 * user interaction</b>. When in edition mode, clocks @b stop
136 * ticking, until one brings them back to canonical mode. The
137 * elm_clock_edit_mode_set() function will influence which digits
138 * of the clock will be editable. By default, all of them will be
139 * (#ELM_CLOCK_NONE).
140 *
141 * @note am/pm sheets, if being shown, will @b always be editable
142 * under edition mode.
143 *
144 * @see elm_clock_edit_get()
145 *
146 * @ingroup Clock
147 */
148EAPI void elm_clock_edit_set(Evas_Object *obj, Eina_Bool edit);
149
150/**
151 * Retrieve whether a given clock widget is under editing mode
152 * or under (default) displaying-only mode.
153 *
154 * @param obj The clock object
155 * @return @c EINA_TRUE, if it's in edition mode, @c EINA_FALSE otherwise
156 *
157 * This function retrieves whether the clock's time can be edited
158 * or not by user interaction.
159 *
160 * @see elm_clock_edit_set() for more details
161 *
162 * @ingroup Clock
163 */
164EAPI Eina_Bool elm_clock_edit_get(const Evas_Object *obj);
165
166/**
167 * Set what digits of the given clock widget should be editable
168 * when in edition mode.
169 *
170 * @param obj The clock object
171 * @param digedit Bit mask indicating the digits to be editable
172 * (values in #Elm_Clock_Edit_Mode).
173 *
174 * If the @p digedit param is #ELM_CLOCK_NONE, editing will be
175 * disabled on @p obj (same effect as elm_clock_edit_set(), with @c
176 * EINA_FALSE).
177 *
178 * @see elm_clock_edit_mode_get()
179 *
180 * @ingroup Clock
181 */
182EAPI void elm_clock_edit_mode_set(Evas_Object *obj, Elm_Clock_Edit_Mode digedit);
183
184/**
185 * Retrieve what digits of the given clock widget should be
186 * editable when in edition mode.
187 *
188 * @param obj The clock object
189 * @return Bit mask indicating the digits to be editable
190 * (values in #Elm_Clock_Edit_Mode).
191 *
192 * @see elm_clock_edit_mode_set() for more details
193 *
194 * @ingroup Clock
195 */
196EAPI Elm_Clock_Edit_Mode elm_clock_edit_mode_get(const Evas_Object *obj);
197
198/**
199 * Set if the given clock widget must show hours in military or
200 * am/pm mode
201 *
202 * @param obj The clock object
203 * @param am_pm @c EINA_TRUE to put it in am/pm mode, @c EINA_FALSE
204 * to military mode
205 *
206 * This function sets if the clock must show hours in military or
207 * am/pm mode. In some countries like Brazil the military mode
208 * (00-24h-format) is used, in opposition to the USA, where the
209 * am/pm mode is more commonly used.
210 *
211 * @see elm_clock_show_am_pm_get()
212 *
213 * @ingroup Clock
214 */
215EAPI void elm_clock_show_am_pm_set(Evas_Object *obj, Eina_Bool am_pm);
216
217/**
218 * Get if the given clock widget shows hours in military or am/pm
219 * mode
220 *
221 * @param obj The clock object
222 * @return @c EINA_TRUE, if in am/pm mode, @c EINA_FALSE if in
223 * military
224 *
225 * This function gets if the clock shows hours in military or am/pm
226 * mode.
227 *
228 * @see elm_clock_show_am_pm_set() for more details
229 *
230 * @ingroup Clock
231 */
232EAPI Eina_Bool elm_clock_show_am_pm_get(const Evas_Object *obj);
233
234/**
235 * Set if the given clock widget must show time with seconds or not
236 *
237 * @param obj The clock object
238 * @param seconds @c EINA_TRUE to show seconds, @c EINA_FALSE otherwise
239 *
240 * This function sets if the given clock must show or not elapsed
241 * seconds. By default, they are @b not shown.
242 *
243 * @see elm_clock_show_seconds_get()
244 *
245 * @ingroup Clock
246 */
247EAPI void elm_clock_show_seconds_set(Evas_Object *obj, Eina_Bool seconds);
248
249/**
250 * Get whether the given clock widget is showing time with seconds
251 * or not
252 *
253 * @param obj The clock object
254 * @return @c EINA_TRUE if it's showing seconds, @c EINA_FALSE otherwise
255 *
256 * This function gets whether @p obj is showing or not the elapsed
257 * seconds.
258 *
259 * @see elm_clock_show_seconds_set()
260 *
261 * @ingroup Clock
262 */
263EAPI Eina_Bool elm_clock_show_seconds_get(const Evas_Object *obj);
264
265/**
266 * Set the first interval on time updates for a user mouse button hold
267 * on clock widgets' time edition.
268 *
269 * @param obj The clock object
270 * @param interval The first interval value in seconds
271 *
272 * This interval value is @b decreased while the user holds the
273 * mouse pointer either incrementing or decrementing a given the
274 * clock digit's value.
275 *
276 * This helps the user to get to a given time distant from the
277 * current one easier/faster, as it will start to flip quicker and
278 * quicker on mouse button holds.
279 *
280 * The calculation for the next flip interval value, starting from
281 * the one set with this call, is the previous interval divided by
282 * 1.05, so it decreases a little bit.
283 *
284 * The default starting interval value for automatic flips is
285 * @b 0.85 seconds.
286 *
287 * @see elm_clock_first_interval_get()
288 *
289 * @ingroup Clock
290 */
291EAPI void elm_clock_first_interval_set(Evas_Object *obj, double interval);
292
293/**
294 * Get the first interval on time updates for a user mouse button hold
295 * on clock widgets' time edition.
296 *
297 * @param obj The clock object
298 * @return The first interval value, in seconds, set on it
299 *
300 * @see elm_clock_first_interval_set() for more details
301 *
302 * @ingroup Clock
303 */
304EAPI double elm_clock_first_interval_get(const Evas_Object *obj);
305
306/**
307 * @}
308 */
diff --git a/libraries/elementary/src/lib/elm_cnp.c b/libraries/elementary/src/lib/elm_cnp.c
new file mode 100644
index 0000000..cf08189
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_cnp.c
@@ -0,0 +1,1635 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4#include <Elementary.h>
5#include "elm_priv.h"
6
7#ifdef HAVE_MMAN_H
8# include <sys/mman.h>
9#endif
10
11#ifdef HAVE_ELEMENTARY_X
12
13#define ARRAYINIT(foo) [foo] =
14
15//#define DEBUGON 1
16
17#ifdef DEBUGON
18# define cnp_debug(x...) fprintf(stderr, __FILE__": " x)
19#else
20# define cnp_debug(x...)
21#endif
22
23typedef struct _Cnp_Selection Cnp_Selection;
24typedef struct _Escape Escape;
25typedef struct _Tmp_Info Tmp_Info;
26typedef struct _Cnp_Atom Cnp_Atom;
27typedef struct _Saved_Type Saved_Type;
28typedef struct _Dropable Dropable;
29
30typedef Eina_Bool (*Converter_Fn_Cb) (char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
31typedef int (*Response_Handler_Cb) (Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
32typedef int (*Notify_Handler_Cb) (Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
33
34enum
35{
36 CNP_ATOM_TARGETS = 0,
37 CNP_ATOM_ATOM,
38 CNP_ATOM_LISTING_ATOMS = CNP_ATOM_ATOM,
39 CNP_ATOM_text_uri,
40 CNP_ATOM_text_urilist,
41 CNP_ATOM_text_x_vcard,
42 CNP_ATOM_image_png,
43 CNP_ATOM_image_jpeg,
44 CNP_ATOM_image_bmp,
45 CNP_ATOM_image_gif,
46 CNP_ATOM_image_tiff,
47 CNP_ATOM_image_svg,
48 CNP_ATOM_image_xpm,
49 CNP_ATOM_image_tga,
50 CNP_ATOM_image_ppm,
51 CNP_ATOM_XELM,
52 CNP_ATOM_text_html_utf8,
53 CNP_ATOM_text_html,
54 CNP_ATOM_UTF8STRING,
55 CNP_ATOM_STRING,
56 CNP_ATOM_TEXT,
57 CNP_ATOM_text_plain_utf8,
58 CNP_ATOM_text_plain,
59
60 CNP_N_ATOMS,
61};
62
63struct _Cnp_Selection
64{
65 const char *debug;
66 Evas_Object *widget;
67 char *selbuf;
68 Evas_Object *requestwidget;
69 void *udata;
70 Elm_Sel_Format requestformat;
71 Elm_Drop_Cb datacb;
72 Eina_Bool (*set) (Ecore_X_Window, const void *data, int size);
73 Eina_Bool (*clear) (void);
74 void (*request) (Ecore_X_Window, const char *target);
75
76 Elm_Sel_Format format;
77 Ecore_X_Selection ecore_sel;
78
79 Eina_Bool active : 1;
80};
81
82struct _Escape
83{
84 const char *escape;
85 const char *value;
86};
87
88struct _Tmp_Info
89{
90 char *filename;
91 void *map;
92 int fd;
93 int len;
94};
95
96struct _Cnp_Atom
97{
98 const char *name;
99 Elm_Sel_Format formats;
100 /* Called by ecore to do conversion */
101 Converter_Fn_Cb converter;
102 Response_Handler_Cb response;
103 Notify_Handler_Cb notify;
104 /* Atom */
105 Ecore_X_Atom atom;
106};
107
108struct _Saved_Type
109{
110 const char **types;
111 char *imgfile;
112 int ntypes;
113 int x, y;
114 Eina_Bool textreq: 1;
115};
116
117struct _Dropable
118{
119 Evas_Object *obj;
120 /* FIXME: Cache window */
121 Elm_Sel_Format types;
122 Elm_Drop_Cb dropcb;
123 void *cbdata;
124};
125
126static Tmp_Info *elm_cnp_tempfile_create(int size);
127static int tmpinfo_free(Tmp_Info *tmp);
128
129static Eina_Bool _elm_cnp_init(void);
130static Eina_Bool selection_clear(void *udata __UNUSED__, int type, void *event);
131static Eina_Bool selection_notify(void *udata __UNUSED__, int type, void *event);
132
133static Eina_Bool targets_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
134static Eina_Bool text_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
135static Eina_Bool general_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
136static Eina_Bool image_converter(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
137static Eina_Bool vcard_send(char *target, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize);
138
139static int response_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *);
140
141static int notify_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
142static int notify_handler_text(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
143static int notify_handler_image(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
144static int notify_handler_uri(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
145static int notify_handler_html(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify);
146static int vcard_receive(Cnp_Selection *sed, Ecore_X_Event_Selection_Notify *notify);
147
148static Eina_Bool pasteimage_append(char *file, Evas_Object *entry);
149
150static Cnp_Atom atoms[CNP_N_ATOMS] = {
151 [CNP_ATOM_TARGETS] = {
152 "TARGETS",
153 ELM_SEL_FORMAT_TARGETS,
154 targets_converter,
155 response_handler_targets,
156 notify_handler_targets,
157 0
158 },
159 [CNP_ATOM_ATOM] = {
160 "ATOM", // for opera browser
161 ELM_SEL_FORMAT_TARGETS,
162 targets_converter,
163 response_handler_targets,
164 notify_handler_targets,
165 0
166 },
167 [CNP_ATOM_XELM] = {
168 "application/x-elementary-markup",
169 ELM_SEL_FORMAT_MARKUP,
170 general_converter,
171 NULL,
172 NULL,
173 0
174 },
175 [CNP_ATOM_text_uri] = {
176 "text/uri",
177 ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE, /* Either images or entries */
178 general_converter,
179 NULL,
180 notify_handler_uri,
181 0
182 },
183 [CNP_ATOM_text_urilist] = {
184 "text/uri-list",
185 ELM_SEL_FORMAT_IMAGE,
186 general_converter,
187 NULL,
188 notify_handler_uri,
189 0
190 },
191 [CNP_ATOM_text_x_vcard] = {
192 "text/x-vcard",
193 ELM_SEL_FORMAT_VCARD,
194 vcard_send, NULL,
195 vcard_receive, 0
196 },
197 [CNP_ATOM_image_png] = {
198 "image/png",
199 ELM_SEL_FORMAT_IMAGE,
200 image_converter,
201 NULL,
202 notify_handler_image,
203 0
204 },
205 [CNP_ATOM_image_jpeg] = {
206 "image/jpeg",
207 ELM_SEL_FORMAT_IMAGE,
208 image_converter,
209 NULL,
210 notify_handler_image,/* Raw image data is the same */
211 0
212 },
213 [CNP_ATOM_image_bmp] = {
214 "image/x-ms-bmp",
215 ELM_SEL_FORMAT_IMAGE,
216 image_converter,
217 NULL,
218 notify_handler_image,/* Raw image data is the same */
219 0
220 },
221 [CNP_ATOM_image_gif] = {
222 "image/gif",
223 ELM_SEL_FORMAT_IMAGE,
224 image_converter,
225 NULL,
226 notify_handler_image,/* Raw image data is the same */
227 0
228 },
229 [CNP_ATOM_image_tiff] = {
230 "image/tiff",
231 ELM_SEL_FORMAT_IMAGE,
232 image_converter,
233 NULL,
234 notify_handler_image,/* Raw image data is the same */
235 0
236 },
237 [CNP_ATOM_image_svg] = {
238 "image/svg+xml",
239 ELM_SEL_FORMAT_IMAGE,
240 image_converter,
241 NULL,
242 notify_handler_image,/* Raw image data is the same */
243 0
244 },
245 [CNP_ATOM_image_xpm] = {
246 "image/x-xpixmap",
247 ELM_SEL_FORMAT_IMAGE,
248 image_converter,
249 NULL,
250 notify_handler_image,/* Raw image data is the same */
251 0
252 },
253 [CNP_ATOM_image_tga] = {
254 "image/x-tga",
255 ELM_SEL_FORMAT_IMAGE,
256 image_converter,
257 NULL,
258 notify_handler_image,/* Raw image data is the same */
259 0
260 },
261 [CNP_ATOM_image_ppm] = {
262 "image/x-portable-pixmap",
263 ELM_SEL_FORMAT_IMAGE,
264 image_converter,
265 NULL,
266 notify_handler_image,/* Raw image data is the same */
267 0
268 },
269 [CNP_ATOM_text_html_utf8] = {
270 "text/html;charset=utf-8",
271 ELM_SEL_FORMAT_HTML,
272 general_converter,
273 NULL,
274 notify_handler_html,
275 0
276 },
277 [CNP_ATOM_text_html] = {
278 "text/html",
279 ELM_SEL_FORMAT_HTML,
280 general_converter,
281 NULL,
282 notify_handler_html, /* No encoding: Webkit only */
283 0
284 },
285 [CNP_ATOM_UTF8STRING] = {
286 "UTF8_STRING",
287 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
288 text_converter,
289 NULL,
290 notify_handler_text,
291 0
292 },
293 [CNP_ATOM_STRING] = {
294 "STRING",
295 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
296 text_converter,
297 NULL,
298 notify_handler_text,
299 0
300 },
301 [CNP_ATOM_TEXT] = {
302 "TEXT",
303 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
304 text_converter,
305 NULL,
306 NULL,
307 0
308 },
309 [CNP_ATOM_text_plain_utf8] = {
310 "text/plain;charset=utf-8",
311 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
312 text_converter,
313 NULL,
314 NULL,
315 0
316 },
317 [CNP_ATOM_text_plain] = {
318 "text/plain",
319 ELM_SEL_FORMAT_TEXT | ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_HTML,
320 text_converter,
321 NULL,
322 NULL,
323 0
324 },
325};
326
327static Cnp_Selection selections[ELM_SEL_TYPE_CLIPBOARD + 1] = {
328 ARRAYINIT(ELM_SEL_TYPE_PRIMARY) {
329 .debug = "Primary",
330 .ecore_sel = ECORE_X_SELECTION_PRIMARY,
331 .set = ecore_x_selection_primary_set,
332 .clear = ecore_x_selection_primary_clear,
333 .request = ecore_x_selection_primary_request,
334 },
335 ARRAYINIT(ELM_SEL_TYPE_SECONDARY) {
336 .debug = "Secondary",
337 .ecore_sel = ECORE_X_SELECTION_SECONDARY,
338 .set = ecore_x_selection_secondary_set,
339 .clear = ecore_x_selection_secondary_clear,
340 .request = ecore_x_selection_secondary_request,
341 },
342 ARRAYINIT(ELM_SEL_TYPE_XDND) {
343 .debug = "XDnD",
344 .ecore_sel = ECORE_X_SELECTION_XDND,
345 .request = ecore_x_selection_xdnd_request,
346 },
347 ARRAYINIT(ELM_SEL_TYPE_CLIPBOARD) {
348 .debug = "Clipboard",
349 .ecore_sel = ECORE_X_SELECTION_CLIPBOARD,
350 .set = ecore_x_selection_clipboard_set,
351 .clear = ecore_x_selection_clipboard_clear,
352 .request = ecore_x_selection_clipboard_request,
353 },
354};
355
356/* Data for DND in progress */
357static Saved_Type savedtypes = { NULL, NULL, 0, 0, 0, EINA_FALSE };
358
359static void (*dragdonecb) (void *data, Evas_Object *obj) = NULL;
360static void *dragdonedata = NULL;
361
362static int _elm_cnp_init_count = 0;
363
364/**
365 * Drag & Drop functions
366 */
367
368/* FIXME: Way too many globals */
369static Eina_List *drops = NULL;
370static Evas_Object *dragwin = NULL;
371static int _dragx = 0, _dragy = 0;
372static Ecore_Event_Handler *handler_pos = NULL;
373static Ecore_Event_Handler *handler_drop = NULL;
374static Ecore_Event_Handler *handler_enter = NULL;
375static Ecore_Event_Handler *handler_status = NULL;
376
377#endif
378
379/* Stringshared, so I can just compare pointers later */
380static const char *text_uri;
381
382Eina_Bool
383elm_selection_selection_has_owner(void)
384{
385#ifdef HAVE_ELEMENTARY_X
386 return !!ecore_x_selection_owner_get(ECORE_X_ATOM_SELECTION_CLIPBOARD);
387#else
388 return EINA_FALSE;
389#endif
390}
391
392EAPI Eina_Bool
393elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
394 Elm_Sel_Format format, const void *selbuf, size_t buflen)
395{
396#ifdef HAVE_ELEMENTARY_X
397 Evas_Object *top = elm_widget_top_get(obj);
398 Ecore_X_Window xwin;
399 Cnp_Selection *sel;
400
401 if (top) xwin = elm_win_xwindow_get(top);
402 else xwin = elm_win_xwindow_get(obj);
403 if ((!xwin) || (selection > ELM_SEL_TYPE_CLIPBOARD))
404 return EINA_FALSE;
405 if (!_elm_cnp_init_count) _elm_cnp_init();
406 if ((!selbuf) && (format != ELM_SEL_FORMAT_IMAGE))
407 return elm_object_cnp_selection_clear(obj, selection);
408
409 sel = selections + selection;
410
411 sel->active = EINA_TRUE;
412 sel->widget = obj;
413 sel->set(xwin, &selection, sizeof(Elm_Sel_Type));
414 sel->format = format;
415
416 if (selbuf)
417 {
418 if (format == ELM_SEL_FORMAT_IMAGE)
419 {
420 // selbuf is actual image data, not text/string
421 sel->selbuf = malloc(buflen);
422 memcpy(sel->selbuf, selbuf, buflen);
423 }
424 else
425 sel->selbuf = strdup((char*)selbuf);
426 }
427 else
428 sel->selbuf = NULL;
429
430 return EINA_TRUE;
431#else
432 return EINA_FALSE;
433#endif
434}
435
436EAPI Eina_Bool
437elm_object_cnp_selection_clear(Evas_Object *obj, Elm_Sel_Type selection)
438{
439#ifdef HAVE_ELEMENTARY_X
440 Cnp_Selection *sel;
441
442 if ((unsigned int)selection > (unsigned int)ELM_SEL_TYPE_CLIPBOARD)
443 return EINA_FALSE;
444 if (!_elm_cnp_init_count) _elm_cnp_init();
445
446 sel = selections + selection;
447
448 /* No longer this selection: Consider it gone! */
449 if ((!sel->active) || (sel->widget != obj)) return EINA_TRUE;
450
451 sel->active = EINA_FALSE;
452 sel->widget = NULL;
453 if (sel->selbuf)
454 {
455 free(sel->selbuf);
456 sel->selbuf = NULL;
457 }
458 sel->clear();
459
460 return EINA_TRUE;
461#else
462 return EINA_FALSE;
463#endif
464}
465
466EAPI Eina_Bool
467elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
468 Elm_Sel_Format format, Elm_Drop_Cb datacb, void *udata)
469{
470#ifdef HAVE_ELEMENTARY_X
471 Evas_Object *top;
472 Cnp_Selection *sel;
473
474 if (selection > ELM_SEL_TYPE_CLIPBOARD)
475 return EINA_FALSE;
476 if (!_elm_cnp_init_count) _elm_cnp_init();
477
478 sel = selections + selection;
479 top = elm_widget_top_get(obj);
480 if (!top) return EINA_FALSE;
481
482 sel->requestformat = format;
483 sel->requestwidget = obj;
484 sel->request(elm_win_xwindow_get(top), ECORE_X_SELECTION_TARGET_TARGETS);
485 sel->datacb = datacb;
486 sel->udata = udata;
487
488 return EINA_TRUE;
489#else
490 return EINA_FALSE;
491#endif
492}
493
494#ifdef HAVE_ELEMENTARY_X
495
496static Eina_Bool
497_elm_cnp_init(void)
498{
499 int i;
500
501 if (_elm_cnp_init_count++) return EINA_TRUE;
502 for (i = 0; i < CNP_N_ATOMS; i++)
503 {
504 atoms[i].atom = ecore_x_atom_get(atoms[i].name);
505 ecore_x_selection_converter_atom_add(atoms[i].atom,
506 atoms[i].converter);
507 }
508
509 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR, selection_clear, NULL);
510 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY, selection_notify, NULL);
511
512 text_uri = eina_stringshare_add("text/uri-list");
513 return EINA_TRUE;
514}
515
516static Eina_Bool
517selection_clear(void *udata __UNUSED__, int type __UNUSED__, void *event)
518{
519 Ecore_X_Event_Selection_Clear *ev = event;
520 Cnp_Selection *sel;
521 int i;
522
523 for (i = 0; i <= ELM_SEL_TYPE_CLIPBOARD; i++)
524 {
525 if (selections[i].ecore_sel == ev->selection) break;
526 }
527 cnp_debug("selection %d clear\n", i);
528 /* Not me... Don't care */
529 if (i > ELM_SEL_TYPE_CLIPBOARD) return ECORE_CALLBACK_PASS_ON;
530
531 sel = selections + i;
532 sel->active = EINA_FALSE;
533 sel->widget = NULL;
534 if (sel->selbuf)
535 {
536 free(sel->selbuf);
537 sel->selbuf = NULL;
538 }
539
540 return ECORE_CALLBACK_PASS_ON;
541}
542
543
544/*
545 * Response to a selection notify:
546 * - So we have asked for the selection list.
547 * - If it's the targets list, parse it, and fire of what we want,
548 * else it's the data we want.
549 */
550static Eina_Bool
551selection_notify(void *udata __UNUSED__, int type __UNUSED__, void *event)
552{
553 Ecore_X_Event_Selection_Notify *ev = event;
554 Cnp_Selection *sel;
555 int i;
556
557 cnp_debug("selection notify callback: %d\n",ev->selection);
558 switch (ev->selection)
559 {
560 case ECORE_X_SELECTION_PRIMARY:
561 sel = selections + ELM_SEL_TYPE_PRIMARY;
562 break;
563 case ECORE_X_SELECTION_SECONDARY:
564 sel = selections + ELM_SEL_TYPE_SECONDARY;
565 break;
566 case ECORE_X_SELECTION_XDND:
567 sel = selections + ELM_SEL_TYPE_XDND;
568 break;
569 case ECORE_X_SELECTION_CLIPBOARD:
570 sel = selections + ELM_SEL_TYPE_CLIPBOARD;
571 break;
572 default:
573 return ECORE_CALLBACK_PASS_ON;
574 }
575 cnp_debug("Target is %s\n", ev->target);
576
577 for (i = 0; i < CNP_N_ATOMS; i++)
578 {
579 if (!strcmp(ev->target, atoms[i].name))
580 {
581 if (atoms[i].notify)
582 {
583 cnp_debug("Found something: %s\n", atoms[i].name);
584 atoms[i].notify(sel, ev);
585 }
586 else
587 {
588 cnp_debug("Ignored: No handler!\n");
589 }
590 }
591 }
592
593 return ECORE_CALLBACK_PASS_ON;
594}
595
596static Elm_Sel_Format
597_get_selection_type(void *data, int size)
598{
599 if (size == sizeof(Elm_Sel_Type))
600 {
601 Cnp_Selection *sel = selections + *((int *)data);
602 if (sel->active &&
603 (sel->format >= ELM_SEL_FORMAT_TARGETS) &&
604 (sel->format <= ELM_SEL_FORMAT_HTML))
605 return sel->format;
606 }
607 return ELM_SEL_FORMAT_NONE;
608}
609
610static Eina_Bool
611targets_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype, int *typesize)
612{
613 int i,count;
614 Ecore_X_Atom *aret;
615 Cnp_Selection *sel;
616 Elm_Sel_Format seltype;
617
618 if (!data_ret) return EINA_FALSE;
619
620 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
621 {
622 /* TODO : fallback into precise type */
623 seltype = ELM_SEL_FORMAT_TEXT;
624 }
625 else
626 {
627 sel = selections + *((int *)data);
628 seltype = sel->format;
629 }
630
631 for (i = 0, count = 0; i < CNP_N_ATOMS ; i++)
632 {
633 if (seltype & atoms[i].formats) count++;
634 }
635
636 aret = malloc(sizeof(Ecore_X_Atom) * count);
637 for (i = 0, count = 0; i < CNP_N_ATOMS; i++)
638 {
639 if (seltype & atoms[i].formats) aret[count ++] = atoms[i].atom;
640 }
641
642 *data_ret = aret;
643 if (typesize) *typesize = 32 /* urk */;
644 if (ttype) *ttype = ECORE_X_ATOM_ATOM;
645 if (size_ret) *size_ret = count;
646
647 return EINA_TRUE;
648}
649
650static Eina_Bool
651image_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__)
652{
653 cnp_debug("Image converter called\n");
654 return EINA_TRUE;
655}
656
657static Eina_Bool
658vcard_send(char *target __UNUSED__, void *data __UNUSED__, int size __UNUSED__, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
659{
660 Cnp_Selection *sel;
661
662 cnp_debug("Vcard send called\n");
663
664 sel = selections + *((int *)data);
665
666 if (data_ret) *data_ret = strdup(sel->selbuf);
667 if (size_ret) *size_ret = strlen(sel->selbuf);
668
669 return EINA_TRUE;
670}
671
672static Eina_Bool
673is_uri_type_data(Cnp_Selection *sel __UNUSED__, Ecore_X_Event_Selection_Notify *notify)
674{
675 Ecore_X_Selection_Data *data;
676 char *p;
677
678 data = notify->data;
679 cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
680 if (data->content == ECORE_X_SELECTION_CONTENT_FILES) return EINA_TRUE;
681 p = (char *)data->data;
682 if (!p) return EINA_TRUE;
683
684 cnp_debug("Got %s\n", p);
685 if (strncmp(p, "file://", 7))
686 {
687 if (*p != '/') return EINA_FALSE;
688 }
689
690 return EINA_TRUE;
691}
692
693/*
694 * Callback to handle a targets response on a selection request:
695 * So pick the format we'd like; and then request it.
696 */
697static int
698notify_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
699{
700 Ecore_X_Selection_Data_Targets *targets;
701 Ecore_X_Atom *atomlist;
702 Evas_Object *top;
703 int i, j;
704
705 targets = notify->data;
706 atomlist = (Ecore_X_Atom *)(targets->data.data);
707
708 for (j = (CNP_ATOM_LISTING_ATOMS+1); j < CNP_N_ATOMS; j++)
709 {
710 cnp_debug("\t%s %d\n", atoms[j].name, atoms[j].atom);
711 if (!(atoms[j].formats & sel->requestformat)) continue;
712 for (i = 0; i < targets->data.length; i++)
713 {
714 if ((atoms[j].atom == atomlist[i]) && (atoms[j].notify))
715 {
716 if ((j == CNP_ATOM_text_uri) ||
717 (j == CNP_ATOM_text_urilist))
718 {
719 if (!is_uri_type_data(sel, notify)) continue;
720 }
721 cnp_debug("Atom %s matches\n",atoms[j].name);
722 goto done;
723 }
724 }
725 }
726
727 cnp_debug("Couldn't find anything that matches\n");
728 return ECORE_CALLBACK_PASS_ON;
729
730done:
731 top = elm_widget_top_get(sel->requestwidget);
732 if (!top) top = sel->requestwidget;
733 cnp_debug("Sending request for %s\n", atoms[j].name);
734 sel->request(elm_win_xwindow_get(top), atoms[j].name);
735
736 return ECORE_CALLBACK_PASS_ON;
737}
738
739static int
740response_handler_targets(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
741{
742 Ecore_X_Selection_Data_Targets *targets;
743 Ecore_X_Atom *atomlist;
744 Evas_Object *top;
745 int i,j;
746
747 targets = notify->data;
748 atomlist = (Ecore_X_Atom *)(targets->data.data);
749
750 for (j = (CNP_ATOM_LISTING_ATOMS+1); j < CNP_N_ATOMS; j++)
751 {
752 if (!(atoms[j].formats & sel->requestformat)) continue;
753 for (i = 0 ; i < targets->data.length ; i ++)
754 {
755 if ((atoms[j].atom == atomlist[i]) && (atoms[j].response))
756 {
757 /* Found a match: Use it */
758 goto found;
759 }
760 }
761 }
762 cnp_debug("No matching type found\n");
763 return 0;
764
765found:
766 top = elm_widget_top_get(sel->requestwidget);
767 if (!top) return 0;
768
769 sel->request(elm_win_xwindow_get(top), atoms[j].name);
770 return 0;
771}
772
773
774static int
775notify_handler_text(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
776{
777 Ecore_X_Selection_Data *data;
778 char *str;
779 char *mkupstr;
780
781 data = notify->data;
782 str = malloc(sizeof(char) * (data->length + 1));
783 if (!str) return 0;
784 strncpy(str, (char *)data->data, data->length);
785 str[data->length] = '\0';
786
787 if (sel->datacb)
788 {
789 Elm_Selection_Data ddata;
790
791 ddata.x = ddata.y = 0;
792 ddata.format = ELM_SEL_FORMAT_TEXT;
793 ddata.data = data->data;
794 ddata.len = data->length;
795 sel->datacb(sel->udata, sel->widget, &ddata);
796 free(str);
797 return 0;
798 }
799
800 cnp_debug("Notify handler text %d %d %p\n", data->format,
801 data->length, data->data);
802 mkupstr = _elm_util_text_to_mkup((const char *)str);
803 cnp_debug("String is %s (from %s)\n", str, data->data);
804 _elm_entry_entry_paste(sel->requestwidget, mkupstr);
805 free(str);
806 free(mkupstr);
807 return 0;
808}
809
810
811/**
812 * So someone is pasting an image into my entry or widget...
813 */
814static int
815notify_handler_uri(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
816{
817 Ecore_X_Selection_Data *data;
818 Ecore_X_Selection_Data_Files *files;
819 char *p, *stripstr;
820
821 data = notify->data;
822 cnp_debug("data->format is %d %p %p\n", data->format, notify, data);
823 if (data->content == ECORE_X_SELECTION_CONTENT_FILES)
824 {
825 cnp_debug("got a files list\n");
826 files = notify->data;
827 if (files->num_files > 1)
828 {
829 /* Don't handle many items */
830 cnp_debug("more then one file: Bailing\n");
831 return 0;
832 }
833 stripstr = p = strdup(files->files[0]);
834 }
835 else
836 {
837 stripstr = p = malloc(data->length * sizeof(char) + 1);
838 memcpy(stripstr, data->data, data->length);
839 stripstr[data->length] = 0;
840 }
841
842 if (!p)
843 {
844 cnp_debug("Couldn't find a file\n");
845 return 0;
846 }
847 cnp_debug("Got %s\n",p);
848 if (strncmp(p, "file://", 7))
849 {
850 /* Try and continue if it looks sane */
851 if (*p != '/')
852 {
853 free(p);
854 return 0;
855 }
856 }
857 else
858 {
859 p += strlen("file://");
860 }
861
862 if (savedtypes.imgfile) free((void*)savedtypes.imgfile);
863 if (savedtypes.textreq)
864 {
865 savedtypes.textreq = 0;
866 savedtypes.imgfile = strdup(p);
867 }
868 else
869 {
870 pasteimage_append(p, sel->requestwidget);
871 }
872 free(stripstr);
873 return 0;
874}
875
876/**
877 * Just receieved an vcard, either through cut and paste, or dnd.
878 */
879static int
880vcard_receive(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
881{
882 Dropable *dropable;
883 Eina_List *l;
884 Ecore_X_Selection_Data *data;
885
886 data = notify->data;
887 cnp_debug("vcard receive\n");
888
889 if (sel == (selections + ELM_SEL_TYPE_XDND))
890 {
891 Elm_Selection_Data ddata;
892
893 cnp_debug("drag & drop\n");
894 /* FIXME: this needs to be generic: Used for all receives */
895 EINA_LIST_FOREACH(drops, l, dropable)
896 {
897 if (dropable->obj == sel->requestwidget) break;
898 }
899 if (!dropable)
900 {
901 cnp_debug("Unable to find drop object");
902 ecore_x_dnd_send_finished();
903 return 0;
904 }
905 dropable = eina_list_data_get(l);
906 ddata.x = savedtypes.x;
907 ddata.y = savedtypes.y;
908 ddata.format = ELM_SEL_FORMAT_VCARD;
909 ddata.data = data->data;
910 ddata.len = data->length;
911 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
912 ecore_x_dnd_send_finished();
913 }
914 else if (sel->datacb)
915 {
916 Elm_Selection_Data ddata;
917 ddata.x = ddata.y = 0;
918 ddata.format = ELM_SEL_FORMAT_IMAGE;
919 ddata.data = data->data;
920 ddata.len = data->length;
921 sel->datacb(sel->udata, sel->widget, &ddata);
922 }
923 else
924 {
925 cnp_debug("Paste request\n");
926 }
927
928 return 0;
929
930}
931
932
933static int
934notify_handler_image(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
935{
936 Ecore_X_Selection_Data *data;
937 Tmp_Info *tmp;
938
939 cnp_debug("got a image file!\n");
940 data = notify->data;
941
942 cnp_debug("Size if %d\n", data->length);
943
944 if (sel->datacb)
945 {
946 Elm_Selection_Data ddata;
947
948 ddata.x = ddata.y = 0;
949 ddata.format = ELM_SEL_FORMAT_IMAGE;
950 ddata.data = data->data;
951 ddata.len = data->length;
952 sel->datacb(sel->udata, sel->widget, &ddata);
953 return 0;
954 }
955
956 /* generate tmp name */
957 tmp = elm_cnp_tempfile_create(data->length);
958 memcpy(tmp->map, data->data, data->length);
959 munmap(tmp->map, data->length);
960
961 /* FIXME: Add to paste image data to clean up */
962 pasteimage_append(tmp->filename, sel->requestwidget);
963
964 tmpinfo_free(tmp);
965 return 0;
966}
967
968
969/**
970 * Warning: Generic text/html can';t handle it sanely.
971 * Firefox sends ucs2 (i think).
972 * chrome sends utf8... blerg
973 */
974static int
975notify_handler_html(Cnp_Selection *sel, Ecore_X_Event_Selection_Notify *notify)
976{
977 Ecore_X_Selection_Data *data;
978
979 cnp_debug("Got some HTML: Checking encoding is useful\n");
980 data = notify->data;
981
982 if (sel->datacb)
983 {
984 Elm_Selection_Data ddata;
985 ddata.x = ddata.y = 0;
986 ddata.format = ELM_SEL_FORMAT_HTML;
987 ddata.data = data->data;
988 ddata.len = data->length;
989 sel->datacb(sel->udata, sel->widget, &ddata);
990 return 0;
991 }
992
993 char *stripstr = malloc(sizeof(char) * (data->length + 1));
994 strncpy(stripstr, (char *)data->data, data->length);
995 stripstr[data->length] = '\0';
996 cnp_debug("String is %s (%d bytes)\n", stripstr, data->length);
997 _elm_entry_entry_paste(sel->requestwidget, stripstr);
998 free(stripstr);
999 return 0;
1000}
1001
1002
1003static Eina_Bool
1004text_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
1005{
1006 Cnp_Selection *sel;
1007
1008 cnp_debug("text converter\n");
1009 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
1010 {
1011 if (data_ret)
1012 {
1013 *data_ret = malloc(size * sizeof(char) + 1);
1014 memcpy(*data_ret, data, size);
1015 ((char**)(data_ret))[0][size] = 0;
1016 }
1017 if (size_ret) *size_ret = size;
1018 return EINA_TRUE;
1019 }
1020 sel = selections + *((int *)data);
1021 if (!sel->active) return EINA_TRUE;
1022
1023 if ((sel->format & ELM_SEL_FORMAT_MARKUP) ||
1024 (sel->format & ELM_SEL_FORMAT_HTML))
1025 {
1026 *data_ret = _elm_util_mkup_to_text(sel->selbuf);
1027 if (size_ret) *size_ret = strlen(*data_ret);
1028 }
1029 else if (sel->format & ELM_SEL_FORMAT_TEXT)
1030 {
1031 *data_ret = strdup(sel->selbuf);
1032 *size_ret = strlen(sel->selbuf);
1033 }
1034 else if (sel->format & ELM_SEL_FORMAT_IMAGE)
1035 {
1036 cnp_debug("Image %s\n", evas_object_type_get(sel->widget));
1037 cnp_debug("Elm type: %s\n", elm_object_widget_type_get(sel->widget));
1038 evas_object_image_file_get(elm_photocam_internal_image_get(sel->widget),
1039 (const char **)data_ret, NULL);
1040 if (!*data_ret) *data_ret = strdup("No file");
1041 else *data_ret = strdup(*data_ret);
1042 *size_ret = strlen(*data_ret);
1043 }
1044 return EINA_TRUE;
1045}
1046
1047static Eina_Bool
1048general_converter(char *target __UNUSED__, void *data, int size, void **data_ret, int *size_ret, Ecore_X_Atom *ttype __UNUSED__, int *typesize __UNUSED__)
1049{
1050 if (_get_selection_type(data, size) == ELM_SEL_FORMAT_NONE)
1051 {
1052 if (data_ret)
1053 {
1054 *data_ret = malloc(size * sizeof(char) + 1);
1055 memcpy(*data_ret, data, size);
1056 ((char**)(data_ret))[0][size] = 0;
1057 }
1058 if (size_ret) *size_ret = size;
1059 }
1060 else
1061 {
1062 Cnp_Selection *sel = selections + *((int *)data);
1063 if (data_ret) *data_ret = strdup(sel->selbuf);
1064 if (size_ret) *size_ret = strlen(sel->selbuf);
1065 }
1066 return EINA_TRUE;
1067}
1068
1069static Eina_Bool
1070pasteimage_append(char *file, Evas_Object *entry)
1071{
1072 char *entrytag;
1073 int len;
1074 static const char *tagstring = "<item absize=240x180 href=file://%s></item>";
1075
1076 if ((!file) || (!entry)) return EINA_FALSE;
1077
1078 len = strlen(tagstring)+strlen(file);
1079
1080 entrytag = alloca(len + 1);
1081 snprintf(entrytag, len + 1, tagstring, file);
1082 _elm_entry_entry_paste(entry, entrytag);
1083
1084 return EINA_TRUE;
1085}
1086
1087static Eina_Bool
1088_dnd_enter(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1089{
1090 Ecore_X_Event_Xdnd_Enter *enter = ev;
1091 int i;
1092
1093 /* Skip it */
1094 if ((!enter) || (!enter->num_types) || (!enter->types)) return EINA_TRUE;
1095
1096 cnp_debug("Types\n");
1097 savedtypes.ntypes = enter->num_types;
1098 if (savedtypes.types) free(savedtypes.types);
1099 savedtypes.types = malloc(sizeof(char *) * enter->num_types);
1100 if (!savedtypes.types) return EINA_FALSE;
1101
1102 for (i = 0; i < enter->num_types; i++)
1103 {
1104 savedtypes.types[i] = eina_stringshare_add(enter->types[i]);
1105 cnp_debug("Type is %s %p %p\n", enter->types[i],
1106 savedtypes.types[i],text_uri);
1107 if (savedtypes.types[i] == text_uri)
1108 {
1109 /* Request it, so we know what it is */
1110 cnp_debug("Sending uri request\n");
1111 savedtypes.textreq = 1;
1112 if (savedtypes.imgfile) free((void*)savedtypes.imgfile);
1113 savedtypes.imgfile = NULL;
1114 ecore_x_selection_xdnd_request(enter->win, text_uri);
1115 }
1116 }
1117
1118 /* FIXME: Find an object and make it current */
1119 return EINA_TRUE;
1120}
1121
1122static Eina_Bool
1123_dnd_drop(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1124{
1125 struct _Ecore_X_Event_Xdnd_Drop *drop;
1126 Dropable *dropable;
1127 Eina_List *l;
1128 Ecore_Evas *ee;
1129 Ecore_X_Window xwin;
1130 Elm_Selection_Data ddata;
1131 int x, y, w, h;
1132 int i, j;
1133
1134 drop = ev;
1135
1136 // check we still have something to drop
1137 if (!drops) return EINA_TRUE;
1138
1139 /* Find any widget in our window; then work out geometry rel to our window */
1140 for (l = drops; l; l = l->next)
1141 {
1142 dropable = l->data;
1143 xwin = (Ecore_X_Window)ecore_evas_window_get
1144 (ecore_evas_ecore_evas_get(evas_object_evas_get
1145 (dropable->obj)));
1146 if (xwin == drop->win) break;
1147 }
1148 /* didn't find a window */
1149 if (!l) return EINA_TRUE;
1150
1151 /* Calculate real (widget relative) position */
1152 // - window position
1153 // - widget position
1154 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(dropable->obj));
1155 ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
1156 savedtypes.x = drop->position.x - x;
1157 savedtypes.y = drop->position.y - y;
1158
1159 cnp_debug("Drop position is %d,%d\n", savedtypes.x, savedtypes.y);
1160
1161 for (; l; l = l->next)
1162 {
1163 dropable = l->data;
1164 evas_object_geometry_get(dropable->obj, &x, &y, &w, &h);
1165 if ((savedtypes.x >= x) && (savedtypes.y >= y) &&
1166 (savedtypes.x < x + w) && (savedtypes.y < y + h))
1167 break; /* found! */
1168 }
1169
1170 if (!l) return EINA_TRUE; /* didn't find one */
1171
1172 evas_object_geometry_get(dropable->obj, &x, &y, NULL, NULL);
1173 savedtypes.x -= x;
1174 savedtypes.y -= y;
1175
1176 /* Find our type from the previous list */
1177 for (i = 0; i < CNP_N_ATOMS; i++)
1178 {
1179 for (j = 0; j < savedtypes.ntypes; j++)
1180 {
1181 if (!strcmp(savedtypes.types[j], atoms[i].name)) goto found;
1182 }
1183 }
1184
1185 cnp_debug("Didn't find a target\n");
1186 return EINA_TRUE;
1187
1188found:
1189 cnp_debug("Found a target we'd like: %s\n", atoms[i].name);
1190 cnp_debug("0x%x\n",xwin);
1191
1192 if (i == CNP_ATOM_text_urilist)
1193 {
1194 cnp_debug("We found a URI... (%scached) %s\n",
1195 savedtypes.imgfile ? "" : "not ",
1196 savedtypes.imgfile);
1197 if (savedtypes.imgfile)
1198 {
1199 char *entrytag;
1200 static const char *tagstring = "<item absize=240x180 href="
1201 "file://%s></item>";
1202 ddata.x = savedtypes.x;
1203 ddata.y = savedtypes.y;
1204
1205 /* If it's markup that also supports images */
1206 if ((dropable->types & ELM_SEL_FORMAT_MARKUP) &&
1207 (dropable->types & ELM_SEL_FORMAT_IMAGE))
1208 {
1209 int len;
1210 ddata.format = ELM_SEL_FORMAT_MARKUP;
1211
1212 len = strlen(tagstring) + strlen(savedtypes.imgfile);
1213 entrytag = alloca(len + 1);
1214 snprintf(entrytag, len + 1, tagstring, savedtypes.imgfile);
1215 ddata.data = entrytag;
1216 cnp_debug("Insert %s\n", (char *)ddata.data);
1217 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1218 ecore_x_dnd_send_finished();
1219 if (savedtypes.imgfile) free((void*)savedtypes.imgfile);
1220 savedtypes.imgfile = NULL;
1221
1222 return EINA_TRUE;
1223 }
1224 else if (dropable->types & ELM_SEL_FORMAT_IMAGE)
1225 {
1226 cnp_debug("Doing image insert (%s)\n", savedtypes.imgfile);
1227 ddata.format = ELM_SEL_FORMAT_IMAGE;
1228 ddata.data = (char *)savedtypes.imgfile;
1229 dropable->dropcb(dropable->cbdata, dropable->obj, &ddata);
1230 ecore_x_dnd_send_finished();
1231 if (savedtypes.imgfile) free((void*)savedtypes.imgfile);
1232 savedtypes.imgfile = NULL;
1233
1234 return EINA_TRUE;
1235 }
1236 else
1237 {
1238 cnp_debug("Item doesn't support images... passing\n");
1239 return EINA_TRUE;
1240 }
1241 }
1242 else if (savedtypes.textreq)
1243 {
1244 /* Already asked: Pretend we asked now, and paste immediately when
1245 * it comes in */
1246 savedtypes.textreq = 0;
1247 ecore_x_dnd_send_finished();
1248 return EINA_TRUE;
1249 }
1250 }
1251
1252 cnp_debug("doing a request then\n");
1253 selections[ELM_SEL_TYPE_XDND].requestwidget = dropable->obj;
1254 selections[ELM_SEL_TYPE_XDND].requestformat = ELM_SEL_FORMAT_MARKUP;
1255 selections[ELM_SEL_TYPE_XDND].active = EINA_TRUE;
1256
1257 ecore_x_selection_xdnd_request(xwin, atoms[i].name);
1258
1259 return EINA_TRUE;
1260}
1261static Eina_Bool
1262_dnd_position(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1263{
1264 struct _Ecore_X_Event_Xdnd_Position *pos;
1265 Ecore_X_Rectangle rect;
1266
1267 pos = ev;
1268
1269 /* Need to send a status back */
1270 /* FIXME: Should check I can drop here */
1271 /* FIXME: Should highlight widget */
1272 rect.x = pos->position.x - 5;
1273 rect.y = pos->position.y - 5;
1274 rect.width = 10;
1275 rect.height = 10;
1276 ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, rect, pos->action);
1277
1278 return EINA_TRUE;
1279}
1280
1281/**
1282 * When dragging this is callback response from the destination.
1283 * The important thing we care about: Can we drop; thus update cursor
1284 * appropriately.
1285 */
1286static Eina_Bool
1287_dnd_status(void *data __UNUSED__, int etype __UNUSED__, void *ev)
1288{
1289 struct _Ecore_X_Event_Xdnd_Status *status = ev;
1290
1291 if (!status) return EINA_TRUE;
1292
1293 /* Only thing we care about: will accept */
1294 if (status->will_accept)
1295 {
1296 cnp_debug("Will accept\n");
1297 }
1298 else
1299 { /* Won't accept */
1300 cnp_debug("Won't accept accept\n");
1301 }
1302 return EINA_TRUE;
1303}
1304
1305/**
1306 * Add a widget as drop target.
1307 */
1308Eina_Bool
1309elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, void *cbdata)
1310{
1311 Dropable *drop;
1312 Ecore_X_Window xwin;
1313 Eina_List *item;
1314 int first;
1315 Evas_Object *top;
1316
1317 if (!obj) return EINA_FALSE;
1318 top = elm_widget_top_get(obj);
1319 if (!top || !elm_win_xwindow_get(top)) return EINA_FALSE;
1320 if (!_elm_cnp_init_count) _elm_cnp_init();
1321
1322 /* Is this the first? */
1323 first = (!drops) ? 1 : 0;
1324
1325 EINA_LIST_FOREACH(drops, item, drop)
1326 {
1327 if (drop->obj == obj)
1328 {
1329 /* Update: Not a new one */
1330 drop->dropcb = dropcb;
1331 drop->cbdata = cbdata;
1332 drop->types = format;
1333 return EINA_TRUE;
1334 }
1335 }
1336
1337 /* Create new drop */
1338 drop = calloc(1, sizeof(Dropable));
1339 if (!drop) return EINA_FALSE;
1340 /* FIXME: Check for eina's deranged error method */
1341 drops = eina_list_append(drops, drop);
1342
1343 if (!drops/* || or other error */)
1344 {
1345 free(drop);
1346 return EINA_FALSE;
1347 }
1348 drop->dropcb = dropcb;
1349 drop->cbdata = cbdata;
1350 drop->types = format;
1351 drop->obj = obj;
1352
1353 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1354 /* I love C and varargs */
1355 (Evas_Object_Event_Cb)elm_drop_target_del,
1356 obj);
1357 /* FIXME: Handle resizes */
1358
1359 /* If not the first: We're done */
1360 if (!first) return EINA_TRUE;
1361
1362 xwin = (Ecore_X_Window)ecore_evas_window_get
1363 (ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
1364
1365 ecore_x_dnd_aware_set(xwin, EINA_TRUE);
1366
1367 cnp_debug("Adding drop target calls\n");
1368 handler_enter = ecore_event_handler_add(ECORE_X_EVENT_XDND_ENTER,
1369 _dnd_enter, NULL);
1370 handler_pos = ecore_event_handler_add(ECORE_X_EVENT_XDND_POSITION,
1371 _dnd_position, NULL);
1372 handler_drop = ecore_event_handler_add(ECORE_X_EVENT_XDND_DROP,
1373 _dnd_drop, NULL);
1374
1375 return EINA_TRUE;
1376}
1377
1378Eina_Bool
1379elm_drop_target_del(Evas_Object *obj)
1380{
1381 Dropable *drop,*del;
1382 Eina_List *item;
1383 Ecore_X_Window xwin;
1384
1385 del = NULL;
1386 EINA_LIST_FOREACH(drops, item, drop)
1387 {
1388 if (drop->obj == obj)
1389 {
1390 drops = eina_list_remove_list(drops, item);
1391 del = drop;
1392 break;
1393 }
1394 }
1395 if (!del) return EINA_FALSE;
1396
1397 evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE,
1398 (Evas_Object_Event_Cb)elm_drop_target_del);
1399 free(drop);
1400 /* If still drops there: All fine.. continue */
1401 if (drops) return EINA_TRUE;
1402
1403 cnp_debug("Disabling DND\n");
1404 xwin = (Ecore_X_Window)ecore_evas_window_get
1405 (ecore_evas_ecore_evas_get(evas_object_evas_get(obj)));
1406 ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1407
1408 ecore_event_handler_del(handler_pos);
1409 ecore_event_handler_del(handler_drop);
1410 ecore_event_handler_del(handler_enter);
1411
1412 if (savedtypes.imgfile) free((void*)savedtypes.imgfile);
1413 savedtypes.imgfile = NULL;
1414
1415 return EINA_TRUE;
1416}
1417
1418
1419static void
1420_drag_mouse_up(void *un __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *data)
1421{
1422 Ecore_X_Window xwin = *((Ecore_X_Window *)data);
1423 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_UP, _drag_mouse_up);
1424 ecore_x_dnd_drop();
1425 ecore_x_dnd_aware_set(xwin, EINA_FALSE);
1426 if (dragdonecb)
1427 {
1428 dragdonecb(dragdonedata, selections[ELM_SEL_TYPE_XDND].widget);
1429 dragdonecb = NULL;
1430 }
1431 if (dragwin)
1432 {
1433 evas_object_del(dragwin);
1434 dragwin = NULL;
1435 }
1436}
1437
1438static void
1439_drag_move(void *data __UNUSED__, Ecore_X_Xdnd_Position *pos)
1440{
1441 evas_object_move(dragwin,
1442 pos->position.x - _dragx,
1443 pos->position.y - _dragy);
1444}
1445
1446
1447Eina_Bool
1448elm_drag_start(Evas_Object *obj, Elm_Sel_Format format, const char *data, void (*dragdone) (void *data, Evas_Object *), void *donecbdata)
1449{
1450 Ecore_X_Window xwin;
1451 Cnp_Selection *sel;
1452 Elm_Sel_Type xdnd = ELM_SEL_TYPE_XDND;
1453 Ecore_Evas *ee;
1454 int x, y, x2, y2, x3, y3;
1455 Evas_Object *icon;
1456 int w, h;
1457
1458 if (!_elm_cnp_init_count) _elm_cnp_init();
1459
1460 xwin = elm_win_xwindow_get(obj);
1461
1462 cnp_debug("starting drag...\n");
1463
1464 if (dragwin)
1465 {
1466 cnp_debug("another obj is dragging...\n");
1467 return EINA_FALSE;
1468 }
1469
1470 ecore_x_dnd_type_set(xwin, "text/uri-list", EINA_TRUE);
1471 sel = selections + ELM_SEL_TYPE_XDND;
1472 sel->active = EINA_TRUE;
1473 sel->widget = obj;
1474 sel->format = format;
1475 sel->selbuf = data ? strdup(data) : NULL;
1476 dragdonecb = dragdone;
1477 dragdonedata = donecbdata;
1478
1479 ecore_x_dnd_aware_set(xwin, EINA_TRUE);
1480 ecore_x_dnd_callback_pos_update_set(_drag_move, NULL);
1481 ecore_x_dnd_begin(xwin, (unsigned char *)&xdnd, sizeof(Elm_Sel_Type));
1482 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
1483 _drag_mouse_up, (void *)(long)xwin);
1484
1485 handler_status = ecore_event_handler_add(ECORE_X_EVENT_XDND_STATUS,
1486 _dnd_status, NULL);
1487
1488 dragwin = elm_win_add(NULL, "Elm Drag Object", ELM_WIN_UTILITY);
1489 elm_win_override_set(dragwin, EINA_TRUE);
1490
1491 /* FIXME: Images only */
1492 icon = elm_icon_add(dragwin);
1493 elm_icon_file_set(icon, data + 7, NULL); /* 7!? "file://" */
1494 elm_win_resize_object_add(dragwin, icon);
1495 evas_object_size_hint_weight_set(icon, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1496 evas_object_size_hint_align_set(icon, EVAS_HINT_FILL, EVAS_HINT_FILL);
1497
1498 /* Position subwindow appropriately */
1499 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
1500 ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
1501 evas_object_geometry_get(obj, &x2, &y2, &w, &h);
1502 x += x2;
1503 y += y2;
1504 evas_object_move(dragwin, x, y);
1505 evas_object_resize(icon, w, h);
1506 evas_object_resize(dragwin, w, h);
1507
1508 evas_object_show(icon);
1509 evas_object_show(dragwin);
1510
1511 evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x3, &y3);
1512 _dragx = x3 - x2;
1513 _dragy = y3 - y2;
1514
1515 return EINA_TRUE;
1516}
1517
1518static Tmp_Info *
1519elm_cnp_tempfile_create(int size)
1520{
1521#ifdef HAVE_MMAN_H
1522 Tmp_Info *info;
1523 const char *tmppath;
1524 int len;
1525
1526 info = malloc(sizeof(Tmp_Info));
1527 if (!info) return NULL;
1528
1529 tmppath = getenv("TMP");
1530 if (!tmppath) tmppath = P_tmpdir;
1531 len = snprintf(NULL, 0, "%s/%sXXXXXX", tmppath, "elmcnpitem-");
1532 if (len < 0)
1533 {
1534 free(info);
1535 return NULL;
1536 }
1537 len++;
1538 info->filename = malloc(len);
1539 if (!info->filename)
1540 {
1541 free(info);
1542 return NULL;
1543 }
1544 snprintf(info->filename,len,"%s/%sXXXXXX", tmppath, "elmcnpitem-");
1545
1546 info->fd = mkstemp(info->filename);
1547
1548# ifdef __linux__
1549 {
1550 char *tmp;
1551 /* And before someone says anything see POSIX 1003.1-2008 page 400 */
1552 long pid;
1553
1554 pid = (long)getpid();
1555 /* Use pid instead of /proc/self: That way if can be passed around */
1556 len = snprintf(NULL,0,"/proc/%li/fd/%i", pid, info->fd);
1557 len++;
1558 tmp = malloc(len);
1559 if (tmp)
1560 {
1561 snprintf(tmp,len, "/proc/%li/fd/%i", pid, info->fd);
1562 unlink(info->filename);
1563 free(info->filename);
1564 info->filename = tmp;
1565 }
1566 }
1567# endif
1568
1569 cnp_debug("filename is %s\n", info->filename);
1570 if (size < 1)
1571 {
1572 /* Set map to NULL and return */
1573 info->map = NULL;
1574 info->len = 0;
1575 return info;
1576 }
1577
1578 /* Map it in */
1579 if (ftruncate(info->fd, size))
1580 {
1581 perror("ftruncate");
1582 info->map = NULL;
1583 info->len = 0;
1584 return info;
1585 }
1586
1587 eina_mmap_safety_enabled_set(EINA_TRUE);
1588
1589 info->map = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, info->fd, 0);
1590 if (info->map == MAP_FAILED)
1591 {
1592 perror("mmap");
1593 info->map = NULL;
1594 info->len = 0;
1595 }
1596
1597 return info;
1598#else
1599 (void) size;
1600 return NULL;
1601#endif
1602}
1603
1604
1605static int
1606tmpinfo_free(Tmp_Info *info)
1607{
1608 if (!info) return 0;
1609 free(info->filename);
1610 free(info);
1611 return 0;
1612}
1613
1614#else
1615/* Stubs for windows */
1616Eina_Bool
1617elm_drag_start(Evas_Object *o, Elm_Sel_Format f, const char *d, void (*donecb)(void *, Evas_Object *),void *cbdata)
1618{
1619 return EINA_FALSE;
1620}
1621
1622Eina_Bool
1623elm_drop_target_add(Evas_Object *obj, Elm_Sel_Type format, Elm_Drop_Cb dropcb, void *cbdata)
1624{
1625 return EINA_FALSE;
1626}
1627
1628Eina_Bool
1629elm_drop_target_del(Evas_Object *o)
1630{
1631 return EINA_TRUE;
1632}
1633#endif
1634
1635/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/elm_cnp.h b/libraries/elementary/src/lib/elm_cnp.h
new file mode 100644
index 0000000..2b45c91
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_cnp.h
@@ -0,0 +1,163 @@
1/**
2 * @defgroup CopyPaste CopyPaste
3 * @ingroup Elementary
4 *
5 * Implements the following functionality
6 * a. select, copy/cut and paste
7 * b. clipboard
8 * c. drag and drop
9 * in order to share data across application windows.
10 *
11 * Contains functions to select text or a portion of data,
12 * send it to a buffer, and paste the data into a target.
13 *
14 * elm_cnp provides a generic copy and paste facility based on its windowing system.
15 * It is not necessary to know the details of each windowing system,
16 * but some terms and behavior are common.
17 * Currently the X11 window system is widely used, and only X11 functionality is implemented.
18 *
19 * In X11R6 window system, CopyPaste works like a peer-to-peer communication.
20 * Copying is an operation on an object in an X server.
21 * X11 calls those objects 'selections' which have names.
22 * Generally, two selection types are needed for copy and paste:
23 * The Primary selection and the Clipboard selection.
24 * Primary selection is for selecting text (that means highlighted text).
25 * Clipboard selection is for explicit copying behavior
26 * (such as ctrl+c, or 'copy' in a menu).
27 * Thus, in applications most cases only use the clipboard selection.
28 * As stated before, taking ownership of a selection doesn't move any actual data.
29 * Copying and Pasting is described as follows:
30 * 1. Copy text in Program A : Program A takes ownership of the selection
31 * 2. Paste text in Program B : Program B notes that Program A owns the selection
32 * 3. Program B asks A for the text
33 * 4. Program A responds and sends the text to program B
34 * 5. Program B pastes the response
35 * More information is on
36 * - http://www.jwz.org/doc/x-cut-and-paste.html
37 * - X11R6 Inter-Client Communication Conventions Manual, section 2
38 *
39 * TODO: add for other window system.
40 *
41 * @{
42 */
43
44/**
45 * Defines the types of selection property names.
46 * @see http://www.x.org/docs/X11/xlib.pdf
47 * for more details.
48 */
49typedef enum
50{
51 ELM_SEL_TYPE_PRIMARY, /**< Primary text selection (highlighted or selected text) */
52 ELM_SEL_TYPE_SECONDARY, /**< Used when primary selection is in use */
53 ELM_SEL_TYPE_XDND, /**< Drag 'n' Drop */
54 ELM_SEL_TYPE_CLIPBOARD, /**< Clipboard selection (ctrl+C) */
55} Elm_Sel_Type;
56
57/**
58 * Defines the types of content.
59 */
60typedef enum
61{
62 /** For matching every possible atom */
63 ELM_SEL_FORMAT_TARGETS = -1,
64 /** Content is from outside of Elementary */
65 ELM_SEL_FORMAT_NONE = 0x0,
66 /** Plain unformatted text: Used for things that don't want rich markup */
67 ELM_SEL_FORMAT_TEXT = 0x01,
68 /** Edje textblock markup, including inline images */
69 ELM_SEL_FORMAT_MARKUP = 0x02,
70 /** Images */
71 ELM_SEL_FORMAT_IMAGE = 0x04,
72 /** Vcards */
73 ELM_SEL_FORMAT_VCARD = 0x08,
74 /** Raw HTML-like data (eg. webkit) */
75 ELM_SEL_FORMAT_HTML = 0x10,
76} Elm_Sel_Format;
77
78/**
79 * Structure holding the info about selected data.
80 */
81struct _Elm_Selection_Data
82{
83 Evas_Coord x, y;
84 Elm_Sel_Format format;
85 void *data;
86 size_t len;
87};
88typedef struct _Elm_Selection_Data Elm_Selection_Data;
89
90/**
91 * Callback invoked in when the selected data is 'dropped' at its destination.
92 *
93 * @param data Application specific data
94 * @param obj The evas object where selected data is 'dropped'.
95 * @param ev struct holding information about selected data
96 * FIXME: this should probably be a smart callback
97 */
98typedef Eina_Bool (*Elm_Drop_Cb)(void *data, Evas_Object *obj, Elm_Selection_Data *ev);
99
100
101/**
102 * @brief Set copy data for a widget.
103 *
104 * Set copy data and take ownership of selection. Format is used for specifying the selection type,
105 * and this is used during pasting.
106 *
107 * @param selection Selection type for copying and pasting
108 * @param obj The source widget pointer
109 * @param format Selection format
110 * @param buf The data selected
111 * @param buflen The size of @p buf
112 * @return If EINA_TRUE, setting data was successful.
113 *
114 * @ingroup CopyPaste
115 *
116 */
117EAPI Eina_Bool elm_cnp_selection_set(Evas_Object *obj, Elm_Sel_Type selection,
118 Elm_Sel_Format format,
119 const void *buf, size_t buflen);
120
121/**
122 * @brief Retrieve data from a widget that has a selection.
123 *
124 * Gets the current selection data from a widget.
125 * The widget input here will usually be elm_entry,
126 * in which case @p datacb and @p udata can be NULL.
127 * If a different widget is passed, @p datacb and @p udata are used for retrieving data.
128 *
129 * @see also elm_cnp_selection_set()
130 *
131 * @param selection Selection type for copying and pasting
132 * @param format Selection format
133 * @param obj The source widget
134 * @param datacb The user data callback if the target widget isn't elm_entry
135 * @param udata The user data pointer for @p datacb
136 * @return If EINA_TRUE, getting selection data was successful.
137 *
138 * @ingroup CopyPaste
139 */
140EAPI Eina_Bool elm_cnp_selection_get(Evas_Object *obj, Elm_Sel_Type selection,
141 Elm_Sel_Format format,
142 Elm_Drop_Cb datacb, void *udata);
143
144/**
145 * @brief Clear the selection data of a widget.
146 *
147 * Clear all data from the selection which is owned by a widget.
148 *
149 * @see also elm_cnp_selection_set()
150 *
151 * @param obj The source widget
152 * @param selection Selection type for copying and pasting
153 * @return If EINA_TRUE, clearing data was successful.
154 *
155 * @ingroup CopyPaste
156 *
157 */
158EAPI Eina_Bool elm_object_cnp_selection_clear(Evas_Object *obj,
159 Elm_Sel_Type selection);
160
161/**
162 * @}
163 */
diff --git a/libraries/elementary/src/lib/elm_colorselector.c b/libraries/elementary/src/lib/elm_colorselector.c
new file mode 100644
index 0000000..f650855
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_colorselector.c
@@ -0,0 +1,1279 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define BASE_STEP 360.0
5#define HUE_STEP 360.0
6#define SAT_STEP 128.0
7#define LIG_STEP 256.0
8#define ALP_STEP 256.0
9#define DEFAULT_HOR_PAD 10
10#define DEFAULT_VER_PAD 10
11
12typedef enum _Color_Type
13{
14 HUE,
15 SATURATION,
16 LIGHTNESS,
17 ALPHA
18} Color_Type;
19
20typedef struct _Colorselector_Data Colorselector_Data;
21struct _Colorselector_Data
22{
23 Evas_Object *parent;
24 Evas_Object *colorbar;
25 Evas_Object *bar;
26 Evas_Object *lbt;
27 Evas_Object *rbt;
28 Evas_Object *bg_rect;
29 Evas_Object *arrow;
30 Evas_Object *touch_area;
31 Color_Type color_type;
32};
33
34typedef struct _Widget_Data Widget_Data;
35typedef struct _Elm_Color_Item Elm_Color_Item;
36struct _Widget_Data
37{
38 Evas_Object *sel;
39 Evas_Object *base;
40 Evas_Object *box;
41 Eina_List *items;
42 Colorselector_Data *cp[4];
43 Ecore_Timer *longpress_timer;
44 const char *palette_name;
45 Evas_Coord _x, _y, _w, _h;
46 int r, g, b, a;
47 int er, eg, eb;
48 int sr, sg, sb;
49 int lr, lg, lb;
50 double h, s, l;
51 Elm_Colorselector_Mode mode;
52 Eina_Bool longpressed : 1;
53 Eina_Bool config_load: 1;
54};
55
56struct _Elm_Color_Item
57{
58 ELM_WIDGET_ITEM;
59 Evas_Object *color_obj;
60 Elm_Color_RGBA *color;
61};
62
63static const char *widtype = NULL;
64
65static void _del_hook(Evas_Object *obj);
66static void _theme_hook(Evas_Object *obj);
67static void _sizing_eval(Evas_Object *obj);
68static void _resize_cb(void *data, Evas *a, Evas_Object *obj, void *event_info);
69static void _rgb_to_hsl(void *data);
70static void _hsl_to_rgb(void *data);
71static void _color_with_saturation(void *data);
72static void _color_with_lightness(void *data);
73static void _draw_rects(void *data, double x);
74static void _arrow_cb(void *data, Evas_Object *obj, const char *emission,
75 const char *source);
76static void _colorbar_cb(void *data, Evas *e, Evas_Object *obj,
77 void *event_info);
78static void _left_button_clicked_cb(void *data, Evas_Object * obj,
79 void *event_info);
80static void _left_button_repeat_cb(void *data, Evas_Object * obj,
81 void *event_info);
82static void _right_button_clicked_cb(void *data, Evas_Object * obj,
83 void *event_info);
84static void _right_button_repeat_cb(void *data, Evas_Object * obj,
85 void *event_info);
86static void _add_colorbar(Evas_Object *obj);
87static void _set_color(Evas_Object *obj, int r, int g, int b, int a);
88static Elm_Color_Item *_item_new(Evas_Object *obj);
89static void _item_sizing_eval(Elm_Color_Item *item);
90static void _item_highlight(void *data, Evas *e, Evas_Object *obj, void *event_info);
91static void _item_unhighlight(void *data, Evas *e, Evas_Object *obj, void *event_info);
92static Eina_Bool _long_press(void *data);
93static void _remove_items(Widget_Data *wd);
94static void _colors_remove(Evas_Object *obj);
95static void _colors_save(Evas_Object *obj);
96static void _colors_load_apply(Evas_Object *obj);
97
98static const char SIG_CHANGED[] = "changed";
99static const char SIG_COLOR_ITEM_SELECTED[] = "color,item,selected";
100static const char SIG_COLOR_ITEM_LONGPRESSED[] = "color,item,longpressed";
101
102static const Evas_Smart_Cb_Description _signals[] =
103{
104 {SIG_COLOR_ITEM_SELECTED, ""},
105 {SIG_COLOR_ITEM_LONGPRESSED, ""},
106 {SIG_CHANGED, ""},
107 {NULL, NULL}
108};
109
110static void
111_del_hook(Evas_Object *obj)
112{
113 Widget_Data *wd = elm_widget_data_get(obj);
114 int i = 0;
115
116 if (!wd) return;
117 if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
118 if (wd->palette_name) eina_stringshare_del(wd->palette_name);
119 _remove_items(wd);
120 for (i = 0; i < 4; i++) free(wd->cp[i]);
121 free(wd);
122}
123
124static void
125_theme_hook(Evas_Object *obj)
126{
127 Widget_Data *wd = elm_widget_data_get(obj);
128 Eina_List *elist;
129 Elm_Color_Item *item;
130 int i;
131 const char *hpadstr, *vpadstr;
132 unsigned int h_pad = DEFAULT_HOR_PAD;
133 unsigned int v_pad = DEFAULT_VER_PAD;
134
135 if ((!wd) || (!wd->sel)) return;
136
137 _elm_theme_object_set(obj, wd->base, "colorselector", "palette",
138 elm_widget_style_get(obj));
139 _elm_theme_object_set(obj, wd->sel, "colorselector", "bg",
140 elm_widget_style_get(obj));
141 hpadstr = edje_object_data_get(wd->base, "horizontal_pad");
142 if (hpadstr) h_pad = atoi(hpadstr);
143 vpadstr = edje_object_data_get(wd->base, "vertical_pad");
144 if (vpadstr) v_pad = atoi(vpadstr);
145 elm_box_padding_set(wd->box, (Evas_Coord)(h_pad * elm_widget_scale_get(obj) * _elm_config->scale),
146 (Evas_Coord)(v_pad * elm_widget_scale_get(obj) *_elm_config->scale));
147 EINA_LIST_FOREACH(wd->items, elist, item)
148 {
149 elm_layout_theme_set(VIEW(item), "colorselector", "item", elm_widget_style_get(obj));
150 _elm_theme_object_set(obj, item->color_obj, "colorselector", "item/color", elm_widget_style_get(obj));
151 }
152 for (i = 0; i < 4; i++)
153 {
154 evas_object_del(wd->cp[i]->colorbar);
155 wd->cp[i]->colorbar = NULL;
156 evas_object_del(wd->cp[i]->bar);
157 wd->cp[i]->bar = NULL;
158 evas_object_del(wd->cp[i]->lbt);
159 wd->cp[i]->lbt = NULL;
160 evas_object_del(wd->cp[i]->rbt);
161 wd->cp[i]->rbt = NULL;
162 if (i != 0)
163 {
164 evas_object_del(wd->cp[i]->bg_rect);
165 wd->cp[i]->bg_rect = NULL;
166 }
167 evas_object_del(wd->cp[i]->arrow);
168 wd->cp[i]->arrow = NULL;
169 evas_object_del(wd->cp[i]->touch_area);
170 wd->cp[i]->touch_area = NULL;
171 }
172
173 _add_colorbar(obj);
174 elm_colorselector_color_set(obj, wd->r, wd->g, wd->b, wd->a);
175 _sizing_eval(obj);
176}
177
178static void
179_colorselector_set_size_hints(Evas_Object *obj, int timesw, int timesh)
180{
181 Evas_Coord minw = -1, minh = -1;
182
183 elm_coords_finger_size_adjust(timesw, &minw, timesh, &minh);
184 edje_object_size_min_restricted_calc(obj, &minw, &minh,
185 minw, minh);
186 evas_object_size_hint_min_set(obj, minw, minh);
187 evas_object_size_hint_max_set(obj, -1, -1);
188}
189
190static void
191_item_sizing_eval(Elm_Color_Item *item)
192{
193 Evas_Coord minw = -1, minh = -1;
194
195 if (!item) return;
196
197 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
198 edje_object_size_min_restricted_calc(VIEW(item), &minw, &minh, minw,
199 minh);
200 evas_object_size_hint_min_set(VIEW(item), minw, minh);
201}
202
203static void _resize_cb(void *data, Evas *a __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
204{
205 _sizing_eval(data);
206}
207
208static void
209_sizing_eval_palette(Evas_Object *obj)
210{
211 Widget_Data *wd = elm_widget_data_get(obj);
212 Eina_List *elist;
213 Elm_Color_Item *item;
214 Evas_Coord bw = 0, bh = 0;
215 Evas_Coord w = 0, h = 0;
216 if (!wd) return;
217
218 EINA_LIST_FOREACH(wd->items, elist, item)
219 {
220 _item_sizing_eval(item);
221 }
222 evas_object_size_hint_min_get(wd->box, &bw, &bh);
223 evas_object_size_hint_min_set(obj, bw, bh);
224 evas_object_size_hint_max_set(obj, -1, -1);
225 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
226 if (w < bw) w = bw;
227 if (h < bh) h = bh;
228 evas_object_resize(obj, w, h);
229}
230
231static void
232_sizing_eval_selector(Evas_Object *obj)
233{
234 Widget_Data *wd = elm_widget_data_get(obj);
235 Evas_Coord minw = -1, minh = -1;
236 Evas_Coord w = 0, h = 0;
237 int i;
238
239 if (!wd) return;
240 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
241 for (i = 0; i < 4; i++)
242 {
243 if (wd->cp[i]->bg_rect)
244 _colorselector_set_size_hints(wd->cp[i]->bg_rect, 1, 1);
245 _colorselector_set_size_hints(wd->cp[i]->bar, 1, 1);
246 _colorselector_set_size_hints(wd->cp[i]->rbt, 1, 1);
247 _colorselector_set_size_hints(wd->cp[i]->lbt, 1, 1);
248
249 _colorselector_set_size_hints(wd->cp[i]->colorbar, 4, 1);
250 }
251
252 elm_coords_finger_size_adjust(4, &minw, 4, &minh);
253 edje_object_size_min_restricted_calc(wd->sel, &minw, &minh, minw, minh);
254 evas_object_size_hint_min_set(obj, minw, minh);
255 evas_object_size_hint_max_set(obj, -1, -1);
256 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
257 if (w < minw) w = minw;
258 if (h < minh) h = minh;
259 evas_object_resize(obj, w, h);
260}
261
262static void
263_sizing_eval_palette_selector(Evas_Object *obj)
264{
265 Widget_Data *wd = elm_widget_data_get(obj);
266 Evas_Coord minw = -1, minh = -1;
267 Evas_Coord bw = 0, bh = 0;
268 Evas_Coord w = 0, h = 0;
269 int i;
270 if (!wd) return;
271 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
272 for (i = 0; i < 4; i++)
273 {
274 if (wd->cp[i]->bg_rect)
275 _colorselector_set_size_hints(wd->cp[i]->bg_rect, 1, 1);
276 _colorselector_set_size_hints(wd->cp[i]->bar, 1, 1);
277 _colorselector_set_size_hints(wd->cp[i]->rbt, 1, 1);
278 _colorselector_set_size_hints(wd->cp[i]->lbt, 1, 1);
279
280 _colorselector_set_size_hints(wd->cp[i]->colorbar, 4, 1);
281 }
282
283 elm_coords_finger_size_adjust(4, &minw, 4, &minh);
284 edje_object_size_min_restricted_calc(wd->sel, &minw, &minh, minw, minh);
285 evas_object_size_hint_min_get(wd->box, &bw, &bh);
286 evas_object_size_hint_min_set(obj, minw, minh+bh);
287 evas_object_size_hint_max_set(obj, -1, -1);
288 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
289 if (w < minw) w = minw;
290 if (h < (minh+bh)) h = (minh+bh);
291 evas_object_resize(obj, w, h);
292}
293
294static void
295_sizing_eval(Evas_Object *obj)
296{
297 Widget_Data *wd = elm_widget_data_get(obj);
298 if (!wd) return;
299 switch (wd->mode)
300 {
301 case ELM_COLORSELECTOR_PALETTE:
302 _sizing_eval_palette(obj);
303 break;
304 case ELM_COLORSELECTOR_COMPONENTS:
305 _sizing_eval_selector(obj);
306 break;
307 case ELM_COLORSELECTOR_BOTH:
308 _sizing_eval_palette_selector(obj);
309 break;
310 default:
311 break;
312 }
313}
314
315static Eina_Bool
316_long_press(void *data)
317{
318 Elm_Color_Item *item = (Elm_Color_Item *) data;
319 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
320 if (!wd) return ECORE_CALLBACK_CANCEL;
321 wd->longpress_timer = NULL;
322 wd->longpressed = EINA_TRUE;
323 evas_object_smart_callback_call(WIDGET(item), SIG_COLOR_ITEM_LONGPRESSED, item);
324 return ECORE_CALLBACK_CANCEL;
325}
326
327static void
328_item_highlight(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
329{
330 Elm_Color_Item *item = (Elm_Color_Item *) data;
331 Evas_Event_Mouse_Down *ev = event_info;
332 if (!item) return;
333 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
334 if (!wd) return;
335 if (ev->button != 1) return;
336 elm_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
337 wd->longpressed = EINA_FALSE;
338 if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
339 wd->longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
340}
341
342static void
343_item_unhighlight(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
344{
345 Elm_Color_Item *item = (Elm_Color_Item *) data;
346 Evas_Event_Mouse_Down *ev = event_info;
347 if (!item) return;
348 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
349 if (!wd) return;
350 if (ev->button != 1) return;
351 if (wd->longpress_timer)
352 {
353 ecore_timer_del(wd->longpress_timer);
354 wd->longpress_timer = NULL;
355 }
356 elm_object_signal_emit(VIEW(item), "elm,state,unselected", "elm");
357 if (!wd->longpressed)
358 {
359 evas_object_smart_callback_call(WIDGET(item), SIG_COLOR_ITEM_SELECTED, item);
360 elm_colorselector_color_set(WIDGET(item), item->color->r, item->color->g, item->color->b, item->color->a);
361 }
362}
363
364static void
365_remove_items(Widget_Data *wd)
366{
367 Elm_Color_Item *item;
368
369 if (!wd->items) return;
370
371 EINA_LIST_FREE(wd->items, item)
372 {
373 free(item->color);
374 elm_widget_item_free(item);
375 }
376
377 wd->items = NULL;
378}
379
380static Elm_Color_Item*
381_item_new(Evas_Object *obj)
382{
383 Elm_Color_Item *item;
384 Widget_Data *wd;
385
386 wd = elm_widget_data_get(obj);
387 if (!wd) return NULL;
388
389 item = elm_widget_item_new(obj, Elm_Color_Item);
390 if (!item) return NULL;
391
392 VIEW(item) = elm_layout_add(obj);
393 elm_layout_theme_set(VIEW(item), "colorselector", "item", elm_widget_style_get(obj));
394 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
395 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
396 item->color_obj = edje_object_add(evas_object_evas_get(obj));
397 _elm_theme_object_set(obj, item->color_obj, "colorselector", "item/color", elm_widget_style_get(obj));
398 evas_object_size_hint_weight_set(item->color_obj, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
399 evas_object_size_hint_align_set(item->color_obj, EVAS_HINT_FILL, EVAS_HINT_FILL);
400 evas_object_event_callback_add(item->color_obj, EVAS_CALLBACK_MOUSE_DOWN, _item_highlight, item);
401 evas_object_event_callback_add(item->color_obj, EVAS_CALLBACK_MOUSE_UP, _item_unhighlight, item);
402 elm_object_part_content_set(VIEW(item), "color_obj", item->color_obj);
403 _item_sizing_eval(item);
404 evas_object_show(VIEW(item));
405
406 return item;
407}
408
409static void
410_colors_remove(Evas_Object *obj)
411{
412 Widget_Data *wd = elm_widget_data_get(obj);
413
414 _remove_items(wd);
415 _elm_config_colors_free(wd->palette_name);
416}
417
418static void _colors_save(Evas_Object *obj)
419{
420 Eina_List *elist;
421 Widget_Data *wd = elm_widget_data_get(obj);
422 Elm_Color_Item *item;
423 _elm_config_colors_free(wd->palette_name);
424 EINA_LIST_FOREACH(wd->items, elist, item)
425 {
426 _elm_config_color_set(wd->palette_name, item->color->r, item->color->g,
427 item->color->b, item->color->a);
428 }
429}
430
431static void
432_colors_load_apply(Evas_Object *obj)
433{
434 Elm_Color_RGBA *color;
435 Eina_List *elist;
436 Eina_List *color_list;
437 Elm_Color_Item *item;
438 Widget_Data *wd = elm_widget_data_get(obj);
439 color_list = _elm_config_color_list_get(wd->palette_name);
440 if (!color_list) return;
441 EINA_LIST_FOREACH(color_list, elist, color)
442 {
443 item = _item_new(obj);
444 if (!item) return;
445 item->color = ELM_NEW(Elm_Color_RGBA);
446 if (!item->color) return;
447 item->color->r = color->r;
448 item->color->g = color->g;
449 item->color->b = color->b;
450 item->color->a = color->a;
451 elm_box_pack_end(wd->box, VIEW(item));
452 evas_object_color_set(item->color_obj, item->color->r, item->color->g,
453 item->color->b, item->color->a);
454 wd->items = eina_list_append(wd->items, item);
455 _sizing_eval_palette(obj);
456 }
457 wd->config_load = EINA_TRUE;
458}
459
460static void
461_rgb_to_hsl(void *data)
462{
463 Widget_Data *wd = data;
464 double r, g, b;
465 double v, m, vm;
466 double r2, g2, b2;
467
468 r = wd->r;
469 g = wd->g;
470 b = wd->b;
471
472 r /= 255.0;
473 g /= 255.0;
474 b /= 255.0;
475
476 v = (r > g) ? r : g;
477 v = (v > b) ? v : b;
478
479 m = (r < g) ? r : g;
480 m = (m < b) ? m : b;
481
482 wd->h = 0.0;
483 wd->s = 0.0;
484 wd->l = 0.0;
485
486 wd->l = (m + v) / 2.0;
487
488 if (wd->l <= 0.0) return;
489
490 vm = v - m;
491 wd->s = vm;
492
493 if (wd->s > 0.0) wd->s /= (wd->l <= 0.5) ? (v + m) : (2.0 - v - m);
494 else return;
495
496 r2 = (v - r) / vm;
497 g2 = (v - g) / vm;
498 b2 = (v - b) / vm;
499
500 if (r == v) wd->h = (g == m ? 5.0 + b2 : 1.0 - g2);
501 else if (g == v) wd->h = (b == m ? 1.0 + r2 : 3.0 - b2);
502 else wd->h = (r == m ? 3.0 + g2 : 5.0 - r2);
503
504 wd->h *= 60.0;
505}
506
507static void
508_hsl_to_rgb(void *data)
509{
510 Widget_Data *wd = data;
511 double r = 0, g = 0, b = 0;
512 double _h, _s, _l;
513 int i = 0;
514 double sv, vsf, f, p, q, t, v;
515
516 _h = wd->h;
517 _s = wd->s;
518 _l = wd->l;
519
520 if (_s == 0.0) r = g = b = _l;
521 else
522 {
523 if (_h == 360.0) _h = 0.0;
524 _h /= 60.0;
525
526 v = (_l <= 0.5) ? (_l * (1.0 + _s)) : (_l + _s - (_l * _s));
527 p = _l + _l - v;
528
529 if (v) sv = (v - p) / v;
530 else sv = 0;
531
532 i = (int)_h;
533 f = _h - i;
534
535 vsf = v * sv * f;
536
537 t = p + vsf;
538 q = v - vsf;
539
540 switch (i)
541 {
542 case 0:
543 r = v;
544 g = t;
545 b = p;
546 break;
547 case 1:
548 r = q;
549 g = v;
550 b = p;
551 break;
552 case 2:
553 r = p;
554 g = v;
555 b = t;
556 break;
557 case 3:
558 r = p;
559 g = q;
560 b = v;
561 break;
562 case 4:
563 r = t;
564 g = p;
565 b = v;
566 break;
567 case 5:
568 r = v;
569 g = p;
570 b = q;
571 break;
572 }
573 }
574 i = (int)(r * 255.0);
575 f = (r * 255.0) - i;
576 wd->r = (f <= 0.5) ? i : (i + 1);
577
578 i = (int)(g * 255.0);
579 f = (g * 255.0) - i;
580 wd->g = (f <= 0.5) ? i : (i + 1);
581
582 i = (int)(b * 255.0);
583 f = (b * 255.0) - i;
584 wd->b = (f <= 0.5) ? i : (i + 1);
585}
586
587static void
588_color_with_saturation(void *data)
589{
590 Widget_Data *wd = data;
591
592 if (wd->er > 127)
593 wd->sr = 127 + (int)((double)(wd->er - 127) * wd->s);
594 else
595 wd->sr = 127 - (int)((double)(127 - wd->er) * wd->s);
596
597 if (wd->eg > 127)
598 wd->sg = 127 + (int)((double)(wd->eg - 127) * wd->s);
599 else
600 wd->sg = 127 - (int)((double)(127 - wd->eg) * wd->s);
601
602 if (wd->eb > 127)
603 wd->sb = 127 + (int)((double)(wd->eb - 127) * wd->s);
604 else
605 wd->sb = 127 - (int)((double)(127 - wd->eb) * wd->s);
606}
607
608static void
609_color_with_lightness(void *data)
610{
611 Widget_Data *wd = data;
612
613 if (wd->l > 0.5)
614 {
615 wd->lr = wd->er + (int)((double)(255 - wd->er) * (wd->l - 0.5) * 2.0);
616 wd->lg = wd->eg + (int)((double)(255 - wd->eg) * (wd->l - 0.5) * 2.0);
617 wd->lb = wd->eb + (int)((double)(255 - wd->eb) * (wd->l - 0.5) * 2.0);
618 }
619 else if (wd->l < 0.5)
620 {
621 wd->lr = (double)wd->er * wd->l * 2.0;
622 wd->lg = (double)wd->eg * wd->l * 2.0;
623 wd->lb = (double)wd->eb * wd->l * 2.0;
624 }
625 else
626 {
627 wd->lr = wd->er;
628 wd->lg = wd->eg;
629 wd->lb = wd->eb;
630 }
631}
632
633static void
634_draw_rects(void *data, double x)
635{
636 Colorselector_Data *cp = data;
637 Widget_Data *wd = elm_widget_data_get(cp->parent);
638 double one_six = 1.0 / 6.0;
639
640 switch (cp->color_type)
641 {
642 case HUE:
643 wd->h = 360.0 * x;
644
645 if (x < one_six)
646 {
647 wd->er = 255;
648 wd->eg = (255.0 * x * 6.0);
649 wd->eb = 0;
650 }
651 else if (x < 2 * one_six)
652 {
653 wd->er = 255 - (int)(255.0 * (x - one_six) * 6.0);
654 wd->eg = 255;
655 wd->eb = 0;
656 }
657 else if (x < 3 * one_six)
658 {
659 wd->er = 0;
660 wd->eg = 255;
661 wd->eb = (int)(255.0 * (x - (2.0 * one_six)) * 6.0);
662 }
663 else if (x < 4 * one_six)
664 {
665 wd->er = 0;
666 wd->eg = 255 - (int)(255.0 * (x - (3.0 * one_six)) * 6.0);
667 wd->eb = 255;
668 }
669 else if (x < 5 * one_six)
670 {
671 wd->er = 255.0 * (x - (4.0 * one_six)) * 6.0;
672 wd->eg = 0;
673 wd->eb = 255;
674 }
675 else
676 {
677 wd->er = 255;
678 wd->eg = 0;
679 wd->eb = 255 - (int)(255.0 * (x - (5.0 * one_six)) * 6.0);
680 }
681
682 evas_object_color_set(wd->cp[0]->arrow, wd->er, wd->eg, wd->eb, 255);
683 evas_object_color_set(wd->cp[1]->bg_rect, wd->er, wd->eg, wd->eb, 255);
684 evas_object_color_set(wd->cp[2]->bg_rect, wd->er, wd->eg, wd->eb, 255);
685 evas_object_color_set(wd->cp[3]->bar, wd->er, wd->eg, wd->eb, 255);
686
687 _color_with_saturation(wd);
688 evas_object_color_set(wd->cp[1]->arrow, wd->sr, wd->sg, wd->sb, 255);
689
690 _color_with_lightness(wd);
691 evas_object_color_set(wd->cp[2]->arrow, wd->lr, wd->lg, wd->lb, 255);
692
693 evas_object_color_set(wd->cp[3]->arrow,
694 (wd->er * wd->a) / 255,
695 (wd->eg * wd->a) / 255,
696 (wd->eb * wd->a) / 255,
697 wd->a);
698 break;
699 case SATURATION:
700 wd->s = 1.0 - x;
701 _color_with_saturation(wd);
702 evas_object_color_set(wd->cp[1]->arrow, wd->sr, wd->sg, wd->sb, 255);
703 break;
704 case LIGHTNESS:
705 wd->l = x;
706 _color_with_lightness(wd);
707 evas_object_color_set(wd->cp[2]->arrow, wd->lr, wd->lg, wd->lb, 255);
708 break;
709 case ALPHA:
710 wd->a = 255.0 * x;
711 evas_object_color_set(wd->cp[3]->arrow,
712 (wd->er * wd->a) / 255,
713 (wd->eg * wd->a) / 255,
714 (wd->eb * wd->a) / 255,
715 wd->a);
716 break;
717 default:
718 break;
719 }
720 _hsl_to_rgb(wd);
721}
722
723static void
724_arrow_cb(void *data, Evas_Object *obj, const char *emission __UNUSED__,
725 const char *source __UNUSED__)
726{
727 Colorselector_Data *cp = data;
728 double x, y;
729
730 edje_object_part_drag_value_get(obj, "elm.arrow", &x, &y);
731 _draw_rects(data, x);
732 evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
733}
734
735static void
736_colorbar_cb(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
737{
738 Colorselector_Data *cp = data;
739 Evas_Event_Mouse_Down *ev = event_info;
740 Evas_Coord x, y, w, h;
741 double arrow_x = 0, arrow_y;
742
743 evas_object_geometry_get(cp->bar, &x, &y, &w, &h);
744 edje_object_part_drag_value_get(cp->colorbar, "elm.arrow",
745 &arrow_x, &arrow_y);
746 if (w > 0) arrow_x = (double)(ev->canvas.x - x) / (double)w;
747 if (arrow_x > 1) arrow_x = 1;
748 if (arrow_x < 0) arrow_x = 0;
749 edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", arrow_x, arrow_y);
750 _draw_rects(data, arrow_x);
751 evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
752 evas_event_feed_mouse_cancel(e, 0, NULL);
753 evas_event_feed_mouse_down(e, 1, EVAS_BUTTON_NONE, 0, NULL);
754}
755
756static void
757_left_button_clicked_cb(void *data, Evas_Object * obj __UNUSED__,
758 void *event_info __UNUSED__)
759{
760 Colorselector_Data *cp = data;
761 double x, y;
762
763 edje_object_signal_emit(cp->lbt, "elm,state,left,button,down",
764 "left_button");
765 edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
766
767 switch(cp->color_type)
768 {
769 case HUE :
770 x -= 1.0 / HUE_STEP;
771 break;
772 case SATURATION :
773 x -= 1.0 / SAT_STEP;
774 break;
775 case LIGHTNESS :
776 x -= 1.0 / LIG_STEP;
777 break;
778 case ALPHA :
779 x -= 1.0 / ALP_STEP;
780 break;
781 default :
782 break;
783 }
784
785 if (x < 0.0) x = 0.0;
786
787 edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
788 _draw_rects(data, x);
789 evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
790}
791
792static void
793_left_button_repeat_cb(void *data, Evas_Object * obj __UNUSED__,
794 void *event_info __UNUSED__)
795{
796 Colorselector_Data *cp = data;
797 double x, y;
798
799 edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
800 x -= 1.0 / BASE_STEP;
801 if (x < 0.0) x = 0.0;
802 edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
803 _draw_rects(data, x);
804 evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
805
806}
807
808static void
809_right_button_clicked_cb(void *data, Evas_Object * obj __UNUSED__,
810 void *event_info __UNUSED__)
811{
812 Colorselector_Data *cp = data;
813 double x, y;
814
815 edje_object_signal_emit(cp->rbt, "elm,state,right,button,down",
816 "right_button");
817 edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
818
819 switch(cp->color_type)
820 {
821 case HUE :
822 x += 1.0 / HUE_STEP;
823 break;
824 case SATURATION :
825 x += 1.0 / SAT_STEP;
826 break;
827 case LIGHTNESS :
828 x += 1.0 / LIG_STEP;
829 break;
830 case ALPHA :
831 x += 1.0 / ALP_STEP;
832 break;
833 default :
834 break;
835 }
836
837 if (x > 1.0) x = 1.0;
838
839 edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
840 _draw_rects(data, x);
841 evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
842}
843
844static void
845_right_button_repeat_cb(void *data, Evas_Object * obj __UNUSED__,
846 void *event_info __UNUSED__)
847{
848 Colorselector_Data *cp = data;
849 double x, y;
850
851 edje_object_part_drag_value_get(cp->colorbar, "elm.arrow", &x, &y);
852 x += 1.0 / BASE_STEP;
853 if (x > 1.0) x = 1.0;
854 edje_object_part_drag_value_set(cp->colorbar, "elm.arrow", x, y);
855 _draw_rects(data, x);
856 evas_object_smart_callback_call(cp->parent, SIG_CHANGED, NULL);
857}
858
859static void
860_add_colorbar(Evas_Object *obj)
861{
862 char colorbar_name[128];
863 char colorbar_s[128];
864 Widget_Data *wd;
865 Evas *e;
866 int i = 0;
867 char buf[1024];
868
869 wd = elm_widget_data_get(obj);
870 if (!wd) return;
871
872 e = evas_object_evas_get(obj);
873
874 for (i = 0; i < 4; i++)
875 {
876 wd->cp[i] = ELM_NEW(Colorselector_Data);
877 wd->cp[i]->parent = obj;
878 switch(i)
879 {
880 case 0 :
881 wd->cp[i]->color_type = HUE;
882 break;
883 case 1 :
884 wd->cp[i]->color_type = SATURATION;
885 break;
886 case 2 :
887 wd->cp[i]->color_type = LIGHTNESS;
888 break;
889 case 3 :
890 wd->cp[i]->color_type = ALPHA;
891 break;
892 default :
893 break;
894 }
895 /* load colorbar area */
896 wd->cp[i]->colorbar = edje_object_add(e);
897 _elm_theme_object_set(obj, wd->cp[i]->colorbar, "colorselector", "base",
898 elm_widget_style_get(obj));
899 snprintf(colorbar_name, sizeof(colorbar_name), "colorbar_%d", i);
900 snprintf(colorbar_s, sizeof(colorbar_s), "elm.colorbar_%d", i);
901 edje_object_signal_callback_add(wd->cp[i]->colorbar, "drag", "*",
902 _arrow_cb, wd->cp[i]);
903 edje_object_part_swallow(wd->sel, colorbar_s, wd->cp[i]->colorbar);
904 elm_widget_sub_object_add(obj, wd->cp[i]->colorbar);
905
906 /* load colorbar image */
907 wd->cp[i]->bar = edje_object_add(e);
908 snprintf(buf, sizeof(buf), "%s/%s", colorbar_name,
909 elm_widget_style_get(obj));
910 _elm_theme_object_set(obj, wd->cp[i]->bar, "colorselector", "image",
911 buf);
912 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar",
913 wd->cp[i]->bar);
914 elm_widget_sub_object_add(obj, wd->cp[i]->bar);
915
916 /* provide expanded touch area */
917 wd->cp[i]->touch_area = evas_object_rectangle_add(e);
918 evas_object_color_set(wd->cp[i]->touch_area, 0, 0, 0, 0);
919 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.arrow_bg",
920 wd->cp[i]->touch_area);
921 evas_object_event_callback_add(wd->cp[i]->touch_area,
922 EVAS_CALLBACK_MOUSE_DOWN, _colorbar_cb,
923 wd->cp[i]);
924 elm_widget_sub_object_add(obj, wd->cp[i]->touch_area);
925
926 /* load background rectangle of the colorbar. used for
927 changing color of the opacity bar */
928 if ((i == 1) || (i == 2))
929 {
930 wd->cp[i]->bg_rect = evas_object_rectangle_add(e);
931 evas_object_color_set(wd->cp[i]->bg_rect, wd->er, wd->eg, wd->eb,
932 255);
933 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar_bg",
934 wd->cp[i]->bg_rect);
935
936 elm_widget_sub_object_add(obj, wd->cp[i]->bg_rect);
937 }
938 if (i == 3)
939 {
940 wd->cp[i]->bg_rect = edje_object_add(e);
941 snprintf(buf, sizeof(buf), "%s/%s", colorbar_name,
942 elm_widget_style_get(obj));
943 _elm_theme_object_set(obj, wd->cp[i]->bg_rect, "colorselector",
944 "bg_image", buf);
945 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.bar_bg",
946 wd->cp[i]->bg_rect);
947 elm_widget_sub_object_add(obj, wd->cp[i]->bg_rect);
948 evas_object_color_set(wd->cp[i]->bar, wd->er, wd->eg, wd->eb, 255);
949 }
950 /* load arrow image, pointing the colorbar */
951 wd->cp[i]->arrow = edje_object_add(e);
952 _elm_theme_object_set(obj, wd->cp[i]->arrow, "colorselector", "arrow",
953 elm_widget_style_get(obj));
954 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.arrow_icon",
955 wd->cp[i]->arrow);
956 elm_widget_sub_object_add(obj, wd->cp[i]->arrow);
957 if (i == 2)
958 evas_object_color_set(wd->cp[i]->arrow, 0, 0, 0, 255);
959 else
960 evas_object_color_set(wd->cp[i]->arrow, wd->er, wd->eg, wd->eb, 255);
961
962 /* load left button */
963 wd->cp[i]->lbt = elm_button_add(obj);
964 snprintf(buf, sizeof(buf), "colorselector/left/%s",
965 elm_widget_style_get(obj));
966 elm_object_style_set(wd->cp[i]->lbt, buf);
967 elm_widget_sub_object_add(obj, wd->cp[i]->lbt);
968 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.l_button",
969 wd->cp[i]->lbt);
970 evas_object_smart_callback_add(wd->cp[i]->lbt, "clicked",
971 _left_button_clicked_cb, wd->cp[i]);
972 elm_button_autorepeat_set(wd->cp[i]->lbt, EINA_TRUE);
973 elm_button_autorepeat_initial_timeout_set(wd->cp[i]->lbt,
974 _elm_config->longpress_timeout);
975 elm_button_autorepeat_gap_timeout_set(wd->cp[i]->lbt,
976 (1.0 / _elm_config->fps));
977 evas_object_smart_callback_add(wd->cp[i]->lbt, "repeated",
978 _left_button_repeat_cb, wd->cp[i]);
979
980 /* load right button */
981 wd->cp[i]->rbt = elm_button_add(obj);
982 snprintf(buf, sizeof(buf), "colorselector/right/%s",
983 elm_widget_style_get(obj));
984 elm_object_style_set(wd->cp[i]->rbt, buf);
985 elm_widget_sub_object_add(obj, wd->cp[i]->rbt);
986 edje_object_part_swallow(wd->cp[i]->colorbar, "elm.r_button",
987 wd->cp[i]->rbt);
988 evas_object_smart_callback_add(wd->cp[i]->rbt, "clicked",
989 _right_button_clicked_cb, wd->cp[i]);
990 elm_button_autorepeat_set(wd->cp[i]->rbt, EINA_TRUE);
991 elm_button_autorepeat_initial_timeout_set(wd->cp[i]->rbt,
992 _elm_config->longpress_timeout);
993 elm_button_autorepeat_gap_timeout_set(wd->cp[i]->rbt,
994 (1.0 / _elm_config->fps));
995 evas_object_smart_callback_add(wd->cp[i]->rbt, "repeated",
996 _right_button_repeat_cb, wd->cp[i]);
997 }
998}
999
1000static void
1001_set_color(Evas_Object *obj, int r, int g, int b, int a)
1002{
1003 Widget_Data *wd = elm_widget_data_get(obj);
1004 double x, y;
1005
1006 wd->r = r;
1007 wd->g = g;
1008 wd->b = b;
1009 wd->a = a;
1010
1011 _rgb_to_hsl(wd);
1012
1013 edje_object_part_drag_value_get(wd->cp[0]->colorbar, "elm.arrow", &x, &y);
1014 x = wd->h / 360.0;
1015 edje_object_part_drag_value_set(wd->cp[0]->colorbar, "elm.arrow", x, y);
1016 _draw_rects(wd->cp[0], x);
1017
1018 edje_object_part_drag_value_get(wd->cp[1]->colorbar, "elm.arrow", &x, &y);
1019 x = 1.0 - wd->s;
1020 edje_object_part_drag_value_set(wd->cp[1]->colorbar, "elm.arrow", x, y);
1021 _draw_rects(wd->cp[1], x);
1022
1023 edje_object_part_drag_value_get(wd->cp[2]->colorbar, "elm.arrow", &x, &y);
1024 x = wd->l;
1025 edje_object_part_drag_value_set(wd->cp[2]->colorbar, "elm.arrow", x, y);
1026 _draw_rects(wd->cp[2], x);
1027
1028 edje_object_part_drag_value_get(wd->cp[3]->colorbar, "elm.arrow", &x, &y);
1029 x = wd->a / 255.0;
1030 edje_object_part_drag_value_set(wd->cp[3]->colorbar, "elm.arrow", x, y);
1031 _draw_rects(wd->cp[3], x);
1032}
1033
1034EAPI Evas_Object *
1035elm_colorselector_add(Evas_Object *parent)
1036{
1037 Evas_Object *obj = NULL;
1038 Widget_Data *wd = NULL;
1039 Evas *e;
1040 const char *hpadstr, *vpadstr;
1041 unsigned int h_pad = DEFAULT_HOR_PAD;
1042 unsigned int v_pad = DEFAULT_VER_PAD;
1043
1044 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1045
1046 ELM_SET_WIDTYPE(widtype, "colorselector");
1047 elm_widget_type_set(obj, "colorselector");
1048 elm_widget_sub_object_add(parent, obj);
1049 elm_widget_data_set(obj, wd);
1050 elm_widget_del_hook_set(obj, _del_hook);
1051 elm_widget_theme_hook_set(obj, _theme_hook);
1052 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1053
1054 /* load background edj */
1055 wd->base = edje_object_add(e);
1056 _elm_theme_object_set(obj, wd->base, "colorselector", "palette", "default");
1057 elm_widget_resize_object_set(obj, wd->base);
1058 evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE,
1059 _resize_cb, obj);
1060
1061 wd->box = elm_box_add(obj);
1062 elm_box_layout_set(wd->box, evas_object_box_layout_flow_horizontal,
1063 NULL, NULL);
1064 elm_box_horizontal_set(wd->box, EINA_TRUE);
1065 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND,
1066 0);
1067 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0);
1068 elm_box_homogeneous_set(wd->box, EINA_TRUE);
1069 hpadstr = edje_object_data_get(wd->base, "horizontal_pad");
1070 if (hpadstr) h_pad = atoi(hpadstr);
1071 vpadstr = edje_object_data_get(wd->base, "vertical_pad");
1072 if (vpadstr) v_pad = atoi(vpadstr);
1073 elm_box_padding_set(wd->box, (Evas_Coord)(h_pad * elm_widget_scale_get(obj) * _elm_config->scale),
1074 (Evas_Coord)(v_pad * elm_widget_scale_get(obj) *_elm_config->scale));
1075 elm_box_align_set(wd->box, 0.5, 0.5);
1076 elm_widget_sub_object_add(obj, wd->box);
1077 evas_object_show(wd->box);
1078 edje_object_part_swallow(wd->base, "palette", wd->box);
1079 wd->palette_name = eina_stringshare_add("default");
1080 _colors_load_apply(obj);
1081
1082 /* load background edj */
1083 wd->sel = edje_object_add(e);
1084 _elm_theme_object_set(obj, wd->sel, "colorselector", "bg", "default");
1085 edje_object_part_swallow(wd->base, "selector", wd->sel);
1086 elm_widget_sub_object_add(obj, wd->sel);
1087
1088 wd->mode = ELM_COLORSELECTOR_BOTH;
1089 wd->er = 255;
1090 wd->eg = 0;
1091 wd->eb = 0;
1092 wd->h = 0.0;
1093 wd->s = 1.0;
1094 wd->l = 0.0;
1095 wd->a = 255;
1096
1097 _hsl_to_rgb(wd);
1098 _add_colorbar(obj);
1099 _sizing_eval(obj);
1100
1101 return obj;
1102}
1103
1104EAPI void
1105elm_colorselector_color_set(Evas_Object *obj, int r, int g, int b, int a)
1106{
1107 ELM_CHECK_WIDTYPE(obj, widtype);
1108 _set_color(obj, r, g, b, a);
1109}
1110
1111EAPI void
1112elm_colorselector_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1113{
1114 ELM_CHECK_WIDTYPE(obj, widtype);
1115 Widget_Data *wd = elm_widget_data_get(obj);
1116
1117 if (r) *r = wd->r;
1118 if (g) *g = wd->g;
1119 if (b) *b = wd->b;
1120 if (a) *a = wd->a;
1121}
1122
1123EAPI void
1124elm_colorselector_mode_set(Evas_Object *obj, Elm_Colorselector_Mode mode)
1125{
1126 ELM_CHECK_WIDTYPE(obj, widtype);
1127 Widget_Data *wd = elm_widget_data_get(obj);
1128 if (!wd) return;
1129 if (wd->mode == mode) return;
1130 wd->mode = mode;
1131 switch (wd->mode)
1132 {
1133 case ELM_COLORSELECTOR_PALETTE:
1134 if (edje_object_part_swallow_get(wd->base, "selector"))
1135 {
1136 edje_object_part_unswallow(wd->base, wd->sel);
1137 evas_object_hide(wd->sel);
1138 }
1139 if (!edje_object_part_swallow_get(wd->base, "palette"))
1140 {
1141 edje_object_part_swallow(wd->base, "palette", wd->box);
1142 evas_object_show(wd->box);
1143 }
1144 edje_object_signal_emit(wd->base, "elm,state,palette", "elm");
1145 break;
1146 case ELM_COLORSELECTOR_COMPONENTS:
1147 if (edje_object_part_swallow_get(wd->base, "palette"))
1148 {
1149 edje_object_part_unswallow(wd->base, wd->box);
1150 evas_object_hide(wd->box);
1151 }
1152 if (!edje_object_part_swallow_get(wd->base, "selector"))
1153 {
1154 edje_object_part_swallow(wd->base, "selector", wd->sel);
1155 evas_object_show(wd->sel);
1156 }
1157 edje_object_signal_emit(wd->base, "elm,state,components", "elm");
1158 break;
1159 case ELM_COLORSELECTOR_BOTH:
1160 if (!edje_object_part_swallow_get(wd->base, "palette"))
1161 {
1162 edje_object_part_swallow(wd->base, "palette", wd->box);
1163 evas_object_show(wd->box);
1164 }
1165 if (!edje_object_part_swallow_get(wd->base, "selector"))
1166 {
1167 edje_object_part_swallow(wd->base, "selector", wd->sel);
1168 evas_object_show(wd->sel);
1169 }
1170 edje_object_signal_emit(wd->base, "elm,state,both", "elm");
1171 break;
1172 default:
1173 return;
1174 }
1175 edje_object_message_signal_process(wd->base);
1176
1177 _sizing_eval(obj);
1178}
1179
1180EAPI Elm_Colorselector_Mode
1181elm_colorselector_mode_get(const Evas_Object *obj)
1182{
1183 ELM_CHECK_WIDTYPE(obj, widtype) ELM_COLORSELECTOR_BOTH;
1184 Widget_Data *wd = elm_widget_data_get(obj);
1185 if (!wd) return ELM_COLORSELECTOR_BOTH;
1186 return wd->mode;
1187}
1188
1189EAPI void
1190elm_colorselector_palette_item_color_get(const Elm_Object_Item *it, int *r __UNUSED__, int *g __UNUSED__, int *b __UNUSED__, int*a __UNUSED__)
1191{
1192 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1193 Elm_Color_Item *item;
1194 item = (Elm_Color_Item *) it;
1195 if (item)
1196 {
1197 if (r) *r = item->color->r;
1198 if (g) *g = item->color->g;
1199 if (b) *b = item->color->b;
1200 if (a) *a = item->color->a;
1201 }
1202}
1203
1204EAPI void
1205elm_colorselector_palette_item_color_set(Elm_Object_Item *it, int r __UNUSED__, int g __UNUSED__, int b __UNUSED__, int a __UNUSED__)
1206{
1207 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1208 Elm_Color_Item *item;
1209 item = (Elm_Color_Item *) it;
1210 item->color->r = r;
1211 item->color->g = g;
1212 item->color->b = b;
1213 item->color->a = a;
1214 evas_object_color_set(item->color_obj, item->color->r, item->color->g, item->color->b, item->color->a);
1215 _colors_save(WIDGET(it));
1216}
1217
1218EAPI Elm_Object_Item *
1219elm_colorselector_palette_color_add(Evas_Object *obj, int r, int g, int b, int a)
1220{
1221 Elm_Color_Item *item;
1222 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1223 Widget_Data *wd = elm_widget_data_get(obj);
1224 if (!wd) return NULL;
1225 if (wd->config_load)
1226 {
1227 _colors_remove(obj);
1228 wd->config_load = EINA_FALSE;
1229 }
1230 item = _item_new(obj);
1231 if (!item) return NULL;
1232 item->color = ELM_NEW(Elm_Color_RGBA);
1233 if (!item->color) return NULL;
1234 item->color->r = r;
1235 item->color->g = g;
1236 item->color->b = b;
1237 item->color->a = a;
1238 _elm_config_color_set(wd->palette_name, item->color->r, item->color->g,
1239 item->color->b, item->color->a);
1240 elm_box_pack_end(wd->box, VIEW(item));
1241 evas_object_color_set(item->color_obj, item->color->r, item->color->g,
1242 item->color->b, item->color->a);
1243 wd->items = eina_list_append(wd->items, item);
1244 _sizing_eval(obj);
1245 return (Elm_Object_Item *) item;
1246}
1247
1248EAPI void
1249elm_colorselector_palette_clear(Evas_Object *obj)
1250{
1251 ELM_CHECK_WIDTYPE(obj, widtype);
1252 Widget_Data *wd = elm_widget_data_get(obj);
1253 if (!wd) return;
1254 _colors_remove(obj);
1255}
1256
1257EAPI void
1258elm_colorselector_palette_name_set(Evas_Object *obj, const char *palette_name)
1259{
1260 ELM_CHECK_WIDTYPE(obj, widtype);
1261 Widget_Data *wd = elm_widget_data_get(obj);
1262 if (!wd) return;
1263 if (!strcmp(wd->palette_name, palette_name)) return;
1264 if (palette_name)
1265 {
1266 _colors_remove(obj);
1267 eina_stringshare_replace(&wd->palette_name, palette_name);
1268 _colors_load_apply(obj);
1269 }
1270}
1271
1272EAPI const char*
1273elm_colorselector_palette_name_get(const Evas_Object *obj)
1274{
1275 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1276 Widget_Data *wd = elm_widget_data_get(obj);
1277 if (!wd) return NULL;
1278 return wd->palette_name;
1279}
diff --git a/libraries/elementary/src/lib/elm_colorselector.h b/libraries/elementary/src/lib/elm_colorselector.h
new file mode 100644
index 0000000..76c6c97
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_colorselector.h
@@ -0,0 +1,192 @@
1/**
2 * @defgroup Colorselector Colorselector
3 * @ingroup Elementary
4 *
5 * @image html img/widget/colorselector/preview-00.png
6 * @image latex img/widget/colorselector/preview-00.eps
7 *
8 * A ColorSelector is a color selection widget. It allows application to set a
9 * series of colors.It also allows to load/save colors from/to config with a
10 * unique identifier, by default, the colors are loaded/saved from/to config
11 * using "default" identifier.
12 * The colors can be picked by user from the color set by clicking on individual color
13 * item on the palette or by selecting it from selector.
14 *
15 * Signals that you can add callbacks for are:
16 * - "changed" - When the color value changes on selector(event_info is NULL).
17 * - "color,item,selected" - When user clicks on color item. The event_info parameter
18 * of the callback will be the selected color item.
19 * - "color,item,longpressed" - When user long presses on color item. The event info
20 * parameter of the callback contains selected color item.
21 *
22 * See @ref tutorial_colorselector.
23 * @{
24 */
25
26typedef struct _Elm_Color_RGBA
27{
28 unsigned int r;
29 unsigned int g;
30 unsigned int b;
31 unsigned int a;
32} Elm_Color_RGBA;
33
34typedef struct _Elm_Custom_Palette
35{
36 const char *palette_name;
37 Eina_List *color_list;
38} Elm_Custom_Palette;
39
40/**
41 * @enum _Elm_Colorselector_Mode
42 * @typedef Elm_Colorselector_Mode
43 *
44 * Different modes supported by Colorselector
45 *
46 * @see elm_colorselector_mode_set()
47 * @see elm_colorselector_mode_get()
48 */
49typedef enum
50{
51 ELM_COLORSELECTOR_PALETTE = 0, /**< only color palette is displayed */
52 ELM_COLORSELECTOR_COMPONENTS, /**< only color selector is displayed */
53 ELM_COLORSELECTOR_BOTH /**< Both Palette and selector is displayed, default */
54} Elm_Colorselector_Mode;
55
56/**
57 * @brief Add a new colorselector to the parent
58 *
59 * @param parent The parent object
60 * @return The new object or NULL if it cannot be created
61 *
62 * @ingroup Colorselector
63 */
64EAPI Evas_Object *elm_colorselector_add(Evas_Object *parent);
65
66/**
67 * Set color to colorselector
68 *
69 * @param obj Colorselector object
70 * @param r r-value of color
71 * @param g g-value of color
72 * @param b b-value of color
73 * @param a a-value of color
74 *
75 * @ingroup Colorselector
76 */
77EAPI void elm_colorselector_color_set(Evas_Object *obj, int r, int g, int b, int a);
78
79/**
80 * Get current color from colorselector
81 *
82 * @param obj Colorselector object
83 * @param r integer pointer for r-value of color
84 * @param g integer pointer for g-value of color
85 * @param b integer pointer for b-value of color
86 * @param a integer pointer for a-value of color
87 *
88 * @ingroup Colorselector
89 */
90EAPI void elm_colorselector_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a);
91
92/**
93 * Set Colorselector's mode.
94 *
95 * @param obj Colorselector object
96 * @param mode Elm_Colorselector_Mode
97 *
98 * Colorselector supports three modes palette only, selector only and both.
99 *
100 * @ingroup Colorselector
101 */
102EAPI void elm_colorselector_mode_set(Evas_Object *obj, Elm_Colorselector_Mode mode);
103
104/**
105 * Get Colorselector's mode.
106 *
107 * @param obj Colorselector object
108 * @return mode The current mode of colorselector
109 *
110 * @ingroup Colorselector
111 */
112EAPI Elm_Colorselector_Mode elm_colorselector_mode_get(const Evas_Object *obj);
113
114/**
115 * Get Palette item's color.
116 *
117 * @param it The color palette item.
118 * @param r integer pointer for r-value of color
119 * @param g integer pointer for g-value of color
120 * @param b integer pointer for b-value of color
121 * @param a integer pointer for a-value of color
122 *
123 * @ingroup Colorselector
124 */
125EAPI void elm_colorselector_palette_item_color_get(const Elm_Object_Item *it, int *r, int *g, int *b, int *a);
126
127/**
128 * Set palette item's color.
129 *
130 * @param it The color palette item.
131 * @param r r-value of color
132 * @param g g-value of color
133 * @param b b-value of color
134 * @param a a-value of color
135 *
136 * @ingroup Colorselector
137 */
138EAPI void elm_colorselector_palette_item_color_set(Elm_Object_Item *it, int r, int g, int b, int a);
139
140/**
141 * Add a new color item to palette.
142 *
143 * @param obj The Colorselector object
144 * @param r r-value of color
145 * @param g g-value of color
146 * @param b b-value of color
147 * @param a a-value of color
148 * @return A new color palette Item.
149 *
150 * @ingroup Colorselector
151 */
152EAPI Elm_Object_Item *elm_colorselector_palette_color_add(Evas_Object *obj, int r, int g, int b, int a);
153
154/**
155 * Clear the palette items.
156 *
157 * @param obj The Colorselector object
158 *
159 * @ingroup Colorselector
160 */
161EAPI void elm_colorselector_palette_clear(Evas_Object *obj);
162
163/**
164 * Set current palette's name
165 *
166 * @param obj The Colorselector object
167 * @param palette_name Name of palette
168 *
169 * When colorpalette name is set, colors will be loaded from and saved to config
170 * using the set name. If no name is set then colors will be loaded from or
171 * saved to "default" config.
172 *
173 * @ingroup Colorselector
174 */
175EAPI void elm_colorselector_palette_name_set(Evas_Object *obj, const char *palette_name);
176
177/**
178 * Get current palette's name
179 *
180 * @param obj The Colorselector object
181 * @return Name of palette
182 *
183 * Returns the currently set palette name using which colors will be
184 * saved/loaded in to config.
185 *
186 * @ingroup Colorselector
187 */
188EAPI const char *elm_colorselector_palette_name_get(const Evas_Object *obj);
189
190/**
191 * @}
192 */
diff --git a/libraries/elementary/src/lib/elm_config.c b/libraries/elementary/src/lib/elm_config.c
new file mode 100644
index 0000000..f4744a5
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_config.c
@@ -0,0 +1,2215 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#include <Elementary.h>
10#include "elm_priv.h"
11
12EAPI int ELM_EVENT_CONFIG_ALL_CHANGED = 0;
13
14Elm_Config *_elm_config = NULL;
15char *_elm_profile = NULL;
16static Eet_Data_Descriptor *_config_edd = NULL;
17static Eet_Data_Descriptor *_config_font_overlay_edd = NULL;
18static Eet_Data_Descriptor *_config_color_edd = NULL;
19static Eet_Data_Descriptor *_config_color_palette_edd = NULL;
20const char *_elm_preferred_engine = NULL;
21
22static Ecore_Poller *_elm_cache_flush_poller = NULL;
23
24const char *_elm_engines[] = {
25 "software_x11",
26 "fb",
27 "directfb",
28 "software_16_x11",
29 "software_8_x11",
30 "xrender_x11",
31 "opengl_x11",
32 "software_gdi",
33 "software_16_wince_gdi",
34 "sdl",
35 "software_16_sdl",
36 "opengl_sdl",
37 "buffer",
38 "ews",
39 "opengl_cocoa",
40 "psl1ght",
41 "wayland_shm",
42 "wayland_egl",
43 NULL
44};
45
46/* whenever you want to add a new text class support into Elementary,
47 declare it both here and in the (default) theme */
48static const Elm_Text_Class _elm_text_classes[] = {
49 {"button", "Button Labels"},
50 {"label", "Text Labels"},
51 {"entry", "Text Entries"},
52 {"title_bar", "Title Bar"},
53 {"list_item", "List Items"},
54 {"grid_item", "Grid Items"},
55 {"toolbar_item", "Toolbar Items"},
56 {"menu_item", "Menu Items"},
57 {NULL, NULL}
58};
59
60static void _desc_init(void);
61static void _desc_shutdown(void);
62static void _profile_fetch_from_conf(void);
63static void _config_free(void);
64static void _config_apply(void);
65static Elm_Config *_config_user_load(void);
66static Elm_Config *_config_system_load(void);
67static void _config_load(void);
68static void _config_update(void);
69static void _env_get(void);
70static size_t _elm_data_dir_snprintf(char *dst,
71 size_t size,
72 const char *fmt, ...)
73 EINA_PRINTF(3, 4);
74static size_t _elm_user_dir_snprintf(char *dst,
75 size_t size,
76 const char *fmt, ...)
77 EINA_PRINTF(3, 4);
78
79#define ELM_CONFIG_VAL(edd, type, member, dtype) \
80 EET_DATA_DESCRIPTOR_ADD_BASIC(edd, type, #member, member, dtype)
81#define ELM_CONFIG_LIST(edd, type, member, eddtype) \
82 EET_DATA_DESCRIPTOR_ADD_LIST(edd, type, #member, member, eddtype)
83
84#ifdef HAVE_ELEMENTARY_X
85static Ecore_Event_Handler *_prop_change_handler = NULL;
86static Ecore_Timer *_prop_all_update_timer = NULL;
87static Ecore_Timer *_prop_change_delay_timer = NULL;
88static Ecore_X_Window _root_1st = 0;
89#define ATOM_COUNT 2
90static Ecore_X_Atom _atom[ATOM_COUNT];
91static Ecore_X_Atom _atom_config = 0;
92static const char *_atom_names[ATOM_COUNT] =
93{
94 "ELM_PROFILE",
95 "ELM_CONFIG"
96};
97#define ATOM_E_PROFILE 0
98#define ATOM_E_CONFIG 1
99
100static Eina_Bool _prop_all_update_cb(void *data __UNUSED__);
101static Eina_Bool _prop_config_get(void);
102static void _prop_config_set(void);
103static Eina_Bool _prop_change(void *data __UNUSED__,
104 int ev_type __UNUSED__,
105 void *ev);
106
107static Eina_Bool
108_prop_all_update_cb(void *data __UNUSED__)
109{
110 _prop_config_set();
111 ecore_x_window_prop_string_set(_root_1st, _atom[ATOM_E_PROFILE],
112 _elm_profile);
113 _prop_all_update_timer = NULL;
114 return EINA_FALSE;
115}
116
117static Eina_Bool
118_prop_config_get(void)
119{
120 int size = 0;
121 Ecore_X_Atom atom;
122 char buf[512];
123 unsigned char *data = NULL;
124 Elm_Config *config_data;
125
126 snprintf(buf, sizeof(buf), "ELM_CONFIG_%s", _elm_profile);
127 atom = ecore_x_atom_get(buf);
128 _atom_config = atom;
129 if (!ecore_x_window_prop_property_get(_root_1st,
130 atom, _atom[ATOM_E_CONFIG],
131 8, &data, &size))
132 {
133 if (!ecore_x_window_prop_property_get(_root_1st,
134 _atom[ATOM_E_CONFIG],
135 _atom[ATOM_E_CONFIG],
136 8, &data, &size))
137 return EINA_FALSE;
138 else
139 _atom_config = _atom[ATOM_E_CONFIG];
140 }
141 else
142 _atom_config = atom;
143 if (size < 1)
144 {
145 free(data);
146 return EINA_FALSE;
147 }
148 config_data = eet_data_descriptor_decode(_config_edd, data, size);
149 free(data);
150 if (!config_data) return EINA_FALSE;
151
152 /* What do we do on version mismatch when someone changes the
153 * config in the rootwindow? */
154 /* Most obvious case, new version and we are still linked to
155 * whatever was there before, we just ignore until user restarts us */
156 if (config_data->config_version > ELM_CONFIG_VERSION)
157 return EINA_TRUE;
158 /* What in the case the version is older? Do we even support those
159 * cases or we only check for equality above? */
160
161 _config_free();
162 _elm_config = config_data;
163 _config_apply();
164 _elm_config_font_overlay_apply();
165 _elm_rescale();
166 _elm_recache();
167 ecore_event_add(ELM_EVENT_CONFIG_ALL_CHANGED, NULL, NULL, NULL);
168 return EINA_TRUE;
169}
170
171static void
172_prop_config_set(void)
173{
174 unsigned char *config_data = NULL;
175 int size = 0;
176
177 config_data = eet_data_descriptor_encode(_config_edd, _elm_config, &size);
178 if (config_data)
179 {
180 Ecore_X_Atom atom;
181 char buf[512];
182
183 snprintf(buf, sizeof(buf), "ELM_CONFIG_%s", _elm_profile);
184 atom = ecore_x_atom_get(buf);
185 _atom_config = atom;
186
187 ecore_x_window_prop_property_set(_root_1st, _atom_config,
188 _atom[ATOM_E_CONFIG], 8,
189 config_data, size);
190 free(config_data);
191 }
192}
193
194static Eina_Bool
195_prop_change_delay_cb(void *data __UNUSED__)
196{
197 char *s;
198
199 s = ecore_x_window_prop_string_get(_root_1st, _atom[ATOM_E_PROFILE]);
200 if (s)
201 {
202 if (_elm_profile) free(_elm_profile);
203 _elm_profile = s;
204 }
205 _prop_config_get();
206 _prop_change_delay_timer = NULL;
207 return EINA_FALSE;
208}
209
210static Eina_Bool
211_prop_change(void *data __UNUSED__,
212 int ev_type __UNUSED__,
213 void *ev)
214{
215 Ecore_X_Event_Window_Property *event = ev;
216
217 if (event->win == _root_1st)
218 {
219 if (event->atom == _atom[ATOM_E_PROFILE])
220 {
221 if (_prop_change_delay_timer) ecore_timer_del(_prop_change_delay_timer);
222 _prop_change_delay_timer = ecore_timer_add(0.1, _prop_change_delay_cb, NULL);
223 }
224 else if (((_atom_config > 0) && (event->atom == _atom_config)) ||
225 (event->atom == _atom[ATOM_E_CONFIG]))
226 {
227 if (_prop_change_delay_timer) ecore_timer_del(_prop_change_delay_timer);
228 _prop_change_delay_timer = ecore_timer_add(0.1, _prop_change_delay_cb, NULL);
229 }
230 }
231 return ECORE_CALLBACK_PASS_ON;
232}
233
234#endif
235
236static void
237_desc_init(void)
238{
239 Eet_Data_Descriptor_Class eddc;
240
241 EET_EINA_FILE_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Config);
242 eddc.func.str_direct_alloc = NULL;
243 eddc.func.str_direct_free = NULL;
244
245 _config_edd = eet_data_descriptor_file_new(&eddc);
246 if (!_config_edd)
247 {
248 printf("EEEK! eet_data_descriptor_file_new() failed\n");
249 return;
250 }
251
252 memset(&eddc, 0, sizeof(eddc)); /* just in case... */
253 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Font_Overlay);
254 eddc.func.str_direct_alloc = NULL;
255 eddc.func.str_direct_free = NULL;
256
257 _config_font_overlay_edd = eet_data_descriptor_stream_new(&eddc);
258 if (!_config_font_overlay_edd)
259 {
260 printf("EEEK! eet_data_descriptor_stream_new() failed\n");
261 eet_data_descriptor_free(_config_edd);
262 return;
263 }
264
265 memset(&eddc, 0, sizeof(eddc)); /* just in case... */
266 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Color_RGBA);
267 eddc.func.str_direct_alloc = NULL;
268 eddc.func.str_direct_free = NULL;
269
270 _config_color_edd = eet_data_descriptor_stream_new(&eddc);
271 if (!_config_color_edd)
272 {
273 printf("EEEK! eet_data_descriptor_stream_new() failed\n");
274 eet_data_descriptor_free(_config_edd);
275 return;
276 }
277
278 memset(&eddc, 0, sizeof(eddc)); /* just in case... */
279 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Elm_Custom_Palette);
280 eddc.func.str_direct_alloc = NULL;
281 eddc.func.str_direct_free = NULL;
282
283 _config_color_palette_edd = eet_data_descriptor_stream_new(&eddc);
284 if (!_config_color_palette_edd)
285 {
286 printf("EEEK! eet_data_descriptor_stream_new() failed\n");
287 eet_data_descriptor_free(_config_edd);
288 return;
289 }
290
291#define T_INT EET_T_INT
292#define T_DOUBLE EET_T_DOUBLE
293#define T_STRING EET_T_STRING
294#define T_UCHAR EET_T_UCHAR
295
296#define T Elm_Font_Overlay
297#define D _config_font_overlay_edd
298 ELM_CONFIG_VAL(D, T, text_class, EET_T_STRING);
299 ELM_CONFIG_VAL(D, T, font, EET_T_STRING);
300 ELM_CONFIG_VAL(D, T, size, EET_T_INT);
301#undef T
302#undef D
303
304#define T Elm_Color_RGBA
305#define D _config_color_edd
306 ELM_CONFIG_VAL(D, T, r, EET_T_UINT);
307 ELM_CONFIG_VAL(D, T, g, EET_T_UINT);
308 ELM_CONFIG_VAL(D, T, b, EET_T_UINT);
309 ELM_CONFIG_VAL(D, T, a, EET_T_UINT);
310#undef T
311#undef D
312
313#define T Elm_Custom_Palette
314#define D _config_color_palette_edd
315 ELM_CONFIG_VAL(D, T, palette_name, EET_T_STRING);
316 ELM_CONFIG_LIST(D, T, color_list, _config_color_edd);
317#undef T
318#undef D
319
320#define T Elm_Config
321#define D _config_edd
322 ELM_CONFIG_VAL(D, T, config_version, T_INT);
323 ELM_CONFIG_VAL(D, T, engine, T_STRING);
324 ELM_CONFIG_VAL(D, T, vsync, T_UCHAR);
325 ELM_CONFIG_VAL(D, T, thumbscroll_enable, T_UCHAR);
326 ELM_CONFIG_VAL(D, T, thumbscroll_threshold, T_INT);
327 ELM_CONFIG_VAL(D, T, thumbscroll_momentum_threshold, T_DOUBLE);
328 ELM_CONFIG_VAL(D, T, thumbscroll_friction, T_DOUBLE);
329 ELM_CONFIG_VAL(D, T, thumbscroll_bounce_friction, T_DOUBLE);
330 ELM_CONFIG_VAL(D, T, thumbscroll_border_friction, T_DOUBLE);
331 ELM_CONFIG_VAL(D, T, thumbscroll_sensitivity_friction, T_DOUBLE);
332 ELM_CONFIG_VAL(D, T, page_scroll_friction, T_DOUBLE);
333 ELM_CONFIG_VAL(D, T, bring_in_scroll_friction, T_DOUBLE);
334 ELM_CONFIG_VAL(D, T, zoom_friction, T_DOUBLE);
335 ELM_CONFIG_VAL(D, T, thumbscroll_bounce_enable, T_UCHAR);
336 ELM_CONFIG_VAL(D, T, scroll_smooth_amount, T_DOUBLE);
337 ELM_CONFIG_VAL(D, T, scroll_smooth_history_weight, T_DOUBLE);
338 ELM_CONFIG_VAL(D, T, scroll_smooth_future_time, T_DOUBLE);
339 ELM_CONFIG_VAL(D, T, scroll_smooth_time_window, T_DOUBLE);
340 ELM_CONFIG_VAL(D, T, scale, T_DOUBLE);
341 ELM_CONFIG_VAL(D, T, bgpixmap, T_INT);
342 ELM_CONFIG_VAL(D, T, compositing, T_INT);
343 /* EET_DATA_DESCRIPTOR_ADD_LIST(D, T, "font_dirs", font_dirs, sub_edd); */
344 ELM_CONFIG_LIST(D, T, font_overlays, _config_font_overlay_edd);
345 ELM_CONFIG_VAL(D, T, font_hinting, T_INT);
346 ELM_CONFIG_VAL(D, T, cache_flush_poll_interval, T_INT);
347 ELM_CONFIG_VAL(D, T, cache_flush_enable, T_UCHAR);
348 ELM_CONFIG_VAL(D, T, image_cache, T_INT);
349 ELM_CONFIG_VAL(D, T, font_cache, T_INT);
350 ELM_CONFIG_VAL(D, T, edje_cache, T_INT);
351 ELM_CONFIG_VAL(D, T, edje_collection_cache, T_INT);
352 ELM_CONFIG_VAL(D, T, finger_size, T_INT);
353 ELM_CONFIG_VAL(D, T, fps, T_DOUBLE);
354 ELM_CONFIG_VAL(D, T, theme, T_STRING);
355 ELM_CONFIG_VAL(D, T, modules, T_STRING);
356 ELM_CONFIG_VAL(D, T, tooltip_delay, T_DOUBLE);
357 ELM_CONFIG_VAL(D, T, cursor_engine_only, T_UCHAR);
358 ELM_CONFIG_VAL(D, T, focus_highlight_enable, T_UCHAR);
359 ELM_CONFIG_VAL(D, T, focus_highlight_animate, T_UCHAR);
360 ELM_CONFIG_VAL(D, T, toolbar_shrink_mode, T_INT);
361 ELM_CONFIG_VAL(D, T, fileselector_expand_enable, T_UCHAR);
362 ELM_CONFIG_VAL(D, T, inwin_dialogs_enable, T_UCHAR);
363 ELM_CONFIG_VAL(D, T, icon_size, T_INT);
364 ELM_CONFIG_VAL(D, T, longpress_timeout, T_DOUBLE);
365 ELM_CONFIG_VAL(D, T, effect_enable, T_UCHAR);
366 ELM_CONFIG_VAL(D, T, desktop_entry, T_UCHAR);
367 ELM_CONFIG_VAL(D, T, password_show_last, T_UCHAR);
368 ELM_CONFIG_VAL(D, T, password_show_last_timeout, T_DOUBLE);
369 ELM_CONFIG_VAL(D, T, glayer_zoom_finger_enable, T_UCHAR);
370 ELM_CONFIG_VAL(D, T, glayer_zoom_finger_factor, T_DOUBLE);
371 ELM_CONFIG_VAL(D, T, glayer_zoom_wheel_factor, T_DOUBLE);
372 ELM_CONFIG_VAL(D, T, glayer_zoom_distance_tolerance, T_DOUBLE);
373 ELM_CONFIG_VAL(D, T, glayer_rotate_finger_enable, T_UCHAR);
374 ELM_CONFIG_VAL(D, T, glayer_rotate_angular_tolerance, T_DOUBLE);
375 ELM_CONFIG_VAL(D, T, glayer_line_min_length, T_DOUBLE);
376 ELM_CONFIG_VAL(D, T, glayer_line_distance_tolerance, T_DOUBLE);
377 ELM_CONFIG_VAL(D, T, glayer_line_angular_tolerance, T_DOUBLE);
378 ELM_CONFIG_VAL(D, T, glayer_flick_time_limit_ms, T_INT);
379 ELM_CONFIG_VAL(D, T, glayer_long_tap_start_timeout, T_DOUBLE);
380 ELM_CONFIG_VAL(D, T, access_mode, T_INT);
381 ELM_CONFIG_VAL(D, T, glayer_continues_enable, T_UCHAR);
382 ELM_CONFIG_VAL(D, T, week_start, T_INT);
383 ELM_CONFIG_VAL(D, T, weekend_start, T_INT);
384 ELM_CONFIG_VAL(D, T, weekend_len, T_INT);
385 ELM_CONFIG_VAL(D, T, year_min, T_INT);
386 ELM_CONFIG_VAL(D, T, year_max, T_INT);
387 ELM_CONFIG_LIST(D, T, color_palette, _config_color_palette_edd);
388#undef T
389#undef D
390#undef T_INT
391#undef T_DOUBLE
392#undef T_STRING
393#undef T_UCHAR
394}
395
396static void
397_desc_shutdown(void)
398{
399 if (_config_edd)
400 {
401 eet_data_descriptor_free(_config_edd);
402 _config_edd = NULL;
403 }
404
405 if (_config_font_overlay_edd)
406 {
407 eet_data_descriptor_free(_config_font_overlay_edd);
408 _config_font_overlay_edd = NULL;
409 }
410
411 if (_config_color_edd)
412 {
413 eet_data_descriptor_free(_config_color_edd);
414 _config_color_edd = NULL;
415 }
416
417 if (_config_color_palette_edd)
418 {
419 eet_data_descriptor_free(_config_color_palette_edd);
420 _config_color_palette_edd = NULL;
421 }
422}
423
424static int
425_sort_files_cb(const void *f1,
426 const void *f2)
427{
428 return strcmp(f1, f2);
429}
430
431const char *
432_elm_config_current_profile_get(void)
433{
434 return _elm_profile;
435}
436
437static size_t
438_elm_data_dir_snprintf(char *dst,
439 size_t size,
440 const char *fmt,
441 ...)
442{
443 size_t data_dir_len, off;
444 va_list ap;
445
446 data_dir_len = eina_strlcpy(dst, _elm_data_dir, size);
447
448 off = data_dir_len + 1;
449 if (off >= size)
450 goto end;
451
452 va_start(ap, fmt);
453 dst[data_dir_len] = '/';
454
455 off = off + vsnprintf(dst + off, size - off, fmt, ap);
456 va_end(ap);
457
458end:
459 return off;
460}
461
462static size_t
463_elm_user_dir_snprintf(char *dst,
464 size_t size,
465 const char *fmt,
466 ...)
467{
468 const char *home;
469 size_t user_dir_len, off;
470 va_list ap;
471
472#ifdef _WIN32
473 home = evil_homedir_get();
474#else
475 home = getenv("HOME");
476#endif
477 if (!home)
478 home = "/";
479
480 user_dir_len = eina_str_join_len(dst, size, '/', home, strlen(home),
481 ELEMENTARY_BASE_DIR, sizeof(ELEMENTARY_BASE_DIR) - 1);
482
483 off = user_dir_len + 1;
484 if (off >= size)
485 goto end;
486
487 va_start(ap, fmt);
488 dst[user_dir_len] = '/';
489
490 off = off + vsnprintf(dst + off, size - off, fmt, ap);
491 va_end(ap);
492
493end:
494 return off;
495}
496
497const char *
498_elm_config_profile_dir_get(const char *prof,
499 Eina_Bool is_user)
500{
501 char buf[PATH_MAX];
502
503 if (!is_user)
504 goto not_user;
505
506 _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s", prof);
507
508 if (ecore_file_is_dir(buf))
509 return strdup(buf);
510
511 return NULL;
512
513not_user:
514 snprintf(buf, sizeof(buf), "%s/config/%s", _elm_data_dir, prof);
515
516 if (ecore_file_is_dir(buf))
517 return strdup(buf);
518
519 return NULL;
520}
521
522Eina_List *
523_elm_config_font_overlays_list(void)
524{
525 return _elm_config->font_overlays;
526}
527
528void
529_elm_config_font_overlay_set(const char *text_class,
530 const char *font,
531 Evas_Font_Size size)
532{
533 Elm_Font_Overlay *efd;
534 Eina_List *l;
535
536 EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
537 {
538 if (strcmp(efd->text_class, text_class))
539 continue;
540
541 if (efd->font) eina_stringshare_del(efd->font);
542 efd->font = eina_stringshare_add(font);
543 efd->size = size;
544 _elm_config->font_overlays =
545 eina_list_promote_list(_elm_config->font_overlays, l);
546 return;
547 }
548
549 /* the text class doesn't exist */
550 efd = calloc(1, sizeof(Elm_Font_Overlay));
551 efd->text_class = eina_stringshare_add(text_class);
552 efd->font = eina_stringshare_add(font);
553 efd->size = size;
554
555 _elm_config->font_overlays = eina_list_prepend(_elm_config->font_overlays,
556 efd);
557}
558
559void
560_elm_config_font_overlay_remove(const char *text_class)
561{
562 Elm_Font_Overlay *efd;
563 Eina_List *l;
564
565 EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
566 {
567 if (strcmp(efd->text_class, text_class))
568 continue;
569
570 _elm_config->font_overlays =
571 eina_list_remove_list(_elm_config->font_overlays, l);
572 if (efd->text_class) eina_stringshare_del(efd->text_class);
573 if (efd->font) eina_stringshare_del(efd->font);
574 free(efd);
575
576 return;
577 }
578}
579
580void
581_elm_config_font_overlay_apply(void)
582{
583 Elm_Font_Overlay *efd;
584 Eina_List *l;
585 int i;
586
587 for (i = 0; _elm_text_classes[i].desc; i++)
588 edje_text_class_del(_elm_text_classes[i].name);
589
590 EINA_LIST_FOREACH(_elm_config->font_overlays, l, efd)
591 edje_text_class_set(efd->text_class, efd->font, efd->size);
592}
593
594Eina_List *
595_elm_config_text_classes_get(void)
596{
597 Eina_List *ret = NULL;
598 int i;
599
600 for (i = 0; _elm_text_classes[i].desc; i++)
601 {
602 Elm_Text_Class *tc;
603 tc = malloc(sizeof(*tc));
604 if (!tc) continue;
605
606 *tc = _elm_text_classes[i];
607
608 ret = eina_list_append(ret, tc);
609 }
610
611 return ret;
612}
613
614void
615_elm_config_text_classes_free(Eina_List *l)
616{
617 Elm_Text_Class *tc;
618
619 EINA_LIST_FREE(l, tc)
620 free(tc);
621}
622
623Eina_List *
624_elm_config_color_list_get(const char *palette_name)
625{
626 Eina_List *plist;
627 Elm_Custom_Palette *cpalette;
628 EINA_LIST_FOREACH(_elm_config->color_palette, plist, cpalette)
629 {
630 if (strcmp(cpalette->palette_name, palette_name))
631 continue;
632 return cpalette->color_list;
633 }
634 return NULL;
635}
636
637void
638_elm_config_color_set(const char *palette_name,
639 int r,
640 int g,
641 int b,
642 int a)
643{
644 Eina_List *plist;
645 Elm_Custom_Palette *cpalette;
646 Elm_Color_RGBA *color;
647 EINA_LIST_FOREACH(_elm_config->color_palette, plist, cpalette)
648 {
649 if (strcmp(cpalette->palette_name, palette_name))
650 continue;
651
652 color = calloc(1, sizeof(Elm_Color_RGBA));
653 color->r = r;
654 color->g = g;
655 color->b = b;
656 color->a = a;
657 cpalette->color_list = eina_list_prepend(cpalette->color_list,
658 color);
659 }
660}
661
662void
663_elm_config_colors_free(const char *palette_name)
664{
665 Eina_List *plist;
666 Elm_Custom_Palette *cpalette;
667 Elm_Color_RGBA *color;
668 EINA_LIST_FOREACH(_elm_config->color_palette, plist, cpalette)
669 {
670 if (strcmp(cpalette->palette_name, palette_name))
671 continue;
672
673 EINA_LIST_FREE(cpalette->color_list, color)
674 {
675 free(color);
676 }
677 }
678}
679
680Eina_List *
681_elm_config_profiles_list(void)
682{
683 Eina_File_Direct_Info *info;
684 Eina_List *flist = NULL;
685 Eina_Iterator *file_it;
686 char buf[PATH_MAX];
687 const char *dir;
688 size_t len;
689
690 len = _elm_user_dir_snprintf(buf, sizeof(buf), "config");
691
692 file_it = eina_file_stat_ls(buf);
693 if (!file_it)
694 goto sys;
695
696 buf[len] = '/';
697 len++;
698
699 len = sizeof(buf) - len;
700
701 EINA_ITERATOR_FOREACH(file_it, info)
702 {
703 if (info->name_length >= len)
704 continue;
705
706 if (info->type == EINA_FILE_DIR)
707 {
708 flist =
709 eina_list_sorted_insert(flist, _sort_files_cb,
710 eina_stringshare_add(info->path +
711 info->name_start));
712 }
713 }
714
715 eina_iterator_free(file_it);
716
717sys:
718 len = eina_str_join_len(buf, sizeof(buf), '/', _elm_data_dir,
719 strlen(_elm_data_dir), "config",
720 sizeof("config") - 1);
721
722 file_it = eina_file_direct_ls(buf);
723 if (!file_it)
724 goto list_free;
725
726 buf[len] = '/';
727 len++;
728
729 len = sizeof(buf) - len;
730 EINA_ITERATOR_FOREACH(file_it, info)
731 {
732 if (info->name_length >= len)
733 continue;
734
735 switch (info->type)
736 {
737 case EINA_FILE_DIR:
738 {
739 const Eina_List *l;
740 const char *tmp;
741
742 EINA_LIST_FOREACH(flist, l, tmp)
743 if (!strcmp(info->path + info->name_start, tmp))
744 break;
745
746 if (!l)
747 flist =
748 eina_list_sorted_insert(flist, _sort_files_cb,
749 eina_stringshare_add(info->path +
750 info->name_start));
751 }
752 break;
753
754 default:
755 continue;
756 }
757 }
758 eina_iterator_free(file_it);
759 return flist;
760
761list_free:
762 EINA_LIST_FREE(flist, dir)
763 eina_stringshare_del(dir);
764
765 return NULL;
766}
767
768static void
769_profile_fetch_from_conf(void)
770{
771 char buf[PATH_MAX], *p, *s;
772 Eet_File *ef = NULL;
773 int len = 0;
774
775 _elm_profile = strdup("default");
776
777 // if env var - use profile without question
778 s = getenv("ELM_PROFILE");
779 if (s)
780 {
781 free(_elm_profile);
782 _elm_profile = strdup(s);
783 return;
784 }
785
786 // user profile
787 _elm_user_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
788 ef = eet_open(buf, EET_FILE_MODE_READ);
789 if (ef)
790 {
791 p = eet_read(ef, "config", &len);
792 if (p)
793 {
794 free(_elm_profile);
795 _elm_profile = malloc(len + 1);
796 memcpy(_elm_profile, p, len);
797 _elm_profile[len] = 0;
798 free(p);
799 }
800 eet_close(ef);
801 if (!p) ef = NULL;
802 }
803 if (ef) return;
804
805 // system profile
806 _elm_data_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
807 ef = eet_open(buf, EET_FILE_MODE_READ);
808 if (ef)
809 {
810 p = eet_read(ef, "config", &len);
811 if (p)
812 {
813 free(_elm_profile);
814 _elm_profile = malloc(len + 1);
815 memcpy(_elm_profile, p, len);
816 _elm_profile[len] = 0;
817 free(p);
818 }
819 eet_close(ef);
820 }
821}
822
823static void
824_config_free(void)
825{
826 Elm_Font_Overlay *fo;
827 const char *fontdir;
828 Elm_Custom_Palette *palette;
829 Elm_Color_RGBA *color;
830
831 if (!_elm_config) return;
832 EINA_LIST_FREE(_elm_config->font_dirs, fontdir)
833 {
834 eina_stringshare_del(fontdir);
835 }
836 if (_elm_config->engine) eina_stringshare_del(_elm_config->engine);
837 EINA_LIST_FREE(_elm_config->font_overlays, fo)
838 {
839 if (fo->text_class) eina_stringshare_del(fo->text_class);
840 if (fo->font) eina_stringshare_del(fo->font);
841 free(fo);
842 }
843 EINA_LIST_FREE(_elm_config->color_palette, palette)
844 {
845 if (palette->palette_name) eina_stringshare_del(palette->palette_name);
846 EINA_LIST_FREE(palette->color_list, color) free(color);
847 free(palette);
848 }
849 if (_elm_config->theme) eina_stringshare_del(_elm_config->theme);
850 if (_elm_config->modules) eina_stringshare_del(_elm_config->modules);
851 free(_elm_config);
852 _elm_config = NULL;
853}
854
855static void
856_config_apply(void)
857{
858 _elm_theme_parse(NULL, _elm_config->theme);
859 ecore_animator_frametime_set(1.0 / _elm_config->fps);
860}
861
862static void
863_config_sub_apply(void)
864{
865 edje_frametime_set(1.0 / _elm_config->fps);
866 edje_scale_set(_elm_config->scale);
867 edje_password_show_last_set(_elm_config->password_show_last);
868 edje_password_show_last_timeout_set(_elm_config->password_show_last_timeout);
869 if (_elm_config->modules) _elm_module_parse(_elm_config->modules);
870}
871
872static Eina_Bool
873_elm_cache_flush_cb(void *data __UNUSED__)
874{
875 elm_cache_all_flush();
876 return ECORE_CALLBACK_RENEW;
877}
878
879/* kind of abusing this call right now -- shared between all of those
880 * properties -- but they are not meant to be called that periodically
881 * anyway */
882void
883_elm_recache(void)
884{
885 Eina_List *l;
886 Evas_Object *win;
887
888 elm_cache_all_flush();
889
890 EINA_LIST_FOREACH(_elm_win_list, l, win)
891 {
892 Evas *e = evas_object_evas_get(win);
893 evas_image_cache_set(e, _elm_config->image_cache * 1024);
894 evas_font_cache_set(e, _elm_config->font_cache * 1024);
895 }
896 edje_file_cache_set(_elm_config->edje_cache);
897 edje_collection_cache_set(_elm_config->edje_collection_cache);
898
899 if (_elm_cache_flush_poller)
900 {
901 ecore_poller_del(_elm_cache_flush_poller);
902 _elm_cache_flush_poller = NULL;
903 }
904 if (_elm_config->cache_flush_enable)
905 {
906 if (_elm_config->cache_flush_poll_interval > 0)
907 {
908 _elm_cache_flush_poller =
909 ecore_poller_add(ECORE_POLLER_CORE,
910 _elm_config->cache_flush_poll_interval,
911 _elm_cache_flush_cb, NULL);
912 }
913 }
914}
915
916static Elm_Config *
917_config_user_load(void)
918{
919 Elm_Config *cfg = NULL;
920 Eet_File *ef;
921 char buf[PATH_MAX];
922
923 _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s/base.cfg",
924 _elm_profile);
925
926 ef = eet_open(buf, EET_FILE_MODE_READ);
927 if (ef)
928 {
929 cfg = eet_data_read(ef, _config_edd, "config");
930 eet_close(ef);
931 }
932 return cfg;
933}
934
935static Elm_Config *
936_config_system_load(void)
937{
938 Elm_Config *cfg = NULL;
939 Eet_File *ef;
940 char buf[PATH_MAX];
941
942 _elm_data_dir_snprintf(buf, sizeof(buf), "config/%s/base.cfg",
943 _elm_profile);
944
945 ef = eet_open(buf, EET_FILE_MODE_READ);
946 if (ef)
947 {
948 cfg = eet_data_read(ef, _config_edd, "config");
949 eet_close(ef);
950 }
951 return cfg;
952}
953
954static void
955_config_load(void)
956{
957 _elm_config = _config_user_load();
958 if (_elm_config)
959 {
960 if (_elm_config->config_version < ELM_CONFIG_VERSION)
961 _config_update();
962 return;
963 }
964
965 /* no user config, fallback for system. No need to check version for
966 * this one, if it's not the right one, someone screwed up at the time
967 * of installing it */
968 _elm_config = _config_system_load();
969 if (_elm_config) return;
970 /* FIXME: config load could have failed because of a non-existent
971 * profile. Fallback to default before moving on */
972
973 // config load fail - defaults
974 // why are these here? well if they are, it means you can make a gui
975 // config recovery app i guess...
976 _elm_config = ELM_NEW(Elm_Config);
977 _elm_config->config_version = ELM_CONFIG_VERSION;
978 _elm_config->engine = eina_stringshare_add("software_x11");
979 _elm_config->vsync = 0;
980 _elm_config->thumbscroll_enable = EINA_TRUE;
981 _elm_config->thumbscroll_threshold = 24;
982 _elm_config->thumbscroll_momentum_threshold = 100.0;
983 _elm_config->thumbscroll_friction = 1.0;
984 _elm_config->thumbscroll_bounce_friction = 0.5;
985 _elm_config->thumbscroll_bounce_enable = EINA_TRUE;
986 _elm_config->page_scroll_friction = 0.5;
987 _elm_config->bring_in_scroll_friction = 0.5;
988 _elm_config->zoom_friction = 0.5;
989 _elm_config->thumbscroll_border_friction = 0.5;
990 _elm_config->thumbscroll_sensitivity_friction = 0.25; // magic number! just trial and error shows this makes it behave "nicer" and not run off at high speed all the time
991 _elm_config->scroll_smooth_amount = 1.0;
992 _elm_config->scroll_smooth_history_weight = 0.3;
993 _elm_config->scroll_smooth_future_time = 0.0;
994 _elm_config->scroll_smooth_time_window = 0.2;
995 _elm_config->scale = 1.0;
996 _elm_config->bgpixmap = 0;
997 _elm_config->compositing = 1;
998 _elm_config->font_hinting = 2;
999 _elm_config->cache_flush_poll_interval = 512;
1000 _elm_config->cache_flush_enable = EINA_TRUE;
1001 _elm_config->font_dirs = NULL;
1002 _elm_config->image_cache = 4096;
1003 _elm_config->font_cache = 512;
1004 _elm_config->edje_cache = 32;
1005 _elm_config->edje_collection_cache = 64;
1006 _elm_config->finger_size = 40;
1007 _elm_config->fps = 60.0;
1008 _elm_config->theme = eina_stringshare_add("default");
1009 _elm_config->modules = NULL;
1010 _elm_config->tooltip_delay = 1.0;
1011 _elm_config->cursor_engine_only = EINA_TRUE;
1012 _elm_config->focus_highlight_enable = EINA_FALSE;
1013 _elm_config->focus_highlight_animate = EINA_TRUE;
1014 _elm_config->toolbar_shrink_mode = 2;
1015 _elm_config->fileselector_expand_enable = EINA_FALSE;
1016 _elm_config->inwin_dialogs_enable = EINA_FALSE;
1017 _elm_config->icon_size = 32;
1018 _elm_config->longpress_timeout = 1.0;
1019 _elm_config->effect_enable = EINA_TRUE;
1020 _elm_config->desktop_entry = EINA_FALSE;
1021 _elm_config->is_mirrored = EINA_FALSE; /* Read sys value in env_get() */
1022 _elm_config->password_show_last = EINA_FALSE;
1023 _elm_config->password_show_last_timeout = 2.0;
1024 _elm_config->glayer_zoom_finger_enable = EINA_TRUE;
1025 _elm_config->glayer_zoom_finger_factor = 1.0;
1026 _elm_config->glayer_zoom_wheel_factor = 0.05;
1027 _elm_config->glayer_zoom_distance_tolerance = 1.0; /* 1 times elm_finger_size_get() */
1028 _elm_config->glayer_rotate_finger_enable = EINA_TRUE;
1029 _elm_config->glayer_rotate_angular_tolerance = 2.0; /* 2 DEG */
1030 _elm_config->glayer_line_min_length = 1.0; /* 1 times elm_finger_size_get() */
1031 _elm_config->glayer_line_distance_tolerance = 3.0; /* 3 times elm_finger_size_get() */
1032 _elm_config->glayer_line_angular_tolerance = 20.0; /* 20 DEG */
1033 _elm_config->glayer_flick_time_limit_ms = 120; /* ms to finish flick */
1034 _elm_config->glayer_long_tap_start_timeout = 1.2; /* 1.2 second to start long-tap */
1035 _elm_config->glayer_continues_enable = EINA_TRUE; /* Continue gestures default */
1036 _elm_config->week_start = 1; /* monday */
1037 _elm_config->weekend_start = 6; /* saturday */
1038 _elm_config->weekend_len = 2;
1039 _elm_config->year_min = 2;
1040 _elm_config->year_max = 137;
1041 _elm_config->color_palette = NULL;
1042}
1043
1044static const char *
1045_elm_config_eet_close_error_get(Eet_File *ef,
1046 char *file)
1047{
1048 Eet_Error err;
1049 const char *erstr = NULL;
1050
1051 err = eet_close(ef);
1052 switch (err)
1053 {
1054 case EET_ERROR_WRITE_ERROR:
1055 erstr = "An error occurred while saving Elementary's "
1056 "settings to disk. The error could not be "
1057 "deterimined. The file where the error occurred was: "
1058 "%s. This file has been deleted to avoid corrupt data.";
1059 break;
1060
1061 case EET_ERROR_WRITE_ERROR_FILE_TOO_BIG:
1062 erstr = "Elementary's settings files are too big "
1063 "for the file system they are being saved to. "
1064 "This error is very strange as the files should "
1065 "be extremely small. Please check the settings "
1066 "for your home directory. "
1067 "The file where the error occurred was: %s ."
1068 "This file has been deleted to avoid corrupt data.";
1069 break;
1070
1071 case EET_ERROR_WRITE_ERROR_IO_ERROR:
1072 erstr = "An output error occurred when writing the settings "
1073 "files for Elementary. Your disk is having troubles "
1074 "and possibly needs replacement. "
1075 "The file where the error occurred was: %s ."
1076 "This file has been deleted to avoid corrupt data.";
1077 break;
1078
1079 case EET_ERROR_WRITE_ERROR_OUT_OF_SPACE:
1080 erstr = "Elementary cannot write its settings file "
1081 "because it ran out of space to write the file. "
1082 "You have either run out of disk space or have "
1083 "gone over your quota limit. "
1084 "The file where the error occurred was: %s ."
1085 "This file has been deleted to avoid corrupt data.";
1086 break;
1087
1088 case EET_ERROR_WRITE_ERROR_FILE_CLOSED:
1089 erstr = "Elementary unexpectedly had the settings file "
1090 "it was writing closed on it. This is very unusual. "
1091 "The file where the error occurred was: %s "
1092 "This file has been deleted to avoid corrupt data.";
1093 break;
1094
1095 default:
1096 break;
1097 }
1098 if (erstr)
1099 {
1100 /* delete any partially-written file */
1101 ecore_file_unlink(file);
1102 return strdup(erstr);
1103 }
1104
1105 return NULL;
1106}
1107
1108static Eina_Bool
1109_elm_config_profile_save(void)
1110{
1111 char buf[4096], buf2[4096];
1112 int ok = 0, ret;
1113 const char *err;
1114 Eet_File *ef;
1115 size_t len;
1116
1117 len = _elm_user_dir_snprintf(buf, sizeof(buf), "config/profile.cfg");
1118 if (len + 1 >= sizeof(buf))
1119 return EINA_FALSE;
1120
1121 len = _elm_user_dir_snprintf(buf2, sizeof(buf2), "config/profile.cfg.tmp");
1122 if (len + 1 >= sizeof(buf2))
1123 return EINA_FALSE;
1124
1125 ef = eet_open(buf2, EET_FILE_MODE_WRITE);
1126 if (!ef)
1127 return EINA_FALSE;
1128
1129 ok = eet_write(ef, "config", _elm_profile, strlen(_elm_profile), 0);
1130 if (!ok)
1131 goto err;
1132
1133 err = _elm_config_eet_close_error_get(ef, buf2);
1134 if (err)
1135 {
1136 ERR("%s", err);
1137 free((void *)err);
1138 goto err;
1139 }
1140
1141 ret = ecore_file_mv(buf2, buf);
1142 if (!ret)
1143 {
1144 ERR("Error saving Elementary's configuration file");
1145 goto err;
1146 }
1147
1148 ecore_file_unlink(buf2);
1149 return EINA_TRUE;
1150
1151err:
1152 ecore_file_unlink(buf2);
1153 return EINA_FALSE;
1154}
1155
1156Eina_Bool
1157_elm_config_save(void)
1158{
1159 char buf[4096], buf2[4096];
1160 int ok = 0, ret;
1161 const char *err;
1162 Eet_File *ef;
1163 size_t len;
1164
1165 len = _elm_user_dir_snprintf(buf, sizeof(buf), "config/%s", _elm_profile);
1166 if (len + 1 >= sizeof(buf))
1167 return EINA_FALSE;
1168
1169 ok = ecore_file_mkpath(buf);
1170 if (!ok)
1171 {
1172 ERR("Problem accessing Elementary's user configuration directory: %s",
1173 buf);
1174 return EINA_FALSE;
1175 }
1176
1177 if (!_elm_config_profile_save())
1178 return EINA_FALSE;
1179
1180 buf[len] = '/';
1181 len++;
1182
1183 if (len + sizeof("base.cfg") >= sizeof(buf) - len)
1184 return EINA_FALSE;
1185
1186 memcpy(buf + len, "base.cfg", sizeof("base.cfg"));
1187 len += sizeof("base.cfg") - 1;
1188
1189 if (len + sizeof(".tmp") >= sizeof(buf))
1190 return EINA_FALSE;
1191
1192 memcpy(buf2, buf, len);
1193 memcpy(buf2 + len, ".tmp", sizeof(".tmp"));
1194
1195 ef = eet_open(buf2, EET_FILE_MODE_WRITE);
1196 if (!ef)
1197 return EINA_FALSE;
1198
1199 ok = eet_data_write(ef, _config_edd, "config", _elm_config, 1);
1200 if (!ok)
1201 goto err;
1202
1203 err = _elm_config_eet_close_error_get(ef, buf2);
1204 if (err)
1205 {
1206 ERR("%s", err);
1207 free((void *)err);
1208 goto err;
1209 }
1210
1211 ret = ecore_file_mv(buf2, buf);
1212 if (!ret)
1213 {
1214 ERR("Error saving Elementary's configuration file");
1215 goto err;
1216 }
1217
1218 ecore_file_unlink(buf2);
1219 return EINA_TRUE;
1220
1221err:
1222 ecore_file_unlink(buf2);
1223 return EINA_FALSE;
1224}
1225
1226static void
1227_config_update(void)
1228{
1229 Elm_Config *tcfg;
1230
1231 tcfg = _config_system_load();
1232 if (!tcfg)
1233 {
1234 /* weird profile or something? We should probably fill
1235 * with hardcoded defaults, or get from default previx */
1236 return;
1237 }
1238#define IFCFG(v) if ((_elm_config->config_version & 0xffff) < (v)) {
1239#define IFCFGELSE } else {
1240#define IFCFGEND }
1241#define COPYVAL(x) do {_elm_config->x = tcfg->x; } while (0)
1242#define COPYPTR(x) do {_elm_config->x = tcfg->x; tcfg->x = NULL; } while (0)
1243#define COPYSTR(x) COPYPTR(x)
1244
1245 /* we also need to update for property changes in the root window
1246 * if needed, but that will be dependent on new properties added
1247 * with each version */
1248
1249 IFCFG(0x0003);
1250 COPYVAL(longpress_timeout);
1251 IFCFGEND;
1252
1253#undef COPYSTR
1254#undef COPYPTR
1255#undef COPYVAL
1256#undef IFCFGEND
1257#undef IFCFGELSE
1258#undef IFCFG
1259
1260 /* after updating user config, we must save */
1261}
1262
1263static void
1264_env_get(void)
1265{
1266 char *s;
1267 double friction;
1268
1269 s = getenv("ELM_ENGINE");
1270 if (s)
1271 {
1272 if ((!strcasecmp(s, "x11")) ||
1273 (!strcasecmp(s, "x")) ||
1274 (!strcasecmp(s, "software-x11")) ||
1275 (!strcasecmp(s, "software_x11")))
1276 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_X11);
1277 else if ((!strcasecmp(s, "opengl")) ||
1278 (!strcasecmp(s, "gl")) ||
1279 (!strcasecmp(s, "opengl-x11")) ||
1280 (!strcasecmp(s, "opengl_x11")))
1281 eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_X11);
1282 else if ((!strcasecmp(s, "x11-8")) ||
1283 (!strcasecmp(s, "x8")) ||
1284 (!strcasecmp(s, "software-8-x11")) ||
1285 (!strcasecmp(s, "software_8_x11")))
1286 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_8_X11);
1287 else if ((!strcasecmp(s, "x11-16")) ||
1288 (!strcasecmp(s, "x16")) ||
1289 (!strcasecmp(s, "software-16-x11")) ||
1290 (!strcasecmp(s, "software_16_x11")))
1291 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_X11);
1292/*
1293 else if ((!strcasecmp(s, "xrender")) ||
1294 (!strcasecmp(s, "xr")) ||
1295 (!strcasecmp(s, "xrender-x11")) ||
1296 (!strcasecmp(s, "xrender_x11")))
1297 eina_stringshare_replace(&_elm_config->engine, ELM_XRENDER_X11);
1298 */
1299 else if ((!strcasecmp(s, "fb")) ||
1300 (!strcasecmp(s, "software-fb")) ||
1301 (!strcasecmp(s, "software_fb")))
1302 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_FB);
1303 else if ((!strcasecmp(s, "directfb")) ||
1304 (!strcasecmp(s, "dfb")))
1305 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_DIRECTFB);
1306 else if ((!strcasecmp(s, "psl1ght")))
1307 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_PSL1GHT);
1308 else if ((!strcasecmp(s, "sdl")) ||
1309 (!strcasecmp(s, "software-sdl")) ||
1310 (!strcasecmp(s, "software_sdl")))
1311 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_SDL);
1312 else if ((!strcasecmp(s, "sdl-16")) ||
1313 (!strcasecmp(s, "software-16-sdl")) ||
1314 (!strcasecmp(s, "software_16_sdl")))
1315 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_SDL);
1316 else if ((!strcasecmp(s, "opengl-sdl")) ||
1317 (!strcasecmp(s, "opengl_sdl")) ||
1318 (!strcasecmp(s, "gl-sdl")) ||
1319 (!strcasecmp(s, "gl_sdl")))
1320 eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_SDL);
1321 else if ((!strcasecmp(s, "opengl-cocoa")) ||
1322 (!strcasecmp(s, "opengl_cocoa")) ||
1323 (!strcasecmp(s, "gl-cocoa")) ||
1324 (!strcasecmp(s, "gl_cocoa")))
1325 eina_stringshare_replace(&_elm_config->engine, ELM_OPENGL_COCOA);
1326 else if ((!strcasecmp(s, "gdi")) ||
1327 (!strcasecmp(s, "software-gdi")) ||
1328 (!strcasecmp(s, "software_gdi")))
1329 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_WIN32);
1330 else if ((!strcasecmp(s, "wince-gdi")) ||
1331 (!strcasecmp(s, "software-16-wince-gdi")) ||
1332 (!strcasecmp(s, "software_16_wince_gdi")))
1333 eina_stringshare_replace(&_elm_config->engine, ELM_SOFTWARE_16_WINCE);
1334 else if (!strcasecmp(s, "buffer"))
1335 eina_stringshare_replace(&_elm_config->engine, ELM_BUFFER);
1336 else if ((!strncmp(s, "shot:", 5)))
1337 eina_stringshare_replace(&_elm_config->engine, s);
1338 else if ((!strcasecmp(s, "ews")))
1339 eina_stringshare_replace(&_elm_config->engine, ELM_EWS);
1340 else if ((!strcasecmp(s, "wayland_shm")))
1341 eina_stringshare_replace(&_elm_config->engine, ELM_WAYLAND_SHM);
1342 else if ((!strcasecmp(s, "wayland_egl")))
1343 eina_stringshare_replace(&_elm_config->engine, ELM_WAYLAND_EGL);
1344 else
1345 ERR("Unknown engine '%s'.", s);
1346 }
1347
1348 s = getenv("ELM_VSYNC");
1349 if (s) _elm_config->vsync = !!atoi(s);
1350
1351 s = getenv("ELM_THUMBSCROLL_ENABLE");
1352 if (s) _elm_config->thumbscroll_enable = !!atoi(s);
1353 s = getenv("ELM_THUMBSCROLL_THRESHOLD");
1354 if (s) _elm_config->thumbscroll_threshold = atoi(s);
1355 // FIXME: floatformat locale issues here 1.0 vs 1,0 - should just be 1.0
1356 s = getenv("ELM_THUMBSCROLL_MOMENTUM_THRESHOLD");
1357 if (s) _elm_config->thumbscroll_momentum_threshold = atof(s);
1358 s = getenv("ELM_THUMBSCROLL_FRICTION");
1359 if (s) _elm_config->thumbscroll_friction = atof(s);
1360 s = getenv("ELM_THUMBSCROLL_BOUNCE_ENABLE");
1361 if (s) _elm_config->thumbscroll_bounce_enable = !!atoi(s);
1362 s = getenv("ELM_THUMBSCROLL_BOUNCE_FRICTION");
1363 if (s) _elm_config->thumbscroll_bounce_friction = atof(s);
1364 s = getenv("ELM_PAGE_SCROLL_FRICTION");
1365 if (s) _elm_config->page_scroll_friction = atof(s);
1366 s = getenv("ELM_BRING_IN_SCROLL_FRICTION");
1367 if (s) _elm_config->bring_in_scroll_friction = atof(s);
1368 s = getenv("ELM_ZOOM_FRICTION");
1369 if (s) _elm_config->zoom_friction = atof(s);
1370 s = getenv("ELM_THUMBSCROLL_BORDER_FRICTION");
1371 if (s)
1372 {
1373 friction = atof(s);
1374 if (friction < 0.0)
1375 friction = 0.0;
1376
1377 if (friction > 1.0)
1378 friction = 1.0;
1379
1380 _elm_config->thumbscroll_border_friction = friction;
1381 }
1382 s = getenv("ELM_THUMBSCROLL_SENSITIVITY_FRICTION");
1383 if (s)
1384 {
1385 friction = atof(s);
1386 if (friction < 0.1)
1387 friction = 0.1;
1388
1389 if (friction > 1.0)
1390 friction = 1.0;
1391
1392 _elm_config->thumbscroll_sensitivity_friction = friction;
1393 }
1394 s = getenv("ELM_SCROLL_SMOOTH_AMOUNT");
1395 if (s) _elm_config->scroll_smooth_amount = atof(s);
1396 s = getenv("ELM_SCROLL_SMOOTH_HISTORY_WEIGHT");
1397 if (s) _elm_config->scroll_smooth_history_weight = atof(s);
1398 s = getenv("ELM_SCROLL_SMOOTH_FUTURE_TIME");
1399 if (s) _elm_config->scroll_smooth_future_time = atof(s);
1400 s = getenv("ELM_SCROLL_SMOOTH_TIME_WINDOW");
1401 if (s) _elm_config->scroll_smooth_time_window = atof(s);
1402 s = getenv("ELM_THEME");
1403 if (s) eina_stringshare_replace(&_elm_config->theme, s);
1404
1405 s = getenv("ELM_FONT_HINTING");
1406 if (s)
1407 {
1408 if (!strcasecmp(s, "none")) _elm_config->font_hinting = 0;
1409 else if (!strcasecmp(s, "auto"))
1410 _elm_config->font_hinting = 1;
1411 else if (!strcasecmp(s, "bytecode"))
1412 _elm_config->font_hinting = 2;
1413 }
1414
1415 s = getenv("ELM_FONT_PATH");
1416 if (s)
1417 {
1418 const char *p, *pp;
1419 char *buf2;
1420
1421 EINA_LIST_FREE(_elm_config->font_dirs, p)
1422 {
1423 eina_stringshare_del(p);
1424 }
1425
1426 buf2 = alloca(strlen(s) + 1);
1427 p = s;
1428 pp = p;
1429 for (;; )
1430 {
1431 if ((*p == ':') || (*p == 0))
1432 {
1433 int len;
1434
1435 len = p - pp;
1436 strncpy(buf2, pp, len);
1437 buf2[len] = 0;
1438 _elm_config->font_dirs =
1439 eina_list_append(_elm_config->font_dirs,
1440 eina_stringshare_add(buf2));
1441 if (*p == 0) break;
1442 p++;
1443 pp = p;
1444 }
1445 else
1446 {
1447 if (*p == 0) break;
1448 p++;
1449 }
1450 }
1451 }
1452
1453 s = getenv("ELM_IMAGE_CACHE");
1454 if (s) _elm_config->image_cache = atoi(s);
1455
1456 s = getenv("ELM_FONT_CACHE");
1457 if (s) _elm_config->font_cache = atoi(s);
1458
1459 s = getenv("ELM_SCALE");
1460 if (s) _elm_config->scale = atof(s);
1461
1462 s = getenv("ELM_FINGER_SIZE");
1463 if (s) _elm_config->finger_size = atoi(s);
1464
1465 s = getenv("ELM_PASSWORD_SHOW_LAST");
1466 if (s) _elm_config->password_show_last = !!atoi(s);
1467
1468 s = getenv("ELM_PASSWORD_SHOW_LAST_TIMEOUT");
1469 if (s)
1470 {
1471 double pw_show_last_timeout = atof(s);
1472 if (pw_show_last_timeout >= 0.0)
1473 _elm_config->password_show_last_timeout = pw_show_last_timeout;
1474 }
1475
1476 s = getenv("ELM_FPS");
1477 if (s) _elm_config->fps = atof(s);
1478 if (_elm_config->fps < 1.0) _elm_config->fps = 1.0;
1479
1480 s = getenv("ELM_MODULES");
1481 if (s) eina_stringshare_replace(&_elm_config->modules, s);
1482
1483 /* Get RTL orientation from system */
1484 setlocale(LC_ALL, "");
1485 bindtextdomain(PACKAGE, LOCALE_DIR);
1486 _elm_config->is_mirrored = !strcmp(E_("default:LTR"), "default:RTL");
1487
1488 s = getenv("ELM_TOOLTIP_DELAY");
1489 if (s)
1490 {
1491 double delay = atof(s);
1492 if (delay >= 0.0)
1493 _elm_config->tooltip_delay = delay;
1494 }
1495
1496 s = getenv("ELM_CURSOR_ENGINE_ONLY");
1497 if (s) _elm_config->cursor_engine_only = !!atoi(s);
1498
1499 s = getenv("ELM_FOCUS_HIGHLIGHT_ENABLE");
1500 if (s) _elm_config->focus_highlight_enable = !!atoi(s);
1501
1502 s = getenv("ELM_FOCUS_HIGHLIGHT_ANIMATE");
1503 if (s) _elm_config->focus_highlight_animate = !!atoi(s);
1504
1505 s = getenv("ELM_TOOLBAR_SHRINK_MODE");
1506 if (s) _elm_config->toolbar_shrink_mode = atoi(s);
1507
1508 s = getenv("ELM_FILESELECTOR_EXPAND_ENABLE");
1509 if (s) _elm_config->fileselector_expand_enable = !!atoi(s);
1510
1511 s = getenv("ELM_INWIN_DIALOGS_ENABLE");
1512 if (s) _elm_config->inwin_dialogs_enable = !!atoi(s);
1513
1514 s = getenv("ELM_ICON_SIZE");
1515 if (s) _elm_config->icon_size = atoi(s);
1516
1517 s = getenv("ELM_LONGPRESS_TIMEOUT");
1518 if (s) _elm_config->longpress_timeout = atof(s);
1519 if (_elm_config->longpress_timeout < 0.0)
1520 _elm_config->longpress_timeout = 0.0;
1521
1522 s = getenv("ELM_EFFECT_ENABLE");
1523 if (s) _elm_config->effect_enable = !!atoi(s);
1524
1525 s = getenv("ELM_DESKTOP_ENTRY");
1526 if (s) _elm_config->desktop_entry = !!atoi(s);
1527 s = getenv("ELM_ACCESS_MODE");
1528 if (s) _elm_config->access_mode = ELM_ACCESS_MODE_ON;
1529}
1530
1531EAPI Eina_Bool
1532elm_config_mirrored_get(void)
1533{
1534 return _elm_config->is_mirrored;
1535}
1536
1537EAPI void
1538elm_config_mirrored_set(Eina_Bool mirrored)
1539{
1540 _elm_config->is_mirrored = mirrored;
1541 _elm_rescale();
1542}
1543
1544EAPI Eina_Bool
1545elm_config_cursor_engine_only_get(void)
1546{
1547 return _elm_config->cursor_engine_only;
1548}
1549
1550EAPI void
1551elm_config_cursor_engine_only_set(Eina_Bool engine_only)
1552{
1553 engine_only = !!engine_only;
1554 _elm_config->cursor_engine_only = engine_only;
1555}
1556
1557EAPI double
1558elm_config_tooltip_delay_get(void)
1559{
1560 return _elm_config->tooltip_delay;
1561}
1562
1563EAPI void
1564elm_config_tooltip_delay_set(double delay)
1565{
1566 if (delay < 0.0) return;
1567 _elm_config->tooltip_delay = delay;
1568}
1569
1570EAPI double
1571elm_config_scale_get(void)
1572{
1573 return _elm_config->scale;
1574}
1575
1576EAPI void
1577elm_config_scale_set(double scale)
1578{
1579 if (_elm_config->scale == scale) return;
1580 _elm_config->scale = scale;
1581 _elm_rescale();
1582}
1583
1584EAPI Eina_Bool
1585elm_config_password_show_last_get(void)
1586{
1587 return _elm_config->password_show_last;
1588}
1589
1590EAPI void
1591elm_config_password_show_last_set(Eina_Bool password_show_last)
1592{
1593 if (_elm_config->password_show_last == password_show_last) return;
1594 _elm_config->password_show_last = password_show_last;
1595 edje_password_show_last_set(_elm_config->password_show_last);
1596}
1597
1598EAPI double
1599elm_config_password_show_last_timeout_get(void)
1600{
1601 return _elm_config->password_show_last_timeout;
1602}
1603
1604EAPI void
1605elm_config_password_show_last_timeout_set(double password_show_last_timeout)
1606{
1607 if (_elm_config->password_show_last_timeout == password_show_last_timeout) return;
1608 _elm_config->password_show_last_timeout = password_show_last_timeout;
1609 edje_password_show_last_timeout_set(_elm_config->password_show_last_timeout);
1610}
1611
1612EAPI Eina_Bool
1613elm_config_save(void)
1614{
1615 return _elm_config_save();
1616}
1617
1618EAPI void
1619elm_config_reload(void)
1620{
1621 _elm_config_reload();
1622}
1623
1624EAPI const char *
1625elm_config_profile_get(void)
1626{
1627 return _elm_config_current_profile_get();
1628}
1629
1630EAPI const char *
1631elm_config_profile_dir_get(const char *profile,
1632 Eina_Bool is_user)
1633{
1634 return _elm_config_profile_dir_get(profile, is_user);
1635}
1636
1637EAPI void
1638elm_config_profile_dir_free(const char *p_dir)
1639{
1640 free((void *)p_dir);
1641}
1642
1643EAPI Eina_List *
1644elm_config_profile_list_get(void)
1645{
1646 return _elm_config_profiles_list();
1647}
1648
1649EAPI void
1650elm_config_profile_list_free(Eina_List *l)
1651{
1652 const char *dir;
1653
1654 EINA_LIST_FREE(l, dir)
1655 eina_stringshare_del(dir);
1656}
1657
1658EAPI void
1659elm_config_profile_set(const char *profile)
1660{
1661 EINA_SAFETY_ON_NULL_RETURN(profile);
1662 _elm_config_profile_set(profile);
1663}
1664
1665EAPI const char *
1666elm_config_engine_get(void)
1667{
1668 return _elm_config->engine;
1669}
1670
1671EAPI void
1672elm_config_engine_set(const char *engine)
1673{
1674 EINA_SAFETY_ON_NULL_RETURN(engine);
1675
1676 _elm_config_engine_set(engine);
1677}
1678
1679EAPI Eina_List *
1680elm_config_text_classes_list_get(void)
1681{
1682 return _elm_config_text_classes_get();
1683}
1684
1685EAPI void
1686elm_config_text_classes_list_free(Eina_List *list)
1687{
1688 _elm_config_text_classes_free(list);
1689}
1690
1691EAPI const Eina_List *
1692elm_config_font_overlay_list_get(void)
1693{
1694 return _elm_config_font_overlays_list();
1695}
1696
1697EAPI void
1698elm_config_font_overlay_set(const char *text_class,
1699 const char *font,
1700 Evas_Font_Size size)
1701{
1702 EINA_SAFETY_ON_NULL_RETURN(text_class);
1703 _elm_config_font_overlay_set(text_class, font, size);
1704}
1705
1706EAPI void
1707elm_config_font_overlay_unset(const char *text_class)
1708{
1709 EINA_SAFETY_ON_NULL_RETURN(text_class);
1710 _elm_config_font_overlay_remove(text_class);
1711}
1712
1713EAPI void
1714elm_config_font_overlay_apply(void)
1715{
1716 _elm_config_font_overlay_apply();
1717}
1718
1719EAPI Evas_Coord
1720elm_config_finger_size_get(void)
1721{
1722 return _elm_config->finger_size;
1723}
1724
1725EAPI void
1726elm_config_finger_size_set(Evas_Coord size)
1727{
1728 if (_elm_config->finger_size == size) return;
1729 _elm_config->finger_size = size;
1730 _elm_rescale();
1731}
1732
1733EAPI int
1734elm_config_cache_flush_interval_get(void)
1735{
1736 return _elm_config->cache_flush_poll_interval;
1737}
1738
1739EAPI void
1740elm_config_cache_flush_interval_set(int size)
1741{
1742 if (_elm_config->cache_flush_poll_interval == size) return;
1743 _elm_config->cache_flush_poll_interval = size;
1744
1745 _elm_recache();
1746}
1747
1748EAPI Eina_Bool
1749elm_config_cache_flush_enabled_get(void)
1750{
1751 return _elm_config->cache_flush_enable;
1752}
1753
1754EAPI void
1755elm_config_cache_flush_enabled_set(Eina_Bool enabled)
1756{
1757 enabled = !!enabled;
1758 if (_elm_config->cache_flush_enable == enabled) return;
1759 _elm_config->cache_flush_enable = enabled;
1760
1761 _elm_recache();
1762}
1763
1764EAPI int
1765elm_config_cache_font_cache_size_get(void)
1766{
1767 return _elm_config->font_cache;
1768}
1769
1770EAPI void
1771elm_config_cache_font_cache_size_set(int size)
1772{
1773 if (_elm_config->font_cache == size) return;
1774 _elm_config->font_cache = size;
1775
1776 _elm_recache();
1777}
1778
1779EAPI int
1780elm_config_cache_image_cache_size_get(void)
1781{
1782 return _elm_config->image_cache;
1783}
1784
1785EAPI void
1786elm_config_cache_image_cache_size_set(int size)
1787{
1788 if (_elm_config->image_cache == size) return;
1789 _elm_config->image_cache = size;
1790
1791 _elm_recache();
1792}
1793
1794EAPI int
1795elm_config_cache_edje_file_cache_size_get()
1796{
1797 return _elm_config->edje_cache;
1798}
1799
1800EAPI void
1801elm_config_cache_edje_file_cache_size_set(int size)
1802{
1803 if (_elm_config->edje_cache == size) return;
1804 _elm_config->edje_cache = size;
1805
1806 _elm_recache();
1807}
1808
1809EAPI int
1810elm_config_cache_edje_collection_cache_size_get(void)
1811{
1812 return _elm_config->edje_collection_cache;
1813}
1814
1815EAPI void
1816elm_config_cache_edje_collection_cache_size_set(int size)
1817{
1818 if (_elm_config->edje_collection_cache == size) return;
1819 _elm_config->edje_collection_cache = size;
1820
1821 _elm_recache();
1822}
1823
1824EAPI Eina_Bool
1825elm_config_focus_highlight_enabled_get(void)
1826{
1827 return _elm_config->focus_highlight_enable;
1828}
1829
1830EAPI void
1831elm_config_focus_highlight_enabled_set(Eina_Bool enable)
1832{
1833 _elm_config->focus_highlight_enable = !!enable;
1834}
1835
1836EAPI Eina_Bool
1837elm_config_focus_highlight_animate_get(void)
1838{
1839 return _elm_config->focus_highlight_animate;
1840}
1841
1842EAPI void
1843elm_config_focus_highlight_animate_set(Eina_Bool animate)
1844{
1845 _elm_config->focus_highlight_animate = !!animate;
1846}
1847
1848EAPI Eina_Bool
1849elm_config_scroll_bounce_enabled_get(void)
1850{
1851 return _elm_config->thumbscroll_bounce_enable;
1852}
1853
1854EAPI void
1855elm_config_scroll_bounce_enabled_set(Eina_Bool enabled)
1856{
1857 _elm_config->thumbscroll_bounce_enable = enabled;
1858}
1859
1860EAPI double
1861elm_config_scroll_bounce_friction_get(void)
1862{
1863 return _elm_config->thumbscroll_bounce_friction;
1864}
1865
1866EAPI void
1867elm_config_scroll_bounce_friction_set(double friction)
1868{
1869 _elm_config->thumbscroll_bounce_friction = friction;
1870}
1871
1872EAPI double
1873elm_config_scroll_page_scroll_friction_get(void)
1874{
1875 return _elm_config->page_scroll_friction;
1876}
1877
1878EAPI void
1879elm_config_scroll_page_scroll_friction_set(double friction)
1880{
1881 _elm_config->page_scroll_friction = friction;
1882}
1883
1884EAPI double
1885elm_config_scroll_bring_in_scroll_friction_get(void)
1886{
1887 return _elm_config->bring_in_scroll_friction;
1888}
1889
1890EAPI void
1891elm_config_scroll_bring_in_scroll_friction_set(double friction)
1892{
1893 _elm_config->bring_in_scroll_friction = friction;
1894}
1895
1896EAPI double
1897elm_config_scroll_zoom_friction_get(void)
1898{
1899 return _elm_config->zoom_friction;
1900}
1901
1902EAPI void
1903elm_config_scroll_zoom_friction_set(double friction)
1904{
1905 _elm_config->zoom_friction = friction;
1906}
1907
1908EAPI Eina_Bool
1909elm_config_scroll_thumbscroll_enabled_get(void)
1910{
1911 return _elm_config->thumbscroll_enable;
1912}
1913
1914EAPI void
1915elm_config_scroll_thumbscroll_enabled_set(Eina_Bool enabled)
1916{
1917 _elm_config->thumbscroll_enable = enabled;
1918}
1919
1920EAPI unsigned int
1921elm_config_scroll_thumbscroll_threshold_get(void)
1922{
1923 return _elm_config->thumbscroll_threshold;
1924}
1925
1926EAPI void
1927elm_config_scroll_thumbscroll_threshold_set(unsigned int threshold)
1928{
1929 _elm_config->thumbscroll_threshold = threshold;
1930}
1931
1932EAPI double
1933elm_config_scroll_thumbscroll_momentum_threshold_get(void)
1934{
1935 return _elm_config->thumbscroll_momentum_threshold;
1936}
1937
1938EAPI void
1939elm_config_scroll_thumbscroll_momentum_threshold_set(double threshold)
1940{
1941 _elm_config->thumbscroll_momentum_threshold = threshold;
1942}
1943
1944EAPI double
1945elm_config_scroll_thumbscroll_friction_get(void)
1946{
1947 return _elm_config->thumbscroll_friction;
1948}
1949
1950EAPI void
1951elm_config_scroll_thumbscroll_friction_set(double friction)
1952{
1953 _elm_config->thumbscroll_friction = friction;
1954}
1955
1956EAPI double
1957elm_config_scroll_thumbscroll_border_friction_get(void)
1958{
1959 return _elm_config->thumbscroll_border_friction;
1960}
1961
1962EAPI void
1963elm_config_scroll_thumbscroll_border_friction_set(double friction)
1964{
1965 if (friction < 0.0) friction = 0.0;
1966 if (friction > 1.0) friction = 1.0;
1967 _elm_config->thumbscroll_border_friction = friction;
1968}
1969
1970EAPI double
1971elm_config_scroll_thumbscroll_sensitivity_friction_get(void)
1972{
1973 return _elm_config->thumbscroll_sensitivity_friction;
1974}
1975
1976EAPI void
1977elm_config_scroll_thumbscroll_sensitivity_friction_set(double friction)
1978{
1979 if (friction < 0.1) friction = 0.1;
1980 if (friction > 1.0) friction = 1.0;
1981 _elm_config->thumbscroll_sensitivity_friction = friction;
1982}
1983
1984EAPI void
1985elm_config_longpress_timeout_set(double longpress_timeout)
1986{
1987 _elm_config->longpress_timeout = longpress_timeout;
1988}
1989
1990EAPI double
1991elm_config_longpress_timeout_get(void)
1992{
1993 return _elm_config->longpress_timeout;
1994}
1995
1996EAPI void
1997elm_config_all_flush(void)
1998{
1999#ifdef HAVE_ELEMENTARY_X
2000 if (_prop_all_update_timer) ecore_timer_del(_prop_all_update_timer);
2001 _prop_all_update_timer = ecore_timer_add(0.1, _prop_all_update_cb, NULL);
2002#endif
2003}
2004
2005static void
2006_translation_init()
2007{
2008#ifdef ENABLE_NLS
2009 const char *cur_dom = textdomain(NULL);
2010 const char *trans_comment = gettext("");
2011 const char *msg_locale = setlocale(LC_MESSAGES, NULL);
2012
2013 /* Same concept as what glib does:
2014 * We shouldn't translate if there are no translations for the
2015 * application in the current locale + domain. (Unless locale is
2016 * en_/C where translating only parts of the interface make some
2017 * sense).
2018 */
2019 _elm_config->translate = !(strcmp (cur_dom, "messages") &&
2020 !*trans_comment && strncmp (msg_locale, "en_", 3) &&
2021 strcmp (msg_locale, "C"));
2022#endif
2023}
2024
2025void
2026_elm_config_init(void)
2027{
2028 if (!ELM_EVENT_CONFIG_ALL_CHANGED)
2029 ELM_EVENT_CONFIG_ALL_CHANGED = ecore_event_type_new();
2030 _desc_init();
2031 _profile_fetch_from_conf();
2032 _config_load();
2033 _env_get();
2034 if (_elm_preferred_engine) eina_stringshare_del(_elm_preferred_engine);
2035 if (_elm_config->engine)
2036 _elm_preferred_engine = eina_stringshare_add(_elm_config->engine);
2037 else
2038 _elm_preferred_engine = NULL;
2039 _translation_init();
2040 _config_apply();
2041 _elm_config_font_overlay_apply();
2042 _elm_recache();
2043}
2044
2045void
2046_elm_config_sub_shutdown(void)
2047{
2048#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
2049 if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
2050 ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
2051 ENGINE_COMPARE(ELM_XRENDER_X11) ||
2052 ENGINE_COMPARE(ELM_OPENGL_X11) ||
2053 ENGINE_COMPARE(ELM_OPENGL_COCOA))
2054#undef ENGINE_COMPARE
2055 {
2056#ifdef HAVE_ELEMENTARY_X
2057 ecore_x_disconnect();
2058#endif
2059 }
2060}
2061
2062void
2063_elm_config_sub_init(void)
2064{
2065#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
2066 if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
2067 ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
2068 ENGINE_COMPARE(ELM_XRENDER_X11) ||
2069 ENGINE_COMPARE(ELM_OPENGL_X11) ||
2070 ENGINE_COMPARE(ELM_OPENGL_COCOA))
2071#undef ENGINE_COMPARE
2072 {
2073#ifdef HAVE_ELEMENTARY_X
2074 if (!ecore_x_init(NULL))
2075 {
2076 ERR("Cannot connect to X11 display. check $DISPLAY variable");
2077 exit(1);
2078 }
2079 _root_1st = ecore_x_window_root_first_get();
2080
2081 if (!ecore_x_screen_is_composited(0))
2082 _elm_config->compositing = 0;
2083
2084 ecore_x_atoms_get(_atom_names, ATOM_COUNT, _atom);
2085 ecore_x_event_mask_set(_root_1st,
2086 ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
2087 _prop_change_handler = ecore_event_handler_add
2088 (ECORE_X_EVENT_WINDOW_PROPERTY, _prop_change, NULL);
2089 if (!getenv("ELM_PROFILE"))
2090 {
2091 char *s;
2092
2093 s = ecore_x_window_prop_string_get(_root_1st,
2094 _atom[ATOM_E_PROFILE]);
2095 if (s)
2096 {
2097 int changed = 0;
2098
2099 if (_elm_profile)
2100 {
2101 if (strcmp(_elm_profile, s)) changed = 1;
2102 free(_elm_profile);
2103 }
2104 _elm_profile = s;
2105 if (changed) _prop_config_get();
2106 }
2107 }
2108#endif
2109 }
2110 _config_sub_apply();
2111}
2112
2113void
2114_elm_config_reload(void)
2115{
2116 _config_free();
2117 _config_load();
2118 _config_apply();
2119 _elm_config_font_overlay_apply();
2120 _elm_rescale();
2121 _elm_recache();
2122}
2123
2124void
2125_elm_config_engine_set(const char *engine)
2126{
2127 if (_elm_config->engine && strcmp(_elm_config->engine, engine))
2128 eina_stringshare_del(_elm_config->engine);
2129
2130 _elm_config->engine = eina_stringshare_add(engine);
2131}
2132
2133EAPI const char *
2134elm_config_preferred_engine_get(void)
2135{
2136 return _elm_preferred_engine;
2137}
2138
2139EAPI void
2140elm_config_preferred_engine_set(const char *engine)
2141{
2142 if (engine)
2143 eina_stringshare_replace(&(_elm_preferred_engine), engine);
2144 else
2145 {
2146 if (_elm_preferred_engine) eina_stringshare_del(_elm_preferred_engine);
2147 _elm_preferred_engine = eina_stringshare_add(_elm_config->engine);
2148 }
2149}
2150
2151void
2152_elm_config_profile_set(const char *profile)
2153{
2154 Eina_Bool changed = EINA_FALSE;
2155
2156 if (_elm_profile)
2157 {
2158 if (strcmp(_elm_profile, profile))
2159 changed = 1;
2160 free(_elm_profile);
2161 }
2162
2163 _elm_profile = strdup(profile);
2164
2165 if (changed)
2166 {
2167 _config_free();
2168 _config_load();
2169 _config_apply();
2170 _elm_config_font_overlay_apply();
2171 _elm_rescale();
2172 _elm_recache();
2173 }
2174}
2175
2176void
2177_elm_config_shutdown(void)
2178{
2179#ifdef HAVE_ELEMENTARY_X
2180 if (_prop_all_update_timer)
2181 {
2182 ecore_timer_del(_prop_all_update_timer);
2183 _prop_all_update_timer = NULL;
2184 _prop_all_update_cb(NULL);
2185 }
2186 if (_prop_change_delay_timer) ecore_timer_del(_prop_change_delay_timer);
2187 _prop_change_delay_timer = NULL;
2188#endif
2189
2190#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
2191 if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
2192 ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
2193 ENGINE_COMPARE(ELM_XRENDER_X11) ||
2194 ENGINE_COMPARE(ELM_OPENGL_X11))
2195#undef ENGINE_COMPARE
2196 {
2197#ifdef HAVE_ELEMENTARY_X
2198 ecore_event_handler_del(_prop_change_handler);
2199 _prop_change_handler = NULL;
2200#endif
2201 }
2202 _config_free();
2203 if (_elm_preferred_engine)
2204 {
2205 eina_stringshare_del(_elm_preferred_engine);
2206 _elm_preferred_engine = NULL;
2207 }
2208 if (_elm_profile)
2209 {
2210 free(_elm_profile);
2211 _elm_profile = NULL;
2212 }
2213 _desc_shutdown();
2214}
2215
diff --git a/libraries/elementary/src/lib/elm_config.h b/libraries/elementary/src/lib/elm_config.h
new file mode 100644
index 0000000..413eab8
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_config.h
@@ -0,0 +1,948 @@
1/**
2 * @defgroup Config Elementary Config
3 * @ingroup Elementary
4 *
5 * Elementary configuration is formed by a set options bounded to a
6 * given @ref Profile profile, like @ref Theme theme, @ref Fingers
7 * "finger size", etc. These are functions with which one synchronizes
8 * changes made to those values to the configuration storing files, de
9 * facto. You most probably don't want to use the functions in this
10 * group unless you're writing an elementary configuration manager.
11 *
12 * @{
13 */
14
15/**
16 * Save back Elementary's configuration, so that it will persist on
17 * future sessions.
18 *
19 * @return @c EINA_TRUE, when successful. @c EINA_FALSE, otherwise.
20 * @ingroup Config
21 *
22 * This function will take effect -- thus, do I/O -- immediately. Use
23 * it when you want to save all configuration changes at once. The
24 * current configuration set will get saved onto the current profile
25 * configuration file.
26 *
27 */
28EAPI Eina_Bool elm_config_save(void);
29
30/**
31 * Reload Elementary's configuration, bounded to current selected
32 * profile.
33 *
34 * @return @c EINA_TRUE, when successful. @c EINA_FALSE, otherwise.
35 * @ingroup Config
36 *
37 * Useful when you want to force reloading of configuration values for
38 * a profile. If one removes user custom configuration directories,
39 * for example, it will force a reload with system values instead.
40 *
41 */
42EAPI void elm_config_reload(void);
43
44/**
45 * Flush all config settings then apply those settings to all applications
46 * using elementary on the current display.
47 *
48 * @ingroup Config
49 */
50EAPI void elm_config_all_flush(void);
51
52/**
53 * @}
54 */
55
56/**
57 * @defgroup Profile Elementary Profile
58 * @ingroup Elementary
59 *
60 * Profiles are pre-set options that affect the whole look-and-feel of
61 * Elementary-based applications. There are, for example, profiles
62 * aimed at desktop computer applications and others aimed at mobile,
63 * touchscreen-based ones. You most probably don't want to use the
64 * functions in this group unless you're writing an elementary
65 * configuration manager.
66 *
67 * @{
68 */
69
70/**
71 * Get Elementary's profile in use.
72 *
73 * This gets the global profile that is applied to all Elementary
74 * applications.
75 *
76 * @return The profile's name
77 * @ingroup Profile
78 */
79EAPI const char *elm_config_profile_get(void);
80
81/**
82 * Get an Elementary's profile directory path in the filesystem. One
83 * may want to fetch a system profile's dir or a user one (fetched
84 * inside $HOME).
85 *
86 * @param profile The profile's name
87 * @param is_user Whether to lookup for a user profile (@c EINA_TRUE)
88 * or a system one (@c EINA_FALSE)
89 * @return The profile's directory path.
90 * @ingroup Profile
91 *
92 * @note You must free it with elm_config_profile_dir_free().
93 */
94EAPI const char *elm_config_profile_dir_get(const char *profile, Eina_Bool is_user);
95
96/**
97 * Free an Elementary's profile directory path, as returned by
98 * elm_config_profile_dir_get().
99 *
100 * @param p_dir The profile's path
101 * @ingroup Profile
102 *
103 */
104EAPI void elm_config_profile_dir_free(const char *p_dir);
105
106/**
107 * Get Elementary's list of available profiles.
108 *
109 * @return The profiles list. List node data are the profile name
110 * strings.
111 * @ingroup Profile
112 *
113 * @note One must free this list, after usage, with the function
114 * elm_config_profile_list_free().
115 */
116EAPI Eina_List *elm_config_profile_list_get(void);
117
118/**
119 * Free Elementary's list of available profiles.
120 *
121 * @param l The profiles list, as returned by elm_config_profile_list_get().
122 * @ingroup Profile
123 *
124 */
125EAPI void elm_config_profile_list_free(Eina_List *l);
126
127/**
128 * Set Elementary's profile.
129 *
130 * This sets the global profile that is applied to Elementary
131 * applications. Just the process the call comes from will be
132 * affected.
133 *
134 * @param profile The profile's name
135 * @ingroup Profile
136 *
137 */
138EAPI void elm_config_profile_set(const char *profile);
139
140/**
141 * @}
142 */
143
144/**
145 * @defgroup Scrolling Elementary Scrolling
146 * @ingroup Elementary
147 *
148 * These are functions setting how scrollable views in Elementary
149 * widgets should behave on user interaction.
150 *
151 * @{
152 */
153
154/**
155 * Get whether scrollers should bounce when they reach their
156 * viewport's edge during a scroll.
157 *
158 * @return the thumb scroll bouncing state
159 *
160 * This is the default behavior for touch screens, in general.
161 * @ingroup Scrolling
162 */
163EAPI Eina_Bool elm_config_scroll_bounce_enabled_get(void);
164
165/**
166 * Set whether scrollers should bounce when they reach their
167 * viewport's edge during a scroll.
168 *
169 * @param enabled the thumb scroll bouncing state
170 *
171 * @see elm_config_scroll_bounce_enabled_get()
172 * @ingroup Scrolling
173 */
174EAPI void elm_config_scroll_bounce_enabled_set(Eina_Bool enabled);
175
176/**
177 * Get the amount of inertia a scroller will impose at bounce
178 * animations.
179 *
180 * @return the thumb scroll bounce friction
181 *
182 * @ingroup Scrolling
183 */
184EAPI double elm_config_scroll_bounce_friction_get(void);
185
186/**
187 * Set the amount of inertia a scroller will impose at bounce
188 * animations.
189 *
190 * @param friction the thumb scroll bounce friction
191 *
192 * @see elm_config_scroll_bounce_friction_get()
193 * @ingroup Scrolling
194 */
195EAPI void elm_config_scroll_bounce_friction_set(double friction);
196
197/**
198 * Get the amount of inertia a <b>paged</b> scroller will impose at
199 * page fitting animations.
200 *
201 * @return the page scroll friction
202 *
203 * @ingroup Scrolling
204 */
205EAPI double elm_config_scroll_page_scroll_friction_get(void);
206
207/**
208 * Set the amount of inertia a <b>paged</b> scroller will impose at
209 * page fitting animations.
210 *
211 * @param friction the page scroll friction
212 *
213 * @see elm_config_scroll_page_scroll_friction_get()
214 * @ingroup Scrolling
215 */
216EAPI void elm_config_scroll_page_scroll_friction_set(double friction);
217
218/**
219 * Get the amount of inertia a scroller will impose at region bring
220 * animations.
221 *
222 * @return the bring in scroll friction
223 *
224 * @ingroup Scrolling
225 */
226EAPI double elm_config_scroll_bring_in_scroll_friction_get(void);
227
228/**
229 * Set the amount of inertia a scroller will impose at region bring
230 * animations.
231 *
232 * @param friction the bring in scroll friction
233 *
234 * @see elm_config_scroll_bring_in_scroll_friction_get()
235 * @ingroup Scrolling
236 */
237EAPI void elm_config_scroll_bring_in_scroll_friction_set(double friction);
238
239/**
240 * Get the amount of inertia scrollers will impose at animations
241 * triggered by Elementary widgets' zooming API.
242 *
243 * @return the zoom friction
244 *
245 * @ingroup Scrolling
246 */
247EAPI double elm_config_scroll_zoom_friction_get(void);
248
249/**
250 * Set the amount of inertia scrollers will impose at animations
251 * triggered by Elementary widgets' zooming API.
252 *
253 * @param friction the zoom friction
254 *
255 * @see elm_config_scroll_zoom_friction_get()
256 * @ingroup Scrolling
257 */
258EAPI void elm_config_scroll_zoom_friction_set(double friction);
259
260/**
261 * Get whether scrollers should be draggable from any point in their
262 * views.
263 *
264 * @return the thumb scroll state
265 *
266 * @note This is the default behavior for touch screens, in general.
267 * @note All other functions namespaced with "thumbscroll" will only
268 * have effect if this mode is enabled.
269 *
270 * @ingroup Scrolling
271 */
272EAPI Eina_Bool elm_config_scroll_thumbscroll_enabled_get(void);
273
274/**
275 * Set whether scrollers should be draggable from any point in their
276 * views.
277 *
278 * @param enabled the thumb scroll state
279 *
280 * @see elm_config_scroll_thumbscroll_enabled_get()
281 * @ingroup Scrolling
282 */
283EAPI void elm_config_scroll_thumbscroll_enabled_set(Eina_Bool enabled);
284
285/**
286 * Get the number of pixels one should travel while dragging a
287 * scroller's view to actually trigger scrolling.
288 *
289 * @return the thumb scroll threshold
290 *
291 * One would use higher values for touch screens, in general, because
292 * of their inherent imprecision.
293 * @ingroup Scrolling
294 */
295EAPI unsigned int elm_config_scroll_thumbscroll_threshold_get(void);
296
297/**
298 * Set the number of pixels one should travel while dragging a
299 * scroller's view to actually trigger scrolling.
300 *
301 * @param threshold the thumb scroll threshold
302 *
303 * @see elm_config_thumbscroll_threshold_get()
304 * @ingroup Scrolling
305 */
306EAPI void elm_config_scroll_thumbscroll_threshold_set(unsigned int threshold);
307
308/**
309 * Get the minimum speed of mouse cursor movement which will trigger
310 * list self scrolling animation after a mouse up event
311 * (pixels/second).
312 *
313 * @return the thumb scroll momentum threshold
314 *
315 * @ingroup Scrolling
316 */
317EAPI double elm_config_scroll_thumbscroll_momentum_threshold_get(void);
318
319/**
320 * Set the minimum speed of mouse cursor movement which will trigger
321 * list self scrolling animation after a mouse up event
322 * (pixels/second).
323 *
324 * @param threshold the thumb scroll momentum threshold
325 *
326 * @see elm_config_thumbscroll_momentum_threshold_get()
327 * @ingroup Scrolling
328 */
329EAPI void elm_config_scroll_thumbscroll_momentum_threshold_set(double threshold);
330
331/**
332 * Get the amount of inertia a scroller will impose at self scrolling
333 * animations.
334 *
335 * @return the thumb scroll friction
336 *
337 * @ingroup Scrolling
338 */
339EAPI double elm_config_scroll_thumbscroll_friction_get(void);
340
341/**
342 * Set the amount of inertia a scroller will impose at self scrolling
343 * animations.
344 *
345 * @param friction the thumb scroll friction
346 *
347 * @see elm_config_thumbscroll_friction_get()
348 * @ingroup Scrolling
349 */
350EAPI void elm_config_scroll_thumbscroll_friction_set(double friction);
351
352/**
353 * Get the amount of lag between your actual mouse cursor dragging
354 * movement and a scroller's view movement itself, while pushing it
355 * into bounce state manually.
356 *
357 * @return the thumb scroll border friction
358 *
359 * @ingroup Scrolling
360 */
361EAPI double elm_config_scroll_thumbscroll_border_friction_get(void);
362
363/**
364 * Set the amount of lag between your actual mouse cursor dragging
365 * movement and a scroller's view movement itself, while pushing it
366 * into bounce state manually.
367 *
368 * @param friction the thumb scroll border friction. @c 0.0 for
369 * perfect synchrony between two movements, @c 1.0 for maximum
370 * lag.
371 *
372 * @see elm_config_thumbscroll_border_friction_get()
373 * @note parameter value will get bound to 0.0 - 1.0 interval, always
374 *
375 * @ingroup Scrolling
376 */
377EAPI void elm_config_scroll_thumbscroll_border_friction_set(double friction);
378
379/**
380 * Get the sensitivity amount which is be multiplied by the length of
381 * mouse dragging.
382 *
383 * @return the thumb scroll sensitivity friction
384 *
385 * @ingroup Scrolling
386 */
387EAPI double elm_config_scroll_thumbscroll_sensitivity_friction_get(void);
388
389/**
390 * Set the sensitivity amount which is be multiplied by the length of
391 * mouse dragging.
392 *
393 * @param friction the thumb scroll sensitivity friction. @c 0.1 for
394 * minimum sensitivity, @c 1.0 for maximum sensitivity. 0.25
395 * is proper.
396 *
397 * @see elm_config_thumbscroll_sensitivity_friction_get()
398 * @note parameter value will get bound to 0.1 - 1.0 interval, always
399 *
400 * @ingroup Scrolling
401 */
402EAPI void elm_config_scroll_thumbscroll_sensitivity_friction_set(double friction);
403
404/**
405 * @}
406 */
407
408/**
409 * Get the duration for occurring long press event.
410 *
411 * @return Timeout for long press event
412 * @ingroup Longpress
413 */
414EAPI double elm_config_longpress_timeout_get(void);
415
416/**
417 * Set the duration for occurring long press event.
418 *
419 * @param lonpress_timeout Timeout for long press event
420 * @ingroup Longpress
421 */
422EAPI void elm_config_longpress_timeout_set(double longpress_timeout);
423
424/**
425 * Get the duration after which tooltip will be shown.
426 *
427 * @return Duration after which tooltip will be shown.
428 */
429EAPI double elm_config_tooltip_delay_get(void);
430
431/**
432 * Set the duration after which tooltip will be shown.
433 *
434 * @return EINA_TRUE if value is set.
435 */
436EAPI void elm_config_tooltip_delay_set(double delay);
437
438/**
439 * Get the configured cursor engine only usage
440 *
441 * This gets the globally configured exclusive usage of engine cursors.
442 *
443 * @return 1 if only engine cursors should be used
444 * @ingroup Cursors
445 */
446EAPI Eina_Bool elm_config_cursor_engine_only_get(void);
447
448/**
449 * Set the configured cursor engine only usage
450 *
451 * This sets the globally configured exclusive usage of engine cursors.
452 * It won't affect cursors set before changing this value.
453 *
454 * @param engine_only If 1 only engine cursors will be enabled, if 0 will
455 * look for them on theme before.
456 * @ingroup Cursors
457 */
458EAPI void elm_config_cursor_engine_only_set(Eina_Bool engine_only);
459
460/**
461 * Get the global scaling factor
462 *
463 * This gets the globally configured scaling factor that is applied to all
464 * objects.
465 *
466 * @return The scaling factor
467 * @ingroup Scaling
468 */
469EAPI double elm_config_scale_get(void);
470
471/**
472 * Set the global scaling factor
473 *
474 * This sets the globally configured scaling factor that is applied to all
475 * objects.
476 *
477 * @param scale The scaling factor to set
478 * @ingroup Scaling
479 */
480EAPI void elm_config_scale_set(double scale);
481
482/**
483 * @defgroup Password_last_show Password show last
484 * @ingroup Elementary
485 *
486 * Show last feature of password mode enables user to view
487 * the last input entered for few seconds before masking it.
488 * These functions allow to set this feature in password mode
489 * of entry widget and also allow to manipulate the duration
490 * for which the input has to be visible.
491 *
492 * @{
493 */
494
495/**
496 * Get the "show last" setting of password mode.
497 *
498 * This gets the "show last" setting of password mode which might be
499 * enabled or disabled.
500 *
501 * @return @c EINA_TRUE, if the "show last" setting is enabled,
502 * @c EINA_FALSE if it's disabled.
503 *
504 * @ingroup Password_last_show
505 */
506EAPI Eina_Bool elm_config_password_show_last_get(void);
507
508/**
509 * Set show last setting in password mode.
510 *
511 * This enables or disables show last setting of password mode.
512 *
513 * @param password_show_last If EINA_TRUE enables "show last" in password mode.
514 * @see elm_config_password_show_last_timeout_set()
515 * @ingroup Password_last_show
516 */
517EAPI void elm_config_password_show_last_set(Eina_Bool password_show_last);
518
519/**
520 * Gets the timeout value in "show last" password mode.
521 *
522 * This gets the time out value for which the last input entered in password
523 * mode will be visible.
524 *
525 * @return The timeout value of "show last" password mode.
526 * @ingroup Password_last_show
527 */
528EAPI double elm_config_password_show_last_timeout_get(void);
529
530/**
531 * Set's the timeout value in "show last" password mode.
532 *
533 * This sets the time out value for which the last input entered in password
534 * mode will be visible.
535 *
536 * @param password_show_last_timeout The timeout value.
537 * @see elm_config_password_show_last_set()
538 * @ingroup Password_last_show
539 */
540EAPI void elm_config_password_show_last_timeout_set(double password_show_last_timeout);
541
542/**
543 * @}
544 */
545
546/**
547 * @defgroup Engine Elementary Engine
548 * @ingroup Elementary
549 *
550 * These are functions setting and querying which rendering engine
551 * Elementary will use for drawing its windows' pixels.
552 *
553 * The following are the available engines:
554 * @li "software_x11"
555 * @li "fb"
556 * @li "directfb"
557 * @li "software_16_x11"
558 * @li "software_8_x11"
559 * @li "xrender_x11"
560 * @li "opengl_x11"
561 * @li "software_gdi"
562 * @li "software_16_wince_gdi"
563 * @li "sdl"
564 * @li "software_16_sdl"
565 * @li "opengl_sdl"
566 * @li "buffer"
567 * @li "ews"
568 * @li "opengl_cocoa"
569 * @li "psl1ght"
570 *
571 * @{
572 */
573
574/**
575 * @brief Get Elementary's rendering engine in use.
576 *
577 * @return The rendering engine's name
578 * @note there's no need to free the returned string, here.
579 *
580 * This gets the global rendering engine that is applied to all Elementary
581 * applications.
582 *
583 * @see elm_config_engine_set()
584 */
585EAPI const char *elm_config_engine_get(void);
586
587/**
588 * @brief Set Elementary's rendering engine for use.
589 *
590 * @param engine The rendering engine's name
591 *
592 * Note that it will take effect only to Elementary windows created after
593 * this is called.
594 *
595 * @see elm_win_add()
596 */
597EAPI void elm_config_engine_set(const char *engine);
598
599/**
600 * @brief Get Elementary's preferred engine to use.
601 *
602 * @return The rendering engine's name
603 * @note there's no need to free the returned string, here.
604 *
605 * This gets the global rendering engine that is applied to all Elementary
606 * applications and is PREFERRED by the application. This can (and will)
607 * override the engine configured for all applications which.
608 *
609 * @see elm_config_preferred_engine_set()
610 */
611EAPI const char *elm_config_preferred_engine_get(void);
612
613/**
614 * @brief Set Elementary's preferred rendering engine for use.
615 *
616 * @param engine The rendering engine's name
617 *
618 * Note that it will take effect only to Elementary windows created after
619 * this is called. This overrides the engine set by configuration at
620 * application startup. Note that it is a hint and may not be honored.
621 *
622 * @see elm_win_add()
623 */
624EAPI void elm_config_preferred_engine_set(const char *engine);
625
626typedef struct _Elm_Text_Class
627{
628 const char *name;
629 const char *desc;
630} Elm_Text_Class;
631
632typedef struct _Elm_Font_Overlay
633{
634 const char *text_class;
635 const char *font;
636 Evas_Font_Size size;
637} Elm_Font_Overlay;
638
639/**
640 * Get Elementary's list of supported text classes.
641 *
642 * @return The text classes list, with @c Elm_Text_Class blobs as data.
643 * @ingroup Fonts
644 *
645 * Release the list with elm_text_classes_list_free().
646 */
647EAPI Eina_List *elm_config_text_classes_list_get(void);
648
649/**
650 * Free Elementary's list of supported text classes.
651 *
652 * @ingroup Fonts
653 *
654 * @see elm_config_text_classes_list_get().
655 */
656EAPI void elm_config_text_classes_list_free(Eina_List *list);
657
658/**
659 * Get Elementary's list of font overlays, set with
660 * elm_config_font_overlay_set().
661 *
662 * @return The font overlays list, with @c Elm_Font_Overlay blobs as
663 * data.
664 *
665 * @ingroup Fonts
666 *
667 * For each text class, one can set a <b>font overlay</b> for it,
668 * overriding the default font properties for that class coming from
669 * the theme in use. There is no need to free this list.
670 *
671 * @see elm_config_font_overlay_set() and elm_config_font_overlay_unset().
672 */
673EAPI const Eina_List *elm_config_font_overlay_list_get(void);
674
675/**
676 * Set a font overlay for a given Elementary text class.
677 *
678 * @param text_class Text class name
679 * @param font Font name and style string
680 * @param size Font size
681 *
682 * @ingroup Fonts
683 *
684 * @p font has to be in the format returned by
685 * elm_font_fontconfig_name_get(). @see elm_config_font_overlay_list_get()
686 * and elm_config_font_overlay_unset().
687 */
688EAPI void elm_config_font_overlay_set(const char *text_class, const char *font, Evas_Font_Size size);
689
690/**
691 * Unset a font overlay for a given Elementary text class.
692 *
693 * @param text_class Text class name
694 *
695 * @ingroup Fonts
696 *
697 * This will bring back text elements belonging to text class
698 * @p text_class back to their default font settings.
699 */
700EAPI void elm_config_font_overlay_unset(const char *text_class);
701
702/**
703 * Apply the changes made with elm_config_font_overlay_set() and
704 * elm_config_font_overlay_unset() on the current Elementary window.
705 *
706 * @ingroup Fonts
707 *
708 * This applies all font overlays set to all objects in the UI.
709 */
710EAPI void elm_config_font_overlay_apply(void);
711
712/**
713 * Get the configured "finger size"
714 *
715 * @return The finger size
716 *
717 * This gets the globally configured finger size, <b>in pixels</b>
718 *
719 * @ingroup Fingers
720 */
721EAPI Evas_Coord elm_config_finger_size_get(void);
722
723/**
724 * Set the configured finger size
725 *
726 * This sets the globally configured finger size in pixels
727 *
728 * @param size The finger size
729 * @ingroup Fingers
730 */
731EAPI void elm_config_finger_size_set(Evas_Coord size);
732
733
734/**
735 * Get the configured cache flush interval time
736 *
737 * This gets the globally configured cache flush interval time, in
738 * ticks
739 *
740 * @return The cache flush interval time
741 * @ingroup Caches
742 *
743 * @see elm_cache_all_flush()
744 */
745EAPI int elm_config_cache_flush_interval_get(void);
746
747/**
748 * Set the configured cache flush interval time
749 *
750 * This sets the globally configured cache flush interval time, in ticks
751 *
752 * @param size The cache flush interval time
753 * @ingroup Caches
754 *
755 * @see elm_cache_all_flush()
756 */
757EAPI void elm_config_cache_flush_interval_set(int size);
758
759/**
760 * Get the configured cache flush enabled state
761 *
762 * This gets the globally configured cache flush state - if it is enabled
763 * or not. When cache flushing is enabled, elementary will regularly
764 * (see elm_config_cache_flush_interval_get() ) flush caches and dump data out of
765 * memory and allow usage to re-seed caches and data in memory where it
766 * can do so. An idle application will thus minimize its memory usage as
767 * data will be freed from memory and not be re-loaded as it is idle and
768 * not rendering or doing anything graphically right now.
769 *
770 * @return The cache flush state
771 * @ingroup Caches
772 *
773 * @see elm_cache_all_flush()
774 */
775EAPI Eina_Bool elm_config_cache_flush_enabled_get(void);
776
777/**
778 * Set the configured cache flush enabled state
779 *
780 * This sets the globally configured cache flush enabled state.
781 *
782 * @param enabled The cache flush enabled state
783 * @ingroup Caches
784 *
785 * @see elm_cache_all_flush()
786 */
787EAPI void elm_config_cache_flush_enabled_set(Eina_Bool enabled);
788
789/**
790 * Get the configured font cache size
791 *
792 * This gets the globally configured font cache size, in bytes.
793 *
794 * @return The font cache size
795 * @ingroup Caches
796 */
797EAPI int elm_config_cache_font_cache_size_get(void);
798
799/**
800 * Set the configured font cache size
801 *
802 * This sets the globally configured font cache size, in bytes
803 *
804 * @param size The font cache size
805 * @ingroup Caches
806 */
807EAPI void elm_config_cache_font_cache_size_set(int size);
808
809/**
810 * Get the configured image cache size
811 *
812 * This gets the globally configured image cache size, in bytes
813 *
814 * @return The image cache size
815 * @ingroup Caches
816 */
817EAPI int elm_config_cache_image_cache_size_get(void);
818
819/**
820 * Set the configured image cache size
821 *
822 * This sets the globally configured image cache size, in bytes
823 *
824 * @param size The image cache size
825 * @ingroup Caches
826 */
827EAPI void elm_config_cache_image_cache_size_set(int size);
828
829
830/**
831 * Get the configured edje file cache size.
832 *
833 * This gets the globally configured edje file cache size, in number
834 * of files.
835 *
836 * @return The edje file cache size
837 * @ingroup Caches
838 */
839EAPI int elm_config_cache_edje_file_cache_size_get(void);
840
841/**
842 * Set the configured edje file cache size
843 *
844 * This sets the globally configured edje file cache size, in number
845 * of files.
846 *
847 * @param size The edje file cache size
848 * @ingroup Caches
849 */
850EAPI void elm_config_cache_edje_file_cache_size_set(int size);
851
852/**
853 * Get the configured edje collections (groups) cache size.
854 *
855 * This gets the globally configured edje collections cache size, in
856 * number of collections.
857 *
858 * @return The edje collections cache size
859 * @ingroup Caches
860 */
861EAPI int elm_config_cache_edje_collection_cache_size_get(void);
862
863/**
864 * Set the configured edje collections (groups) cache size
865 *
866 * This sets the globally configured edje collections cache size, in
867 * number of collections.
868 *
869 * @param size The edje collections cache size
870 * @ingroup Caches
871 */
872EAPI void elm_config_cache_edje_collection_cache_size_set(int size);
873
874/**
875 * Get the enable status of the focus highlight
876 *
877 * This gets whether the highlight on focused objects is enabled or not
878 *
879 * @see elm_config_focus_highlight_enabled_set()
880 * @ingroup Focus
881 */
882EAPI Eina_Bool elm_config_focus_highlight_enabled_get(void);
883
884/**
885 * Set the enable status of the focus highlight
886 *
887 * @param enable Enable highlight if EINA_TRUE, disable otherwise
888 *
889 * Set whether to show or not the highlight on focused objects
890 *
891 * Note that it will take effect only to Elementary windows created after
892 * this is called.
893 *
894 * @see elm_win_add()
895 *
896 * @ingroup Focus
897 */
898EAPI void elm_config_focus_highlight_enabled_set(Eina_Bool enable);
899
900/**
901 * Get the enable status of the highlight animation
902 *
903 * @return The focus highlight mode set
904 *
905 * Get whether the focus highlight, if enabled, will animate its switch from
906 * one object to the next
907 *
908 * @ingroup Focus
909 */
910EAPI Eina_Bool elm_config_focus_highlight_animate_get(void);
911
912/**
913 * Set the enable status of the highlight animation
914 *
915 * @param animate Enable animation if EINA_TRUE, disable otherwise
916 *
917 * Set whether the focus highlight, if enabled, will animate its switch from
918 * one object to the next
919 *
920 * Note that it will take effect only to Elementary windows created after
921 * this is called.
922 *
923 * @see elm_win_add()
924 *
925 * @ingroup Focus
926 */
927EAPI void elm_config_focus_highlight_animate_set(Eina_Bool animate);
928
929/**
930 * Get the system mirrored mode. This determines the default mirrored mode
931 * of widgets.
932 *
933 * @return EINA_TRUE if mirrored is set, EINA_FALSE otherwise
934 */
935EAPI Eina_Bool elm_config_mirrored_get(void);
936
937/**
938 * Set the system mirrored mode. This determines the default mirrored mode
939 * of widgets.
940 *
941 * @param mirrored EINA_TRUE to set mirrored mode, EINA_FALSE to unset it.
942 */
943EAPI void elm_config_mirrored_set(Eina_Bool mirrored);
944
945/**
946 * @}
947 */
948
diff --git a/libraries/elementary/src/lib/elm_conform.c b/libraries/elementary/src/lib/elm_conform.c
new file mode 100644
index 0000000..355341e
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_conform.c
@@ -0,0 +1,692 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#ifndef MIN
5# define MIN(a,b) ((a) < (b)) ? (a) : (b)
6#endif
7
8#ifndef MAX
9# define MAX(a,b) ((a) < (b)) ? (b) : (a)
10#endif
11
12typedef struct _Widget_Data Widget_Data;
13struct _Widget_Data
14{
15 Evas_Object *base;
16 Evas_Object *indicator;
17 Evas_Object *softkey;
18 Evas_Object *virtualkeypad;
19 Evas_Object *clipboard;
20 Evas_Object *content;
21 Evas_Object *scroller;
22#ifdef HAVE_ELEMENTARY_X
23 Ecore_Event_Handler *prop_hdl;
24 Ecore_X_Virtual_Keyboard_State vkb_state;
25#endif
26 struct
27 {
28 Ecore_Animator *animator; // animaton timer
29 double start; // time started
30 Evas_Coord auto_x, auto_y; // desired delta
31 Evas_Coord x, y; // current delta
32 } delta;
33 Ecore_Job *show_region_job;
34};
35
36/* Enum to identify conformant swallow parts */
37typedef enum _Conformant_Part_Type Conformant_Part_Type;
38enum _Conformant_Part_Type
39{
40 ELM_CONFORM_INDICATOR_PART = 1,
41 ELM_CONFORM_SOFTKEY_PART = 2,
42 ELM_CONFORM_VIRTUAL_KEYPAD_PART = 4,
43 ELM_CONFORM_CLIPBOARD_PART = 8
44};
45
46#ifdef HAVE_ELEMENTARY_X
47#define SUB_TYPE_COUNT 2
48static char *sub_type[SUB_TYPE_COUNT] = { "scroller", "genlist" };
49#endif
50
51/* local function prototypes */
52static const char *widtype = NULL;
53static void _del_pre_hook(Evas_Object *obj);
54static void _del_hook(Evas_Object *obj);
55static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
56static void _theme_hook(Evas_Object *obj);
57static void _content_set_hook(Evas_Object *obj,
58 const char *part,
59 Evas_Object *content);
60static Evas_Object *_content_get_hook(const Evas_Object *obj,
61 const char *part);
62static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
63static void _swallow_conformant_parts(Evas_Object *obj);
64static void _conformant_part_size_set(Evas_Object *obj,
65 Evas_Object *sobj,
66 Evas_Coord sx,
67 Evas_Coord sy,
68 Evas_Coord sw,
69 Evas_Coord sh);
70static void _conformant_part_sizing_eval(Evas_Object *obj,
71 Conformant_Part_Type part_type);
72static void _conformant_move_resize_event_cb(void *data,
73 Evas *e,
74 Evas_Object *obj,
75 void *event_info);
76static void _sizing_eval(Evas_Object *obj);
77static void _show_region_job(void *data);
78static void _changed_size_hints(void *data, Evas *e,
79 Evas_Object *obj,
80 void *event_info);
81
82/* local functions */
83static void
84_del_pre_hook(Evas_Object *obj)
85{
86 Widget_Data *wd = elm_widget_data_get(obj);
87 if (!wd) return;
88
89#ifdef HAVE_ELEMENTARY_X
90 if (wd->prop_hdl) ecore_event_handler_del(wd->prop_hdl);
91#endif
92}
93
94static void
95_del_hook(Evas_Object *obj)
96{
97 Widget_Data *wd = elm_widget_data_get(obj);
98 if (!wd) return;
99
100 if (wd->show_region_job) ecore_job_del(wd->show_region_job);
101 free(wd);
102}
103
104static void
105_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
106{
107 Widget_Data *wd = elm_widget_data_get(obj);
108 if (!wd) return;
109
110 edje_object_mirrored_set(wd->base, rtl);
111}
112
113static void
114_theme_hook(Evas_Object *obj)
115{
116 Widget_Data *wd = elm_widget_data_get(obj);
117 if (!wd) return;
118
119 _elm_widget_mirrored_reload(obj);
120 _mirrored_set(obj, elm_widget_mirrored_get(obj));
121 _elm_theme_object_set(obj, wd->base, "conformant", "base",
122 elm_widget_style_get(obj));
123 _swallow_conformant_parts(obj);
124
125 if (wd->content)
126 edje_object_part_swallow(wd->base, "elm.swallow.content", wd->content);
127 _sizing_eval(obj);
128}
129
130static void
131_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
132{
133 ELM_CHECK_WIDTYPE(obj, widtype);
134 Widget_Data *wd;
135
136 if (part && strcmp(part, "default")) return;
137 wd = elm_widget_data_get(obj);
138 if (!wd) return;
139 if (wd->content == content) return;
140 if (wd->content) evas_object_del(wd->content);
141 wd->content = content;
142 if (content)
143 {
144 elm_widget_sub_object_add(obj, content);
145 evas_object_event_callback_add(content,
146 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
147 _changed_size_hints, obj);
148 edje_object_part_swallow(wd->base, "elm.swallow.content", content);
149 }
150 _sizing_eval(obj);
151}
152
153static Evas_Object *
154_content_get_hook(const Evas_Object *obj, const char *part)
155{
156 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
157 Widget_Data *wd;
158
159 if (part && strcmp(part, "default")) return NULL;
160 wd = elm_widget_data_get(obj);
161 if (!wd) return NULL;
162 return wd->content;
163}
164
165static Evas_Object *
166_content_unset_hook(Evas_Object *obj, const char *part)
167{
168 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
169 Widget_Data *wd;
170 Evas_Object *content;
171 if (part && strcmp(part, "default")) return NULL;
172 wd = elm_widget_data_get(obj);
173 if ((!wd) || (!wd->content)) return NULL;
174
175 content = wd->content;
176 elm_widget_sub_object_del(obj, wd->content);
177 evas_object_event_callback_del_full(content,
178 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
179 _changed_size_hints, obj);
180 edje_object_part_unswallow(wd->base, content);
181 wd->content = NULL;
182 return content;
183}
184
185static void
186_sizing_eval(Evas_Object *obj)
187{
188 Widget_Data *wd = elm_widget_data_get(obj);
189 Evas_Coord mw = -1, mh = -1;
190 if (!wd) return;
191
192 edje_object_size_min_calc(wd->base, &mw, &mh);
193 evas_object_size_hint_min_set(obj, mw, mh);
194 evas_object_size_hint_max_set(obj, -1, -1);
195}
196
197/* Example of env vars:
198 * ILLUME_KBD="0, 0, 800, 301"
199 * ILLUME_IND=0,0,800,32
200 * ILLUME_STK="0,568,800,32
201 */
202static Eina_Bool
203_conformant_part_geometry_env_get(const char *part, int *sx, int *sy, int *sw, int *sh)
204{
205 const char delimiters[] = " ,;";
206 char *env_val, *token;
207 char buf[PATH_MAX];
208 int tsx, tsy, tsw;
209
210 if (!(env_val = getenv(part))) return EINA_FALSE;
211
212 /* strtok would modify env var if not copied to a buffer */
213 strncpy(buf, env_val, sizeof(buf));
214
215 token = strtok(buf, delimiters);
216 if (!token) return EINA_FALSE;
217 tsx = atoi(token);
218
219 token = strtok(NULL, delimiters);
220 if (!token) return EINA_FALSE;
221 tsy = atoi(token);
222
223 token = strtok(NULL, delimiters);
224 if (!token) return EINA_FALSE;
225 tsw = atoi(token);
226
227 token = strtok(NULL, delimiters);
228 if (!token) return EINA_FALSE;
229 *sh = atoi(token);
230
231 *sx = tsx;
232 *sy = tsy;
233 *sw = tsw;
234
235 return EINA_TRUE;
236}
237
238static void
239_conformant_part_size_set(Evas_Object *obj, Evas_Object *sobj, Evas_Coord sx,
240 Evas_Coord sy, Evas_Coord sw, Evas_Coord sh)
241{
242 Evas_Coord cx, cy, cw, ch;
243 Evas_Coord part_height = 0, part_width = 0;
244
245 evas_object_geometry_get(obj, &cx, &cy, &cw, &ch);
246
247 /* Part overlapping with conformant */
248 if ((cx < (sx + sw)) && ((cx + cw) > sx)
249 && (cy < (sy + sh)) && ((cy + ch) > sy))
250 {
251 part_height = MIN((cy + ch), (sy + sh)) - MAX(cy, sy);
252 part_width = MIN((cx + cw), (sx + sw)) - MAX(cx, sx);
253 }
254
255 evas_object_size_hint_min_set(sobj, part_width, part_height);
256 evas_object_size_hint_max_set(sobj, part_width, part_height);
257}
258
259static void
260_conformant_part_sizing_eval(Evas_Object *obj, Conformant_Part_Type part_type)
261{
262#ifdef HAVE_ELEMENTARY_X
263 Ecore_X_Window zone = 0;
264 Evas_Object *top;
265#endif
266 Ecore_X_Window xwin;
267 int sx = -1, sy = -1, sw = -1, sh = -1;
268 Widget_Data *wd = elm_widget_data_get(obj);
269 if (!wd) return;
270
271#ifdef HAVE_ELEMENTARY_X
272 top = elm_widget_top_get(obj);
273 xwin = elm_win_xwindow_get(top);
274 if (xwin)
275 zone = ecore_x_e_illume_zone_get(xwin);
276#endif
277
278 if (part_type & ELM_CONFORM_INDICATOR_PART)
279 {
280 if ((!_conformant_part_geometry_env_get("ILLUME_IND",
281 &sx, &sy, &sw, &sh)) && (xwin))
282 {
283#ifdef HAVE_ELEMENTARY_X
284 //No information of the indicator geometry, reset the geometry.
285 if (!ecore_x_e_illume_indicator_geometry_get(zone, &sx, &sy, &sw, &sh))
286 sx = sy = sw = sh = 0;
287#else
288 ;
289#endif
290 }
291 _conformant_part_size_set(obj, wd->indicator, sx, sy, sw, sh);
292 }
293 if (part_type & ELM_CONFORM_VIRTUAL_KEYPAD_PART)
294 {
295 if ((!_conformant_part_geometry_env_get("ILLUME_KBD",
296 &sx, &sy, &sw, &sh)) && (xwin))
297 {
298#ifdef HAVE_ELEMENTARY_X
299 //No information of the keyboard geometry, reset the geometry.
300 if (!ecore_x_e_illume_keyboard_geometry_get(zone, &sx, &sy, &sw, &sh))
301 sx = sy = sw = sh = 0;
302#else
303 ;
304#endif
305 }
306 _conformant_part_size_set(obj, wd->virtualkeypad, sx, sy, sw, sh);
307 }
308 if (part_type & ELM_CONFORM_SOFTKEY_PART)
309 {
310 if ((!_conformant_part_geometry_env_get("ILLUME_STK",
311 &sx, &sy, &sw, &sh)) && (xwin))
312 {
313#ifdef HAVE_ELEMENTARY_X
314 //No information of the softkey geometry, reset the geometry.
315 if (!ecore_x_e_illume_softkey_geometry_get(zone, &sx, &sy, &sw, &sh))
316 sx = sy = sw = sh = 0;
317#else
318 ;
319#endif
320 }
321 _conformant_part_size_set(obj, wd->softkey, sx, sy, sw, sh);
322 }
323 if (part_type & ELM_CONFORM_CLIPBOARD_PART)
324 {
325 if ((!_conformant_part_geometry_env_get("ILLUME_CB",
326 &sx, &sy, &sw, &sh)) && (xwin))
327 {
328#ifdef HAVE_ELEMENTARY_X
329 //No information of the clipboard geometry, reset the geometry.
330 if (!ecore_x_e_illume_clipboard_geometry_get(zone, &sx, &sy, &sw, &sh))
331 sx = sy = sw = sh = 0;
332#else
333 ;
334#endif
335 }
336 _conformant_part_size_set(obj, wd->clipboard, sx, sy, sw, sh);
337 }
338}
339
340static void
341_swallow_conformant_parts(Evas_Object *obj)
342{
343 Widget_Data *wd = elm_widget_data_get(obj);
344 Evas *e = evas_object_evas_get(obj);
345 if (!wd || !e) return;
346
347 wd->scroller = NULL;
348
349 //Indicator
350 if (!wd->indicator)
351 {
352 wd->indicator = evas_object_rectangle_add(e);
353 elm_widget_sub_object_add(obj, wd->indicator);
354 evas_object_size_hint_min_set(wd->indicator, -1, 0);
355 evas_object_size_hint_max_set(wd->indicator, -1, 0);
356 }
357 else
358 _conformant_part_sizing_eval(obj, ELM_CONFORM_INDICATOR_PART);
359 evas_object_color_set(wd->indicator, 0, 0, 0, 0);
360 edje_object_part_swallow(wd->base, "elm.swallow.indicator", wd->indicator);
361
362 //Virtual Keyboard
363 if (!wd->virtualkeypad)
364 {
365 wd->virtualkeypad = evas_object_rectangle_add(e);
366 elm_widget_sub_object_add(obj, wd->virtualkeypad);
367 evas_object_size_hint_min_set(wd->virtualkeypad, -1, 0);
368 evas_object_size_hint_max_set(wd->virtualkeypad, -1, 0);
369 }
370 else
371 _conformant_part_sizing_eval(obj, ELM_CONFORM_VIRTUAL_KEYPAD_PART);
372 evas_object_color_set(wd->virtualkeypad, 0, 0, 0, 0);
373 edje_object_part_swallow(wd->base, "elm.swallow.virtualkeypad",
374 wd->virtualkeypad);
375 //Clipboard
376 if (!wd->clipboard)
377 {
378 wd->clipboard = evas_object_rectangle_add(e);
379 elm_widget_sub_object_add(obj, wd->clipboard);
380 evas_object_size_hint_min_set(wd->clipboard, -1, 0);
381 evas_object_size_hint_max_set(wd->clipboard, -1, 0);
382 }
383 else
384 _conformant_part_sizing_eval(obj, ELM_CONFORM_CLIPBOARD_PART);
385 evas_object_color_set(wd->clipboard, 0, 0, 0, 0);
386 edje_object_part_swallow(wd->base, "elm.swallow.clipboard",
387 wd->clipboard);
388
389 //Softkey
390 if (!wd->softkey)
391 {
392 wd->softkey = evas_object_rectangle_add(e);
393 elm_widget_sub_object_add(obj, wd->softkey);
394 evas_object_size_hint_min_set(wd->softkey, -1, 0);
395 evas_object_size_hint_max_set(wd->softkey, -1, 0);
396 }
397 else
398 _conformant_part_sizing_eval(obj, ELM_CONFORM_SOFTKEY_PART);
399 evas_object_color_set(wd->softkey, 0, 0, 0, 0);
400 edje_object_part_swallow(wd->base, "elm.swallow.softkey", wd->softkey);
401}
402
403static void
404_changed_size_hints(void *data, Evas *e __UNUSED__,
405 Evas_Object *obj __UNUSED__,
406 void *event_info __UNUSED__)
407{
408 Widget_Data *wd = elm_widget_data_get(data);
409 if (!wd) return;
410
411 _sizing_eval(data);
412}
413
414static void
415_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
416{
417 Widget_Data *wd = elm_widget_data_get(obj);
418 Evas_Object *sub = event_info;
419 if (!wd) return;
420
421 if (sub == wd->content)
422 {
423 evas_object_event_callback_del_full(sub,
424 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
425 _changed_size_hints, obj);
426 wd->content = NULL;
427 _sizing_eval(obj);
428 }
429}
430
431/* unused now - but meant to be for making sure the focused widget is always
432 * visible when the vkbd comes and goes by moving the conformant obj (and thus
433 * its children) to show the focused widget (and if focus changes follow)
434
435static Evas_Object *
436_focus_object_get(const Evas_Object *obj)
437{
438 Evas_Object *win, *foc;
439
440 win = elm_widget_top_get(obj);
441 if (!win) return NULL;
442 foc = elm_widget_top_get(win);
443}
444
445static void
446_focus_object_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
447{
448 evas_object_geometry_get(obj, x, y, w, h);
449}
450
451static void
452_focus_change_del(void *data, Evas_Object *obj, void *event_info)
453{
454 // called from toplevel when the focused window shanges
455}
456
457static void
458_autoscroll_move(Evas_Object *obj)
459{
460 // move conformant edje by delta to show focused widget
461}
462
463static void
464_autoscroll_mode_enable(Evas_Object *obj)
465{
466// called when autoscroll mode should be on - content area smaller than
467// its min size
468// 1. get focused object
469// 2. if not in visible conformant area calculate delta needed to
470// get it in
471// 3. store delta and call _autoscroll_move() which either asanimates
472// or jumps right there
473}
474
475static void
476_autoscroll_mode_disable(Evas_Object *obj)
477{
478// called when autoscroll mode should be off - set delta to 0 and
479// call _autoscroll_move()
480}
481 */
482
483static void
484_conformant_move_resize_event_cb(void *data __UNUSED__, Evas *e __UNUSED__,
485 Evas_Object *obj, void *event_info __UNUSED__)
486{
487 Conformant_Part_Type part_type;
488 Widget_Data *wd = elm_widget_data_get(obj);
489 if (!wd) return;
490
491 part_type = (ELM_CONFORM_INDICATOR_PART |
492 ELM_CONFORM_SOFTKEY_PART |
493 ELM_CONFORM_VIRTUAL_KEYPAD_PART |
494 ELM_CONFORM_CLIPBOARD_PART);
495 _conformant_part_sizing_eval(obj, part_type);
496}
497
498// showing the focused/important region.
499#ifdef HAVE_ELEMENTARY_X
500static void
501_content_resize_event_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj
502 __UNUSED__, void *event_info __UNUSED__)
503{
504 Evas_Object *conformant = (Evas_Object *)data;
505 Widget_Data *wd = elm_widget_data_get(conformant);
506 if (!wd) return;
507
508 if (wd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) return;
509
510 if (wd->show_region_job) ecore_job_del(wd->show_region_job);
511 wd->show_region_job = ecore_job_add(_show_region_job, conformant);
512}
513#endif
514
515static void
516_show_region_job(void *data)
517{
518 Evas_Object *focus_obj;
519 Evas_Object *conformant = (Evas_Object *)data;
520 Widget_Data *wd = elm_widget_data_get(conformant);
521 if (!wd) return;
522
523 focus_obj = elm_widget_focused_object_get(conformant);
524 if (focus_obj)
525 {
526 Evas_Coord x, y, w, h;
527
528 elm_widget_show_region_get(focus_obj, &x, &y, &w, &h);
529
530 if (h < _elm_config->finger_size)
531 h = _elm_config->finger_size;
532
533 elm_widget_show_region_set(focus_obj, x, y, w, h, EINA_TRUE);
534 }
535
536 wd->show_region_job = NULL;
537}
538
539#ifdef HAVE_ELEMENTARY_X
540static void
541_update_autoscroll_objs(void *data)
542{
543 const char *type;
544 int i;
545 Evas_Object *sub, *top_scroller = NULL;
546 Evas_Object *conformant = (Evas_Object *)data;
547 Widget_Data *wd = elm_widget_data_get(data);
548 if (!wd) return;
549
550 sub = elm_widget_focused_object_get(conformant);
551 //Look up for Top most scroller in the Focus Object hierarchy inside Conformant.
552
553 while (sub)
554 {
555 type = elm_widget_type_get(sub);
556 if (!strcmp(type, "conformant")) break;
557 for (i = 0; i < SUB_TYPE_COUNT; i++)
558 if (!strcmp(type, sub_type[i]))
559 {
560 top_scroller = sub;
561 break;
562 }
563 sub = elm_object_parent_widget_get(sub);
564 }
565
566 //If the scroller got changed by app, replace it.
567 if (top_scroller != wd->scroller)
568 {
569 if (wd->scroller) evas_object_event_callback_del(wd->scroller,
570 EVAS_CALLBACK_RESIZE,
571 _content_resize_event_cb);
572 wd->scroller = top_scroller;
573 if (wd->scroller) evas_object_event_callback_add(wd->scroller,
574 EVAS_CALLBACK_RESIZE,
575 _content_resize_event_cb,
576 data);
577 }
578}
579
580static Eina_Bool
581_prop_change(void *data, int type __UNUSED__, void *event)
582{
583 Ecore_X_Event_Window_Property *ev;
584 Widget_Data *wd = elm_widget_data_get(data);
585
586 if (!wd) return ECORE_CALLBACK_PASS_ON;
587 ev = event;
588 if (ev->atom == ECORE_X_ATOM_E_ILLUME_ZONE)
589 {
590 Conformant_Part_Type part_type;
591
592 part_type = (ELM_CONFORM_INDICATOR_PART |
593 ELM_CONFORM_SOFTKEY_PART |
594 ELM_CONFORM_VIRTUAL_KEYPAD_PART |
595 ELM_CONFORM_CLIPBOARD_PART);
596 _conformant_part_sizing_eval(data, part_type);
597 }
598 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_INDICATOR_GEOMETRY)
599 _conformant_part_sizing_eval(data, ELM_CONFORM_INDICATOR_PART);
600 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_SOFTKEY_GEOMETRY)
601 _conformant_part_sizing_eval(data, ELM_CONFORM_SOFTKEY_PART);
602 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_KEYBOARD_GEOMETRY)
603 _conformant_part_sizing_eval(data, ELM_CONFORM_VIRTUAL_KEYPAD_PART);
604 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_GEOMETRY)
605 _conformant_part_sizing_eval(data, ELM_CONFORM_CLIPBOARD_PART);
606 else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE)
607 {
608 Ecore_X_Window zone;
609
610 printf("Keyboard Geometry Changed\n");
611 zone = ecore_x_e_illume_zone_get(ev->win);
612 wd->vkb_state = ecore_x_e_virtual_keyboard_state_get(zone);
613 if (wd->vkb_state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF)
614 {
615 evas_object_size_hint_min_set(wd->virtualkeypad, -1, 0);
616 evas_object_size_hint_max_set(wd->virtualkeypad, -1, 0);
617 }
618 else
619 _update_autoscroll_objs(data);
620 }
621 else if (ev->atom == ECORE_X_ATOM_E_ILLUME_CLIPBOARD_STATE)
622 {
623 Ecore_X_Window zone;
624 Ecore_X_Illume_Clipboard_State state;
625
626 zone = ecore_x_e_illume_zone_get(ev->win);
627 state = ecore_x_e_illume_clipboard_state_get(zone);
628
629 if (state != ECORE_X_ILLUME_CLIPBOARD_STATE_ON)
630 {
631 evas_object_size_hint_min_set(wd->clipboard, -1, 0);
632 evas_object_size_hint_max_set(wd->clipboard, -1, 0);
633 }
634 else
635 _update_autoscroll_objs(data);
636 }
637
638 return ECORE_CALLBACK_PASS_ON;
639}
640#endif
641
642EAPI Evas_Object *
643elm_conformant_add(Evas_Object *parent)
644{
645 Evas_Object *obj;
646 Evas *e;
647 Widget_Data *wd;
648
649 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
650
651 ELM_SET_WIDTYPE(widtype, "conformant");
652 elm_widget_type_set(obj, "conformant");
653 elm_widget_sub_object_add(parent, obj);
654 elm_widget_data_set(obj, wd);
655 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
656 elm_widget_del_hook_set(obj, _del_hook);
657 elm_widget_theme_hook_set(obj, _theme_hook);
658 elm_widget_can_focus_set(obj, EINA_FALSE);
659 elm_widget_content_set_hook_set(obj, _content_set_hook);
660 elm_widget_content_get_hook_set(obj, _content_get_hook);
661 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
662
663 wd->base = edje_object_add(e);
664 _elm_theme_object_set(obj, wd->base, "conformant", "base", "default");
665 elm_widget_resize_object_set(obj, wd->base);
666
667 _swallow_conformant_parts(obj);
668
669#ifdef HAVE_ELEMENTARY_X
670 Evas_Object *top = elm_widget_top_get(obj);
671 Ecore_X_Window xwin = elm_win_xwindow_get(top);
672
673 if ((xwin) && (!elm_win_inlined_image_object_get(top)))
674 {
675 wd->prop_hdl = ecore_event_handler_add(ECORE_X_EVENT_WINDOW_PROPERTY,
676 _prop_change, obj);
677 wd->vkb_state = ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF;
678 }
679 // FIXME: get kbd region prop
680#endif
681
682 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
683 _conformant_move_resize_event_cb, obj);
684 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
685 _conformant_move_resize_event_cb, obj);
686
687 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
688
689 _mirrored_set(obj, elm_widget_mirrored_get(obj));
690 _sizing_eval(obj);
691 return obj;
692}
diff --git a/libraries/elementary/src/lib/elm_conform.h b/libraries/elementary/src/lib/elm_conform.h
new file mode 100644
index 0000000..3daf72a
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_conform.h
@@ -0,0 +1,49 @@
1/**
2 * @defgroup Conformant Conformant
3 * @ingroup Elementary
4 *
5 * @image html img/widget/conformant/preview-00.png
6 * @image latex img/widget/conformant/preview-00.eps width=\textwidth
7 *
8 * @image html img/conformant.png
9 * @image latex img/conformant.eps width=\textwidth
10 *
11 * The aim is to provide a widget that can be used in elementary apps to
12 * account for space taken up by the indicator, virtual keypad & softkey
13 * windows when running the illume2 module of E17.
14 *
15 * So conformant content will be sized and positioned considering the
16 * space required for such stuff, and when they popup, as a keyboard
17 * shows when an entry is selected, conformant content won't change.
18 *
19 * Available styles for it:
20 * - @c "default"
21 *
22 * Default content parts of the conformant widget that you can use for are:
23 * @li "default" - A content of the conformant
24 *
25 * See how to use this widget in this example:
26 * @ref conformant_example
27 */
28
29/**
30 * @addtogroup Conformant
31 * @{
32 */
33
34/**
35 * Add a new conformant widget to the given parent Elementary
36 * (container) object.
37 *
38 * @param parent The parent object.
39 * @return A new conformant widget handle or @c NULL, on errors.
40 *
41 * This function inserts a new conformant widget on the canvas.
42 *
43 * @ingroup Conformant
44 */
45EAPI Evas_Object *elm_conformant_add(Evas_Object *parent);
46
47/**
48 * @}
49 */
diff --git a/libraries/elementary/src/lib/elm_cursor.h b/libraries/elementary/src/lib/elm_cursor.h
new file mode 100644
index 0000000..84a404a
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_cursor.h
@@ -0,0 +1,122 @@
1/**
2 * @defgroup Cursors Cursors
3 * @ingroup Elementary
4 *
5 * The Elementary cursor is an internal smart object used to
6 * customize the mouse cursor displayed over objects (or
7 * widgets). In the most common scenario, the cursor decoration
8 * comes from the graphical @b engine Elementary is running
9 * on. Those engines may provide different decorations for cursors,
10 * and Elementary provides functions to choose them (think of X11
11 * cursors, as an example).
12 *
13 * By default, Elementary searches cursors only from engine.
14 * There's also the possibility of, besides using engine provided
15 * cursors, also use the ones coming from Edje theme files. Both
16 * globally and per widget, Elementary makes it possible for one to
17 * make the cursors lookup to be held on engines only or on
18 * Elementary's theme file, too. To set cursor's hot spot,
19 * two data items should be added to cursor's theme: "hot_x" and
20 * "hot_y", that are the offset from upper-left corner of the cursor
21 * (coordinates 0,0).
22 *
23 * @{
24 */
25
26/**
27 * Set the cursor to be shown when mouse is over the object
28 *
29 * Set the cursor that will be displayed when mouse is over the
30 * object. The object can have only one cursor set to it, so if
31 * this function is called twice for an object, the previous set
32 * will be unset.
33 * If using X cursors, a definition of all the valid cursor names
34 * is listed on Elementary_Cursors.h. If an invalid name is set
35 * the default cursor will be used.
36 *
37 * @param obj the object being set a cursor.
38 * @param cursor the cursor name to be used.
39 *
40 * @ingroup Cursors
41 */
42EAPI void elm_object_cursor_set(Evas_Object *obj, const char *cursor);
43
44/**
45 * Get the cursor to be shown when mouse is over the object
46 *
47 * @param obj an object with cursor already set.
48 * @return the cursor name.
49 *
50 * @ingroup Cursors
51 */
52EAPI const char *elm_object_cursor_get(const Evas_Object *obj);
53
54/**
55 * Unset cursor for object
56 *
57 * Unset cursor for object, and set the cursor to default if the mouse
58 * was over this object.
59 *
60 * @param obj Target object
61 * @see elm_object_cursor_set()
62 *
63 * @ingroup Cursors
64 */
65EAPI void elm_object_cursor_unset(Evas_Object *obj);
66
67/**
68 * Sets a different style for this object cursor.
69 *
70 * @note before you set a style you should define a cursor with
71 * elm_object_cursor_set()
72 *
73 * @param obj an object with cursor already set.
74 * @param style the theme style to use (default, transparent, ...)
75 *
76 * @ingroup Cursors
77 */
78EAPI void elm_object_cursor_style_set(Evas_Object *obj, const char *style);
79
80/**
81 * Get the style for this object cursor.
82 *
83 * @param obj an object with cursor already set.
84 * @return style the theme style in use, defaults to "default". If the
85 * object does not have a cursor set, then NULL is returned.
86 *
87 * @ingroup Cursors
88 */
89EAPI const char *elm_object_cursor_style_get(const Evas_Object *obj);
90
91/**
92 * Set if the cursor set should be searched on the theme or should use
93 * the provided by the engine, only.
94 *
95 * @note before you set engine_only you should define a cursor with
96 * elm_object_cursor_set(). By default it will only look for cursors
97 * provided by the engine.
98 *
99 * @param obj an object with cursor already set.
100 * @param theme_search boolean to define if cursors should be looked only
101 * between the provided by the engine or searched on widget's theme as well.
102 *
103 * @ingroup Cursors
104 */
105EAPI void elm_object_cursor_theme_search_enabled_set(Evas_Object *obj, Eina_Bool theme_search);
106
107/**
108 * Get the cursor engine only usage for this object cursor.
109 *
110 * @param obj an object with cursor already set.
111 * @return engine_only boolean to define it cursors should be
112 * looked only between the provided by the engine or searched on
113 * widget's theme as well. If the object does not have a cursor
114 * set, then EINA_FALSE is returned.
115 *
116 * @ingroup Cursors
117 */
118EAPI Eina_Bool elm_object_cursor_theme_search_enabled_get(const Evas_Object *obj);
119
120/**
121 * @}
122 */
diff --git a/libraries/elementary/src/lib/elm_datetime.c b/libraries/elementary/src/lib/elm_datetime.c
new file mode 100644
index 0000000..8736e8d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_datetime.c
@@ -0,0 +1,1075 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#ifdef HAVE_LOCALE_H
5# include <locale.h>
6#endif
7
8#ifdef HAVE_LANGINFO_H
9# include <langinfo.h>
10#endif
11
12typedef struct _Widget_Data Widget_Data;
13typedef struct _Datetime_Field Datetime_Field;
14typedef struct _Datetime_Mod_Api Datetime_Mod_Api;
15typedef struct _Format_Map Format_Map;
16
17#define DATETIME_TYPE_COUNT 6
18#define MAX_FORMAT_LEN 64
19#define MAX_SEPARATOR_LEN 6
20#define MAX_FIELD_FORMAT_LEN 3
21#define MIN_DAYS_IN_MONTH 28
22#define BUFFER_SIZE 1024
23
24// interface between EDC & C code. Field names & signal names.
25// values 0 to DATETIME_TYPE_COUNT are valid range, can be substituted for %d.
26#define EDC_DATETIME_ENABLE_SIG_STR "elm,state,enabled"
27#define EDC_DATETIME_DISABLE_SIG_STR "elm,state,disabled"
28#define EDC_DATETIME_FOCUSIN_SIG_STR "elm,action,focus"
29#define EDC_DATETIME_FOCUSOUT_SIG_STR "elm,action,unfocus"
30#define EDC_PART_FIELD_STR "field%d"
31#define EDC_PART_SEPARATOR_STR "separator%d"
32#define EDC_PART_FIELD_ENABLE_SIG_STR "field%d,enable"
33#define EDC_PART_FIELD_DISABLE_SIG_STR "field%d,disable"
34
35// struct tm does not define the fields in the order from year, month, date, hour, minute.
36// values are reassigned to an array for easy handling.
37#define DATETIME_TM_ARRAY(intptr, tmptr) int *intptr[] = {&(tmptr)->tm_year, \
38 &(tmptr)->tm_mon, &(tmptr)->tm_mday, &(tmptr)->tm_hour, &(tmptr)->tm_min}
39
40struct _Datetime_Field
41{
42 Evas_Object *item_obj;
43 char fmt[MAX_FIELD_FORMAT_LEN];
44 Elm_Datetime_Field_Type type;
45 const char *separator;
46 int location; // location of the field as per the current format
47 int min, max;
48 Eina_Bool fmt_exist:1; // whether field format is present or not
49 Eina_Bool visible:1; // whether field can be visible or not
50};
51
52struct _Datetime_Mod_Api
53{
54 Elm_Datetime_Module_Data *(*obj_hook) (Evas_Object *obj);
55 void (*obj_unhook) (Elm_Datetime_Module_Data *module_data);
56 Evas_Object *(*field_create) (Elm_Datetime_Module_Data *module_data,
57 Elm_Datetime_Field_Type field_type);
58 void (*field_value_display) (Elm_Datetime_Module_Data *module_data,
59 Evas_Object *obj);
60};
61
62struct _Widget_Data
63{
64 Evas_Object *base;
65 Datetime_Field field_list[DATETIME_TYPE_COUNT]; // fixed set of fields.
66 struct tm curr_time, min_limit, max_limit;
67 Elm_Datetime_Module_Data *mod_data;
68 char format[MAX_FORMAT_LEN];
69 Eina_Bool user_format:1; // whether user set format or default format.
70};
71
72struct _Format_Map
73{
74 char *fmt_char;
75 int def_min;
76 int def_max;
77 char *ignore_sep;
78};
79
80// default limits for individual fields
81static Format_Map mapping[DATETIME_TYPE_COUNT] = {
82 [ELM_DATETIME_YEAR] = { "Yy", -1, -1, "" },
83 [ELM_DATETIME_MONTH] = { "mbBh", 0, 11, "" },
84 [ELM_DATETIME_DATE] = { "de", 1, 31, "" },
85 [ELM_DATETIME_HOUR] = { "IHkl", 0, 23, "" },
86 [ELM_DATETIME_MINUTE] = { "M", 0, 59, ":" },
87 [ELM_DATETIME_AMPM] = { "pP", 0, 1, "" }
88};
89
90static const char *multifield_formats = "cxXrRTDF";
91static const char *ignore_separators = "()";
92
93static Datetime_Mod_Api *dt_mod = NULL;
94static const char *widtype = NULL;
95
96static void _del_hook(Evas_Object *obj);
97static void _disable_hook(Evas_Object *obj);
98static void _translate_hook(Evas_Object *obj);
99static void _on_focus_hook(void *data __UNUSED__, Evas_Object *obj);
100static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
101static void _sizing_eval(Evas_Object *obj);
102static void _theme_hook(Evas_Object *obj);
103static void _validate_datetime_limits(struct tm *time1, struct tm *time2, Eina_Bool swap);
104static void _apply_field_limits(Evas_Object *obj);
105static void _apply_range_restrictions(Evas_Object *obj, struct tm *time);
106static const char *_field_format_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type);
107static void _field_limit_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type,
108 int *range_min, int *range_max);
109static void _reload_format(Evas_Object *obj);
110static void _field_list_display(Evas_Object *obj);
111static void _field_list_arrange(Evas_Object *obj);
112static void _field_list_init(Evas_Object *obj);
113
114static const char SIG_CHANGED[] = "changed";
115static const char SIG_LANGUAGE_CHANGED[] = "language,changed";
116static const Evas_Smart_Cb_Description _signals[] = {
117 {SIG_CHANGED, ""},
118 {SIG_LANGUAGE_CHANGED, ""},
119 {NULL, NULL}
120};
121
122static Datetime_Mod_Api *
123_dt_mod_init()
124{
125 Elm_Module *mod = NULL;
126 if (!(mod = _elm_module_find_as("datetime/api"))) return NULL;
127
128 mod->api = malloc(sizeof(Datetime_Mod_Api));
129 if (!mod->api) return NULL;
130
131 ((Datetime_Mod_Api *)(mod->api))->obj_hook = _elm_module_symbol_get(mod, "obj_hook");
132 ((Datetime_Mod_Api *)(mod->api))->obj_unhook = _elm_module_symbol_get(mod, "obj_unhook");
133 ((Datetime_Mod_Api *)(mod->api))->field_create = _elm_module_symbol_get(mod, "field_create");
134 ((Datetime_Mod_Api *)(mod->api))->field_value_display = _elm_module_symbol_get(mod, "field_value_display");
135
136 return mod->api;
137}
138
139static void
140_del_hook(Evas_Object *obj)
141{
142 Widget_Data *wd;
143 Datetime_Field *tmp;
144 unsigned int idx;
145
146 wd = elm_widget_data_get(obj);
147 if (!wd) return;
148
149 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
150 {
151 tmp = wd->field_list + idx;
152 evas_object_del(tmp->item_obj);
153 eina_stringshare_del(tmp->separator);
154 }
155
156 if ((dt_mod) && (dt_mod->obj_unhook))
157 dt_mod->obj_unhook(wd->mod_data); // module - unhook
158
159 free(wd);
160}
161
162static void
163_disable_hook(Evas_Object *obj)
164{
165 Widget_Data *wd;
166
167 wd = elm_widget_data_get(obj);
168 if (!wd || !wd->base) return;
169 if (elm_widget_disabled_get(obj))
170 edje_object_signal_emit(wd->base, EDC_DATETIME_DISABLE_SIG_STR, "elm");
171 else
172 edje_object_signal_emit(wd->base, EDC_DATETIME_ENABLE_SIG_STR, "elm");
173}
174
175static void
176_translate_hook(Evas_Object *obj)
177{
178 Widget_Data *wd;
179 wd = elm_widget_data_get(obj);
180 if (!wd) return;
181
182 if (!wd->user_format) _reload_format(obj);
183 else _field_list_display(obj);
184 evas_object_smart_callback_call(obj, SIG_LANGUAGE_CHANGED, NULL);
185}
186
187static void
188_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
189{
190 Widget_Data *wd;
191
192 wd = elm_widget_data_get(obj);
193 if (!wd) return;
194
195 if (elm_widget_focus_get(obj))
196 edje_object_signal_emit(wd->base, EDC_DATETIME_FOCUSIN_SIG_STR, "elm");
197 else
198 edje_object_signal_emit(wd->base, EDC_DATETIME_FOCUSOUT_SIG_STR, "elm");
199}
200
201static Eina_List *
202_datetime_items_get(const Evas_Object *obj)
203{
204 Widget_Data *wd;
205 Eina_List *items = NULL;
206 Datetime_Field *field;
207 int loc, count = 0;
208 unsigned int idx;
209
210 wd = elm_widget_data_get(obj);
211 if (!wd) return NULL;
212
213 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
214 {
215 field = wd->field_list + idx;
216 if (field->fmt_exist && field->visible) count++;
217 }
218 for (loc = 0; loc < count; loc++)
219 {
220 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
221 {
222 field = wd->field_list + idx;
223 if (field->location == loc)
224 items = eina_list_append(items, field->item_obj);
225 }
226 }
227
228 return items;
229}
230
231static Eina_Bool
232_elm_datetime_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
233{
234 Widget_Data *wd;
235 const Eina_List *items;
236 void *(*list_data_get) (const Eina_List *list);
237 Eina_List *(*list_free) (Eina_List *list);
238 Eina_Bool ret;
239
240 wd = elm_widget_data_get(obj);
241 if (!wd) return EINA_FALSE;
242
243 if ((items = elm_widget_focus_custom_chain_get(obj)))
244 {
245 list_data_get = eina_list_data_get;
246 list_free = NULL;
247 }
248 else
249 {
250 items = _datetime_items_get(obj);
251 list_data_get = eina_list_data_get;
252 list_free = eina_list_free;
253 if (!items) return EINA_FALSE;
254 }
255
256 ret = elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
257 if (list_free) list_free((Eina_List *)items);
258
259 return ret;
260}
261
262static void
263_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
264{
265 Widget_Data *wd;
266
267 wd = elm_widget_data_get(obj);
268 if (!wd) return;
269
270 edje_object_mirrored_set(wd->base, rtl);
271}
272
273static void
274_sizing_eval(Evas_Object *obj)
275{
276 Widget_Data *wd;
277 Datetime_Field *field;
278 Evas_Coord minw = -1, minh = -1;
279 unsigned int idx, field_count = 0;
280
281 wd = elm_widget_data_get(obj);
282 if (!wd || !wd->base) return;
283 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
284 {
285 field = wd->field_list + idx;
286 if ((field->visible) && (field->fmt_exist)) field_count ++;
287 }
288 if (field_count)
289 elm_coords_finger_size_adjust(field_count, &minw, 1, &minh);
290 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
291 evas_object_size_hint_min_set(obj, minw, minh);
292 evas_object_size_hint_max_set(obj, -1, -1);
293}
294
295static void
296_theme_hook(Evas_Object *obj)
297{
298 Widget_Data *wd;
299 Datetime_Field *field;
300 char buf[BUFFER_SIZE];
301 unsigned int idx;
302
303 wd = elm_widget_data_get(obj);
304 if (!wd || !wd->base) return;
305
306 _elm_theme_object_set(obj, wd->base, "datetime", "base",
307 elm_widget_style_get(obj));
308 _elm_widget_mirrored_reload(obj);
309 _mirrored_set(obj, elm_widget_mirrored_get(obj));
310
311 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
312
313 if (elm_widget_disabled_get(obj))
314 edje_object_signal_emit(wd->base, EDC_DATETIME_DISABLE_SIG_STR,"elm");
315 else
316 edje_object_signal_emit(wd->base, EDC_DATETIME_ENABLE_SIG_STR, "elm");
317
318 if ((!dt_mod) || (!dt_mod->field_value_display)) return;
319
320 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
321 {
322 field = wd->field_list + idx;
323 if (field->fmt_exist && field->visible)
324 {
325 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR, field->location);
326 edje_object_signal_emit(wd->base, buf, "elm");
327 snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, field->location);
328 edje_object_part_text_escaped_set(wd->base, buf, field->separator);
329 dt_mod->field_value_display(wd->mod_data, field->item_obj);
330 }
331 else
332 {
333 snprintf(buf, sizeof(buf),EDC_PART_FIELD_DISABLE_SIG_STR, field->location);
334 edje_object_signal_emit(wd->base, buf, "elm");
335 }
336 }
337 edje_object_message_signal_process(wd->base);
338 _sizing_eval(obj);
339}
340
341static int
342_max_days_get(int year, int month)
343{
344 struct tm time1;
345 time_t t;
346 int day;
347
348 t = time(NULL);
349 localtime_r(&t, &time1);
350 time1.tm_year = year;
351 time1.tm_mon = month;
352 for (day = MIN_DAYS_IN_MONTH; day <= mapping[ELM_DATETIME_DATE].def_max; day++)
353 {
354 time1.tm_mday = day;
355 mktime(&time1);
356 if (time1.tm_mday == 1) break;
357 }
358 day --;
359 return day;
360}
361
362static Eina_Bool
363_date_cmp(struct tm *time1, struct tm *time2)
364{
365 unsigned int idx;
366 DATETIME_TM_ARRAY(timearr1, time1);
367 DATETIME_TM_ARRAY(timearr2, time2);
368
369 for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++)
370 {
371 if (*timearr1[idx] != *timearr2[idx])
372 return EINA_FALSE;
373 }
374 return EINA_TRUE;
375}
376
377// validates curr_time/min_limt/max_limit according to the newly set value
378static void
379_validate_datetime_limits(struct tm *time1, struct tm *time2, Eina_Bool swap)
380{
381 struct tm *t1, *t2;
382 unsigned int idx;
383 if (!time1 || !time2) return;
384
385 t1 = (swap) ? time2 : time1;
386 t2 = (swap) ? time1 : time2;
387
388 DATETIME_TM_ARRAY(timearr1, time1);
389 DATETIME_TM_ARRAY(timearr2, time2);
390 for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++)
391 {
392 if (*timearr1[idx] < *timearr2[idx])
393 {
394 memcpy(t1, t2, sizeof(struct tm));
395 break;
396 }
397 else if (*timearr1[idx] > *timearr2[idx])
398 break;
399 }
400}
401
402static void
403_apply_field_limits(Evas_Object *obj)
404{
405 Widget_Data *wd;
406 Datetime_Field *field;
407 int val;
408 unsigned int idx = 0;
409
410 wd = elm_widget_data_get(obj);
411 if (!wd) return;
412
413 DATETIME_TM_ARRAY(timearr, &wd->curr_time);
414 for (idx = 0; idx < DATETIME_TYPE_COUNT - 1; idx++)
415 {
416 field = wd->field_list + idx;
417 val = *timearr[idx];
418 if (val < field->min)
419 *timearr[idx] = field->min;
420 else if (val > field->max)
421 *timearr[idx] = field->max;
422 }
423 _field_list_display(obj);
424}
425
426static void
427_apply_range_restrictions(Evas_Object *obj, struct tm *tim)
428{
429 Widget_Data *wd;
430 unsigned int idx;
431 int val, min, max;
432
433 wd = elm_widget_data_get(obj);
434 if (!wd || !tim) return;
435
436 DATETIME_TM_ARRAY(timearr, tim);
437 for (idx = ELM_DATETIME_MONTH; idx < DATETIME_TYPE_COUNT - 1; idx++)
438 {
439 val = *timearr[idx];
440 min = mapping[idx].def_min;
441 max = mapping[idx].def_max;
442 if (idx == ELM_DATETIME_DATE)
443 max = _max_days_get(tim->tm_year, tim->tm_mon);
444 if (val < min)
445 *timearr[idx] = min;
446 else if (val > max)
447 *timearr[idx] = max;
448 }
449}
450
451static const char *
452_field_format_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type)
453{
454 Widget_Data *wd;
455 Datetime_Field *field;
456
457 wd = elm_widget_data_get(obj);
458 if (!wd) return NULL;
459
460 field = wd->field_list + field_type;
461 if (!field) return NULL;
462
463 return field->fmt;
464}
465
466static void
467_field_limit_get(Evas_Object * obj, Elm_Datetime_Field_Type field_type, int *range_min, int *range_max)
468{
469 Widget_Data *wd;
470 Datetime_Field *field;
471 int min, max, max_days;
472 unsigned int idx;
473
474 wd = elm_widget_data_get(obj);
475 if (!wd) return;
476
477 field = wd->field_list + field_type;
478 if (!field) return;
479
480 min = field->min;
481 max = field->max;
482
483 DATETIME_TM_ARRAY(curr_timearr, &wd->curr_time);
484 DATETIME_TM_ARRAY(min_timearr, &wd->min_limit);
485 DATETIME_TM_ARRAY(max_timearr, &wd->max_limit);
486
487 for (idx = 0; idx < field->type; idx++)
488 if (*curr_timearr[idx] > *min_timearr[idx]) break;
489 if ((idx == field_type) && (min < *min_timearr[field_type]))
490 min = *min_timearr[field_type];
491 if (field_type == ELM_DATETIME_DATE)
492 {
493 max_days = _max_days_get(wd->curr_time.tm_year, wd->curr_time.tm_mon);
494 if (max > max_days) max = max_days;
495 }
496 for (idx = 0; idx < field->type; idx++)
497 if (*curr_timearr[idx] < *max_timearr[idx]) break;
498 if ((idx == field_type) && (max > *max_timearr[field_type]))
499 max = *max_timearr[field_type];
500
501 *range_min = min;
502 *range_max = max;
503}
504
505static void
506_field_list_display(Evas_Object *obj)
507{
508 Widget_Data *wd;
509 Datetime_Field *field;
510 unsigned int idx= 0;
511
512 wd = elm_widget_data_get(obj);
513 if (!wd) return;
514
515 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
516 {
517 field = wd->field_list + idx;
518 if (field->fmt_exist && field->visible)
519 {
520 if ((dt_mod) && (dt_mod->field_value_display))
521 dt_mod->field_value_display(wd->mod_data, field->item_obj);
522 }
523 }
524}
525
526static void
527_field_list_arrange(Evas_Object *obj)
528{
529 Widget_Data *wd;
530 Datetime_Field *field;
531 char buf[BUFFER_SIZE];
532 int idx;
533
534 wd = elm_widget_data_get(obj);
535 if (!wd) return;
536
537 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
538 {
539 field = wd->field_list + idx;
540 edje_object_part_unswallow(wd->base, field->item_obj);
541 }
542 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
543 {
544 field = wd->field_list + idx;
545 if (field->visible && field->fmt_exist)
546 {
547 snprintf(buf, sizeof(buf), EDC_PART_FIELD_STR, field->location);
548 edje_object_part_swallow(wd->base, buf, field->item_obj);
549 }
550 else evas_object_hide(field->item_obj);
551 }
552 _sizing_eval(obj);
553 _field_list_display(obj);
554}
555
556// FIXME: provide nl_langinfo on Windows if possible
557// returns expanded format string for corresponding multi-field format character
558static char *
559_expanded_fmt_str_get(char ch)
560{
561 char *exp_fmt = "";
562 switch (ch)
563 {
564 case 'c':
565#ifdef HAVE_LANGINFO_H
566 exp_fmt = nl_langinfo(D_T_FMT);
567#else
568 exp_fmt = "";
569#endif
570 break;
571 case 'x':
572#ifdef HAVE_LANGINFO_H
573 exp_fmt = nl_langinfo(D_FMT);
574#else
575 exp_fmt = "";
576#endif
577 break;
578 case 'X':
579#ifdef HAVE_LANGINFO_H
580 exp_fmt = nl_langinfo(T_FMT);
581#else
582 exp_fmt = "";
583#endif
584 break;
585 case 'r':
586#ifdef HAVE_LANGINFO_H
587 exp_fmt = nl_langinfo(T_FMT_AMPM);
588#else
589 exp_fmt = "";
590#endif
591 break;
592 case 'R':
593 exp_fmt = "%H:%M";
594 break;
595 case 'T':
596 exp_fmt = "%H:%M:%S";
597 break;
598 case 'D':
599 exp_fmt = "%m/%d/%y";
600 break;
601 case 'F':
602 exp_fmt = "%Y-%m-%d";
603 break;
604 default:
605 exp_fmt = "";
606 break;
607 }
608 return exp_fmt;
609}
610
611static void
612_expand_format(char * dt_fmt)
613{
614 char *ptr, *expanded_fmt, ch;
615 char buf[MAX_FORMAT_LEN] = {0,};
616 unsigned int idx = 0, len = 0;
617 Eina_Bool fmt_char = EINA_FALSE;
618
619 ptr = dt_fmt;
620 while ((ch = *ptr))
621 {
622 if ((fmt_char) && (strchr(multifield_formats, ch)))
623 {
624 // replace the multi-field format characters with corresponding expanded format
625 expanded_fmt = _expanded_fmt_str_get(ch);
626 len = strlen(expanded_fmt);
627 buf[--idx] = 0;
628 strncat(buf, expanded_fmt, len);
629 idx += len;
630 }
631 else buf[idx++] = ch;
632 if (ch == '%') fmt_char = EINA_TRUE;
633 else fmt_char = EINA_FALSE;
634 ptr++;
635 }
636 buf[idx] = 0;
637 strncpy(dt_fmt, buf, MAX_FORMAT_LEN);
638}
639
640static unsigned int
641_parse_format(Evas_Object *obj, char *fmt_ptr)
642{
643 Widget_Data *wd;
644 Datetime_Field *field = NULL;
645 unsigned int len = 0, idx = 0, location = 0;
646 char separator[MAX_SEPARATOR_LEN];
647 char cur;
648 Eina_Bool fmt_parsing = EINA_FALSE, sep_parsing = EINA_FALSE,
649 sep_lookup = EINA_FALSE;
650
651 wd = elm_widget_data_get(obj);
652
653 while ((cur = *fmt_ptr))
654 {
655 if (fmt_parsing)
656 {
657 fmt_parsing = EINA_FALSE;
658 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
659 {
660 if (strchr(mapping[idx].fmt_char, cur))
661 {
662 field = wd->field_list + idx;
663 // ignore the fields already have or disabled
664 // valid formats, means already parsed & repeated, ignore.
665 if (!field->visible || field->location != -1) break;
666 field->fmt[1] = cur;
667 field->fmt_exist = EINA_TRUE;
668 field->location = location++;
669 sep_lookup = EINA_TRUE;
670 len = 0;
671 break;
672 }
673 }
674 }
675 if (cur == '%')
676 {
677 fmt_parsing = EINA_TRUE;
678 sep_parsing = EINA_FALSE;
679 // set the separator to previous field
680 separator[len] = 0;
681 if (field) eina_stringshare_replace(&field->separator, separator);
682 }
683
684 // ignore the set of chars (global, field specific) as field separators.
685 if (sep_parsing && (len < MAX_SEPARATOR_LEN - 1) &&
686 (field->type != ELM_DATETIME_AMPM) && (!strchr(ignore_separators, cur)) &&
687 (!strchr(mapping[idx].ignore_sep, cur)))
688 separator[len++] = cur;
689 if (sep_lookup) sep_parsing = EINA_TRUE;
690 sep_lookup = EINA_FALSE;
691 fmt_ptr++;
692 }
693 // return the number of valid fields parsed.
694 return location;
695}
696
697static void
698_reload_format(Evas_Object *obj)
699{
700 Widget_Data *wd;
701 Datetime_Field *field;
702 char buf[BUFFER_SIZE];
703 unsigned int idx, field_count;
704 char *dt_fmt;
705
706 wd = elm_widget_data_get(obj);
707 if (!wd) return;
708
709 // FIXME: provide nl_langinfo on Windows if possible
710 // fetch the default format from Libc.
711 if (!wd->user_format)
712#ifdef HAVE_LANGINFO_H
713 strncpy(wd->format, nl_langinfo(D_T_FMT), MAX_FORMAT_LEN);
714#else
715 strncpy(wd->format, "", MAX_FORMAT_LEN);
716#endif
717
718 dt_fmt = (char *)malloc(MAX_FORMAT_LEN);
719 if (!dt_fmt) return;
720 strncpy(dt_fmt, wd->format, MAX_FORMAT_LEN);
721
722 _expand_format(dt_fmt);
723
724 // reset all the fields to disable state
725 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
726 {
727 field = wd->field_list + idx;
728 field->fmt_exist = EINA_FALSE;
729 field->location = -1;
730 }
731
732 field_count = _parse_format(obj, dt_fmt);
733 free(dt_fmt);
734
735 // assign locations to disabled fields for uniform usage
736 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
737 {
738 field = wd->field_list + idx;
739 if (field->location == -1) field->location = field_count++;
740
741 if (field->fmt_exist && field->visible)
742 {
743 snprintf(buf, sizeof(buf), EDC_PART_FIELD_ENABLE_SIG_STR,
744 field->location);
745 edje_object_signal_emit(wd->base, buf, "elm");
746 }
747 else
748 {
749 snprintf(buf, sizeof(buf),EDC_PART_FIELD_DISABLE_SIG_STR,
750 field->location);
751 edje_object_signal_emit(wd->base, buf, "elm");
752 }
753 snprintf(buf, sizeof(buf), EDC_PART_SEPARATOR_STR, (field->location + 1));
754 edje_object_part_text_escaped_set(wd->base, buf, field->separator);
755 }
756 edje_object_message_signal_process(wd->base);
757 _field_list_arrange(obj);
758}
759
760static void
761_field_list_init(Evas_Object *obj)
762{
763 Widget_Data *wd;
764 Datetime_Field *field;
765 unsigned int idx;
766 time_t t;
767
768 wd = elm_widget_data_get(obj);
769 if (!wd) return;
770
771 t = time(NULL);
772 localtime_r(&t, &wd->curr_time);
773
774 mapping[ELM_DATETIME_YEAR].def_min = _elm_config->year_min;
775 mapping[ELM_DATETIME_YEAR].def_max = _elm_config->year_max;
776 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
777 {
778 field = wd->field_list + idx;
779 field->type = ELM_DATETIME_YEAR + idx;
780 field->fmt[0] = '%';
781 field->fmt_exist = EINA_FALSE;
782 field->visible = EINA_TRUE;
783 field->min = mapping[idx].def_min;
784 field->max = mapping[idx].def_max;
785 }
786 DATETIME_TM_ARRAY(min_timearr, &wd->min_limit);
787 DATETIME_TM_ARRAY(max_timearr, &wd->max_limit);
788 for (idx = 0; idx < DATETIME_TYPE_COUNT-1; idx++)
789 {
790 *min_timearr[idx] = mapping[idx].def_min;
791 *max_timearr[idx] = mapping[idx].def_max;
792 }
793}
794
795EAPI Evas_Object *
796elm_datetime_add(Evas_Object *parent)
797{
798 Evas_Object *obj;
799 Evas *e;
800 Widget_Data *wd;
801 Datetime_Field *field;
802 int idx;
803
804 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
805
806 ELM_SET_WIDTYPE(widtype, "datetime");
807 elm_widget_type_set(obj, widtype);
808 elm_widget_sub_object_add(parent, obj);
809 elm_widget_data_set(obj, wd);
810 elm_widget_del_hook_set(obj, _del_hook);
811 elm_widget_theme_hook_set(obj, _theme_hook);
812 elm_widget_translate_hook_set(obj, _translate_hook);
813 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
814 elm_widget_disable_hook_set(obj, _disable_hook);
815 elm_widget_can_focus_set(obj, EINA_TRUE);
816 elm_widget_focus_next_hook_set(obj, _elm_datetime_focus_next_hook);
817
818 wd->base = edje_object_add(e);
819 elm_widget_resize_object_set(obj, wd->base);
820 _elm_theme_object_set(obj, wd->base, "datetime", "base", "default");
821 evas_object_smart_callbacks_descriptions_set(obj, _signals);
822
823 // module - initialise module for datetime
824 if (!dt_mod) dt_mod = _dt_mod_init();
825 if ((dt_mod) && (dt_mod->obj_hook))
826 wd->mod_data = dt_mod->obj_hook(obj);
827 // update module data
828 if (wd->mod_data)
829 {
830 wd->mod_data->base = obj;
831 wd->mod_data->field_limit_get = _field_limit_get;
832 wd->mod_data->field_format_get = _field_format_get;
833 }
834
835 _field_list_init(obj);
836 _reload_format(obj);
837
838 if ((dt_mod)&&(dt_mod->field_create))
839 {
840 for (idx = 0; idx < DATETIME_TYPE_COUNT; idx++)
841 {
842 field = wd->field_list + idx;
843 field->item_obj = dt_mod->field_create(wd->mod_data, idx);
844 }
845 }
846 _field_list_arrange(obj);
847 _mirrored_set(obj, elm_widget_mirrored_get(obj));
848
849 return obj;
850}
851
852EAPI const char *
853elm_datetime_format_get(const Evas_Object *obj)
854{
855 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
856 Widget_Data *wd;
857
858 wd = elm_widget_data_get(obj);
859 if (!wd) return NULL;
860
861 return wd->format;
862}
863
864EAPI void
865elm_datetime_format_set(Evas_Object *obj, const char *fmt)
866{
867 ELM_CHECK_WIDTYPE(obj, widtype);
868 Widget_Data *wd;
869
870 wd = elm_widget_data_get(obj);
871 if (!wd) return;
872
873 if (fmt)
874 {
875 strncpy(wd->format, fmt, MAX_FORMAT_LEN);
876 wd->user_format = EINA_TRUE;
877 }
878 else
879 wd->user_format = EINA_FALSE;
880
881 _reload_format(obj);
882}
883
884EAPI Eina_Bool
885elm_datetime_field_visible_get(const Evas_Object *obj, Elm_Datetime_Field_Type
886 fieldtype)
887{
888 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
889 Widget_Data *wd;
890 Datetime_Field *field;
891
892 wd = elm_widget_data_get(obj);
893 if (!wd || (fieldtype > ELM_DATETIME_AMPM)) return EINA_FALSE;
894
895 field = wd->field_list + fieldtype;
896 return field->visible;
897}
898
899EAPI void
900elm_datetime_field_visible_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype,
901 Eina_Bool visible)
902{
903 ELM_CHECK_WIDTYPE(obj, widtype);
904 Widget_Data *wd;
905 Datetime_Field *field;
906
907 wd = elm_widget_data_get(obj);
908 if (!wd || (fieldtype > ELM_DATETIME_AMPM)) return;
909
910 field = wd->field_list + fieldtype;
911 if (field->visible == visible) return;
912
913 field->visible = visible;
914 _reload_format(obj);
915}
916
917EAPI void
918elm_datetime_field_limit_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype,
919 int *min, int *max)
920{
921 ELM_CHECK_WIDTYPE(obj, widtype);
922 Widget_Data *wd;
923 Datetime_Field *field;
924
925 wd = elm_widget_data_get(obj);
926 if (!wd || (fieldtype >= ELM_DATETIME_AMPM)) return;
927
928 field = wd->field_list + fieldtype;
929 if (min) *min = field->min;
930 if (max) *max = field->max;
931}
932
933EAPI void
934elm_datetime_field_limit_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype,
935 int min, int max)
936{
937 ELM_CHECK_WIDTYPE(obj, widtype);
938 Widget_Data *wd;
939 Datetime_Field *field;
940
941 wd = elm_widget_data_get(obj);
942 if (!wd || (fieldtype >= ELM_DATETIME_AMPM)) return;
943
944 if (min > max) return;
945
946 field = wd->field_list + fieldtype;
947 if ((min > mapping[fieldtype].def_min && min < mapping[fieldtype].def_max)
948 || (field->type == ELM_DATETIME_YEAR))
949 field->min = min;
950 if ((max > mapping[fieldtype].def_min && max < mapping[fieldtype].def_max)
951 || (field->type == ELM_DATETIME_YEAR))
952 field->max = max;
953
954 _apply_field_limits(obj);
955}
956
957EAPI Eina_Bool
958elm_datetime_value_get(const Evas_Object *obj, struct tm *currtime)
959{
960 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
961 EINA_SAFETY_ON_NULL_RETURN_VAL(currtime, EINA_FALSE);
962 Widget_Data *wd;
963
964 wd = elm_widget_data_get(obj);
965 if (!wd) return EINA_FALSE;
966
967 *currtime = wd->curr_time;
968 return EINA_TRUE;
969}
970
971EAPI Eina_Bool
972elm_datetime_value_set(Evas_Object *obj, const struct tm *newtime)
973{
974 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
975 EINA_SAFETY_ON_NULL_RETURN_VAL(newtime, EINA_FALSE);
976 Widget_Data *wd;
977 struct tm old_time;
978
979 wd = elm_widget_data_get(obj);
980 if (!wd) return EINA_FALSE;
981
982 old_time = wd->curr_time;
983 wd->curr_time = *newtime;
984 // apply default field restrictions for curr_time
985 _apply_range_restrictions(obj, &wd->curr_time);
986 // validate the curr_time according to the min_limt and max_limt
987 _validate_datetime_limits(&wd->curr_time, &wd->min_limit, EINA_FALSE);
988 _validate_datetime_limits(&wd->max_limit, &wd->curr_time, EINA_TRUE);
989 _apply_field_limits(obj);
990
991 if (!_date_cmp(&old_time, &wd->curr_time))
992 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
993
994 return EINA_TRUE;
995}
996
997EAPI Eina_Bool
998elm_datetime_value_min_get(const Evas_Object *obj, struct tm *mintime)
999{
1000 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1001 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
1002 Widget_Data *wd;
1003
1004 wd = elm_widget_data_get(obj);
1005 if (!wd) return EINA_FALSE;
1006
1007 *mintime = wd->min_limit;
1008 return EINA_TRUE;
1009}
1010
1011EAPI Eina_Bool
1012elm_datetime_value_min_set(Evas_Object *obj, const struct tm *mintime)
1013{
1014 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1015 EINA_SAFETY_ON_NULL_RETURN_VAL(mintime, EINA_FALSE);
1016 Widget_Data *wd;
1017 struct tm old_time;
1018
1019 wd = elm_widget_data_get(obj);
1020 if (!wd) return EINA_FALSE;
1021
1022 wd->min_limit = *mintime;
1023 old_time = wd->curr_time;
1024 // apply default field restrictions for min_limit
1025 _apply_range_restrictions(obj, &wd->min_limit);
1026 // validate curr_time and max_limt according to the min_limit
1027 _validate_datetime_limits(&wd->max_limit, &wd->min_limit, EINA_FALSE);
1028 _validate_datetime_limits(&wd->curr_time, &wd->min_limit, EINA_FALSE);
1029 _apply_field_limits(obj);
1030
1031 if (!_date_cmp(&old_time, &wd->curr_time))
1032 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
1033
1034 return EINA_TRUE;
1035}
1036
1037EAPI Eina_Bool
1038elm_datetime_value_max_get(const Evas_Object *obj, struct tm *maxtime)
1039{
1040 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1041 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1042 Widget_Data *wd;
1043
1044 wd = elm_widget_data_get(obj);
1045 if (!wd) return EINA_FALSE;
1046
1047 *maxtime = wd->max_limit;
1048 return EINA_TRUE;
1049}
1050
1051EAPI Eina_Bool
1052elm_datetime_value_max_set(Evas_Object *obj, const struct tm *maxtime)
1053{
1054 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1055 EINA_SAFETY_ON_NULL_RETURN_VAL(maxtime, EINA_FALSE);
1056 Widget_Data *wd;
1057 struct tm old_time;
1058
1059 wd = elm_widget_data_get(obj);
1060 if (!wd) return EINA_FALSE;
1061
1062 wd->max_limit = *maxtime;
1063 old_time = wd->curr_time;
1064 // apply default field restrictions for max_limit
1065 _apply_range_restrictions(obj, &wd->max_limit);
1066 // validate curr_time and min_limt according to the max_limit
1067 _validate_datetime_limits(&wd->max_limit, &wd->min_limit, EINA_TRUE);
1068 _validate_datetime_limits(&wd->max_limit, &wd->curr_time, EINA_TRUE);
1069 _apply_field_limits(obj);
1070
1071 if (!_date_cmp(&old_time, &wd->curr_time))
1072 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
1073
1074 return EINA_TRUE;
1075}
diff --git a/libraries/elementary/src/lib/elm_datetime.h b/libraries/elementary/src/lib/elm_datetime.h
new file mode 100644
index 0000000..36785cb
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_datetime.h
@@ -0,0 +1,592 @@
1/**
2 * @defgroup Datetime Datetime
3 * @ingroup Elementary
4 *
5 *
6 * @image html img/widget/datetime/preview-00.png
7 * @image latex img/widget/datetime/preview-00.eps
8 *
9 * @image html img/widget/datetime/preview-01.png
10 * @image latex img/widget/datetime/preview-01.eps
11 *
12 * @image html img/widget/datetime/preview-02.png
13 * @image latex img/widget/datetime/preview-02.eps
14 *
15 * Datetime widget is used to display and input date & time values.
16 * This widget displays date and time as per the <b>system's locale</b> settings (Date
17 * includes Day, Month & Year along with the defined separators and
18 * Time includes Hour, Minute & AM/PM fields. Separator for AM/PM field is ignored.
19 *
20 * The corresponding Month, AM/PM strings are displayed according to the
21 * system’s language settings.
22 *
23 * Datetime format is a combination of LIBC standard characters like
24 * “%%d %%b %%Y %%I : %%M %%p” which, as a whole represents both Date as well as Time
25 * format.
26 *
27 * Elm_datetime supports only the following sub set of libc date format specifiers:
28 *
29 * @b %%Y : The year as a decimal number including the century (example: 2011).
30 *
31 * @b %%y : The year as a decimal number without a century (range 00 to 99)
32 *
33 * @b %%m : The month as a decimal number (range 01 to 12).
34 *
35 * @b %%b : The abbreviated month name according to the current locale.
36 *
37 * @b %%B : The full month name according to the current locale.
38 *
39 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
40 *
41 * @b %%d : The day of the month as a decimal number (range 01 to 31).
42 *
43 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
44 * digits are preceded by a blank.
45 *
46 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
47 *
48 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
49 *
50 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
51 * digits are preceded by a blank.
52 *
53 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
54 * digits are preceded by a blank.
55 *
56 * @b %%M : The minute as a decimal number (range 00 to 59).
57 *
58 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
59 * corresponding strings for the current locale. Noon is treated as 'PM'
60 * and midnight as 'AM'
61 *
62 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
63 * the current locale.
64 *
65 * @b %%c : The preferred date and time representation for the current locale.
66 *
67 * @b %%x : The preferred date representation for the current locale without the time.
68 *
69 * @b %%X : The preferred time representation for the current locale without the date.
70 *
71 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
72 *
73 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
74 *
75 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
76 *
77 * @b %%D : The date using the format %%m/%%d/%%y.
78 *
79 * @b %%F : The date using the format %%Y-%%m-%%d.
80 *
81 * (For more reference on the available <b>LIBC date format specifiers</b>, please
82 * visit the link:
83 * http://www.gnu.org/s/hello/manual/libc.html#Formatting-Calendar-Time )
84 *
85 * Datetime widget can provide Unicode @b separators in between its fields
86 * except for AM/PM field.
87 * A separator can be any <b>Unicode character</b> other than the LIBC standard
88 * date format specifiers.( Example: In the format %%b %%d @b , %%y %%H @b : %%M
89 * comma(,) is separator for date field %%d and colon(:) is separator for
90 * hour field %%H ).
91 *
92 * The default format is a predefined one, based on the system Locale.
93 *
94 * Hour format 12hr(1-12) or 24hr(0-23) display can be selected by setting
95 * the corresponding user format.
96 *
97 * Datetime supports six fields: Year, Month, Date, Hour, Minute, AM/PM.
98 * Depending on the Datetime module that is loaded, the user can see
99 * different UI to select the individual field values.
100 *
101 * The individual fields of Datetime can be arranged in any order according to the format
102 * set by application.
103 *
104 * There is a provision to set the visibility of a particular field as TRUE/ FALSE
105 * so that <b>only time/ only date / only required fields</b> will be displayed.
106 *
107 * Each field is having a default minimum and maximum values just like the daily
108 * calendar information. These min/max values can be modified as per the application usage.
109 *
110 * User can enter the values only in between the range of maximum and minimum.
111 * Apart from these APIs, there is a provision to display only a limited set of
112 * values out of the possible values. APIs to select the individual field limits
113 * are intended for this purpose.
114 *
115 * The whole widget is left aligned and its size grows horizontally depending
116 * on the current format and each field's visible/disabled state.
117 *
118 * Datetime individual field selection is implemented in a modular style.
119 * Module can be implemented as a Ctxpopup based selection or an ISE based
120 * selection or even a spinner like selection etc.
121 *
122 * <b>Datetime Module design:</b>
123 *
124 * The following functions are expected to be implemented in a Datetime module:
125 *
126 * <b>Field creation:</b>
127 * <pre>
128 *
129 * __________ __________
130 * | |----- obj_hook() ---------------------->>>| |
131 * | |<<<----------------returns Mod_data ------| |
132 * | Datetime |_______ | |
133 * | widget | |Assign module call backs | Module |
134 * | base |<<<____| | |
135 * | | | |
136 * | |----- field_create() ------------------>>>| |
137 * |__________|<<<----------------returns field_obj -----|__________|
138 *
139 * </pre>
140 *
141 * <b>Field value setting:</b>
142 * <pre>
143 *
144 * __________ __________
145 * | | | |
146 * | Datetime |<<<----------elm_datetime_value_set()---| |
147 * | widget | | Module |
148 * | base |----display_field_value()------------>>>| |
149 * |__________| |__________|
150 *
151 * </pre>
152 *
153 * <b>del_hook:</b>
154 * <pre>
155 * __________ __________
156 * | | | |
157 * | Datetime |----obj_unhook()-------------------->>>>| |
158 * | widget | | Module |
159 * | base | <<<-----frees mod_data---------| |
160 * |__________| |__________|
161 *
162 * </pre>
163 *
164 *
165 * Any module can use the following shared functions that are implemented in elm_datetime.c :
166 *
167 * <b>field_format_get()</b> - gives the field format.
168 *
169 * <b>field_limit_get()</b> - gives the field minimum, maximum limits.
170 *
171 * To enable a module, set the ELM_MODULES environment variable as shown:
172 *
173 * <b>export ELM_MODULES="datetime_input_ctxpopup>datetime/api"</b>
174 *
175 *
176 * Datetime widgets emits the following signals:
177 *
178 * @li @b "changed" - whenever Datetime field value is changed, this signal is sent.
179 *
180 * @li @b "language,changed" - whenever system locale changes, this signal is sent.
181 *
182 * Here is an example on its usage:
183 * @li @ref datetime_example
184 *
185 */
186
187/**
188 * @addtogroup Datetime
189 * @{
190 */
191
192/**
193 * Identifies a Datetime field, The widget supports 6 fields : Year, month,
194 * Date, Hour, Minute, AM/PM
195 *
196 */
197typedef enum _Elm_Datetime_Field_Type
198{
199 ELM_DATETIME_YEAR = 0, /**< Indicates Year field */
200 ELM_DATETIME_MONTH = 1, /**< Indicates Month field */
201 ELM_DATETIME_DATE = 2, /**< Indicates Date field */
202 ELM_DATETIME_HOUR = 3, /**< Indicates Hour field */
203 ELM_DATETIME_MINUTE = 4, /**< Indicates Minute field */
204 ELM_DATETIME_AMPM = 5, /**< Indicates AM/PM field */
205} Elm_Datetime_Field_Type;
206
207/**
208 * @brief Adds a new datetime Widget
209 *
210 * The default datetime format and corresponding strings are based on current locale.
211 *
212 * @param parent The parent object
213 * @return The new object or NULL if it cannot be created
214 *
215 * This function inserts a new datetime widget on the canvas.
216 *
217 * @ingroup Datetime
218 */
219EAPI Evas_Object *elm_datetime_add(Evas_Object *parent);
220
221/**
222 * Get the datetime format. Format is a combination of allowed Libc date format
223 * specifiers like: "%b %d, %Y %I : %M %p".
224 *
225 * Maximum allowed format length is 64 chars.
226 *
227 * Format can include separators for each individual datetime field except
228 * for AM/PM field.
229 *
230 * Each separator can be a maximum of 6 UTF-8 bytes.
231 * Space is also taken as a separator.
232 *
233 * Following are the allowed set of format specifiers for each datetime field.
234 *
235 * @b %%Y : The year as a decimal number including the century.
236 *
237 * @b %%y : The year as a decimal number without a century (range 00 to 99).
238 *
239 * @b %%m : The month as a decimal number (range 01 to 12).
240 *
241 * @b %%b : The abbreviated month name according to the current locale.
242 *
243 * @b %%B : The full month name according to the current locale.
244 *
245 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
246 *
247 * @b %%d : The day of the month as a decimal number (range 01 to 31).
248 *
249 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
250 * digits are preceded by a blank.
251 *
252 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
253 *
254 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
255 *
256 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
257 * digits are preceded by a blank.
258 *
259 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
260 * digits are preceded by a blank.
261 *
262 * @b %%M : The minute as a decimal number (range 00 to 59).
263 *
264 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
265 * corresponding strings for the current locale. Noon is treated as 'PM'
266 * and midnight as 'AM'.
267 *
268 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
269 * the current locale.
270 *
271 * @b %%c : The preferred date and time representation for the current locale.
272 *
273 * @b %%x : The preferred date representation for the current locale without the time.
274 *
275 * @b %%X : The preferred time representation for the current locale without the date.
276 *
277 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
278 *
279 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
280 *
281 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
282 *
283 * @b %%D : The date using the format %%m/%%d/%%y.
284 *
285 * @b %%F : The date using the format %%Y-%%m-%%d.
286 *
287 * These specifiers can be arranged in any order and the widget will display the
288 * fields accordingly.
289 *
290 * Default format is taken as per the system locale settings.
291 *
292 * @param obj The datetime object
293 * @return The datetime format string. Example: "%b %d, %Y %I : %M %p"
294 *
295 * @see elm_datetime_format_set()
296 * @ingroup Datetime
297 */
298 EAPI const char *elm_datetime_format_get(const Evas_Object *obj);
299
300/**
301 * Set the datetime format. Format is a combination of allowed Libc date format
302 * specifiers like: "%b %d, %Y %I : %M %p".
303 *
304 * Maximum allowed format length is 64 chars.
305 *
306 * Format can include separators for each individual datetime field except
307 * for AM/PM field.
308 *
309 * Each separator can be a maximum of 6 UTF-8 bytes.
310 * Space is also taken as a separator.
311 *
312 * Following are the allowed set of format specifiers for each datetime field.
313 *
314 * @b %%Y : The year as a decimal number including the century.
315 *
316 * @b %%y : The year as a decimal number without a century (range 00 to 99).
317 *
318 * @b %%m : The month as a decimal number (range 01 to 12).
319 *
320 * @b %%b : The abbreviated month name according to the current locale.
321 *
322 * @b %%B : The full month name according to the current locale.
323 *
324 * @b %%h : The abbreviated month name according to the current locale(same as %%b).
325 *
326 * @b %%d : The day of the month as a decimal number (range 01 to 31).
327 *
328 * @b %%e : The day of the month as a decimal number (range 1 to 31). single
329 * digits are preceded by a blank.
330 *
331 * @b %%I : The hour as a decimal number using a 12-hour clock (range 01 to 12).
332 *
333 * @b %%H : The hour as a decimal number using a 24-hour clock (range 00 to 23).
334 *
335 * @b %%k : The hour (24-hour clock) as a decimal number (range 0 to 23). single
336 * digits are preceded by a blank.
337 *
338 * @b %%l : The hour (12-hour clock) as a decimal number (range 1 to 12); single
339 * digits are preceded by a blank.
340 *
341 * @b %%M : The minute as a decimal number (range 00 to 59).
342 *
343 * @b %%p : Either 'AM' or 'PM' according to the given time value, or the
344 * corresponding strings for the current locale. Noon is treated as 'PM'
345 * and midnight as 'AM'.
346 *
347 * @b %%P : Like %p but in lower case: 'am' or 'pm' or a corresponding string for
348 * the current locale.
349 *
350 * @b %%c : The preferred date and time representation for the current locale.
351 *
352 * @b %%x : The preferred date representation for the current locale without the time.
353 *
354 * @b %%X : The preferred time representation for the current locale without the date.
355 *
356 * @b %%r : The complete calendar time using the AM/PM format of the current locale.
357 *
358 * @b %%R : The hour and minute in decimal numbers using the format %H:%M.
359 *
360 * @b %%T : The time of day in decimal numbers using the format %H:%M:%S.
361 *
362 * @b %%D : The date using the format %%m/%%d/%%y.
363 *
364 * @b %%F : The date using the format %%Y-%%m-%%d.
365 *
366 * These specifiers can be arranged in any order and the widget will display the
367 * fields accordingly.
368 *
369 * Default format is taken as per the system locale settings.
370 *
371 * @param obj The datetime object
372 * @param fmt The datetime format
373 *
374 * @see elm_datetime_format_get()
375 * @ingroup Datetime
376 */
377EAPI void elm_datetime_format_set(Evas_Object *obj, const char *fmt);
378
379/**
380 * @brief Get the upper boundary of a field.
381 *
382 * Year: years since 1900. Negative value represents year below 1900 (year
383 * value -30 represents 1870). Year default range is from 70 to 137.
384 *
385 * Month: default value range is from 0 to 11.
386 *
387 * Date: default value range is from 1 to 31 according to the month value.
388 *
389 * Hour: default value will be in terms of 24 hr format (0~23)
390 *
391 * Minute: default value range is from 0 to 59.
392 *
393 * @param obj The datetime object
394 * @param maxtime Time structure containing the maximum time value.
395 * @return int The maximum value of the field.
396 *
397 * @see elm_datetime_value_max_set()
398 * @ingroup Datetime
399 */
400EAPI Eina_Bool elm_datetime_value_max_get(const Evas_Object *obj, struct tm *maxtime);
401
402/**
403 * @brief Set the upper boundary of a field.
404 *
405 * Year: years since 1900. Negative value represents year below 1900 (year
406 * value -30 represents 1870). Year default range is from 70 to 137.
407 *
408 * Month: default value range is from 0 to 11.
409 *
410 * Date: default value range is from 1 to 31 according to the month value.
411 *
412 * Hour: default value will be in terms of 24 hr format (0~23)
413 *
414 * Minute: default value range is from 0 to 59.
415 *
416 * @param obj The datetime object
417 * @param maxtime Time structure containing the maximum time value.
418 * @return EINA_TRUE if maximum value is accepted.
419 *
420 * @see elm_datetime_value_max_get()
421 * @ingroup Datetime
422 */
423EAPI Eina_Bool elm_datetime_value_max_set(Evas_Object *obj, const struct tm *maxtime);
424
425/**
426 * @brief Get the lower boundary of a field.
427 *
428 * Year: years since 1900. Negative value represents year below 1900 (year
429 * value -30 represents 1870). Year default range is from 70 to 137.
430 *
431 * Month: default value range is from 0 to 11.
432 *
433 * Date: default value range is from 1 to 31 according to the month value.
434 *
435 * Hour: default value will be in terms of 24 hr format (0~23)
436 *
437 * Minute: default value range is from 0 to 59.
438 *
439 * @param obj The datetime object
440 * @param mintime Time structure.
441 * @return EINA_TRUE if minimum value is successfully returned.
442 *
443 * @see elm_datetime_value_min_set()
444 * @ingroup Datepicker
445 */
446EAPI Eina_Bool elm_datetime_value_min_get(const Evas_Object *obj, struct tm *mintime);
447
448/**
449 * @brief Set the lower boundary of a field.
450 *
451 * Year: years since 1900. Negative value represents year below 1900 (year
452 * value -30 represents 1870). Year default range is from 70 to 137.
453 *
454 * Month: default value range is from 0 to 11.
455 *
456 * Date: default value range is from 1 to 31 according to the month value.
457 *
458 * Hour: default value will be in terms of 24 hr format (0~23)
459 *
460 * Minute: default value range is from 0 to 59.
461 *
462 * @param obj The datetime object.
463 * @param mintime Time structure containing the minimum time value.
464 * @return EINA_TRUE if minimum value is accepted.
465 *
466 * @see elm_datetime_value_min_get()
467 * @ingroup Datetime
468 */
469EAPI Eina_Bool elm_datetime_value_min_set(Evas_Object *obj, const struct tm *mintime);
470
471/**
472 * @brief Get the field limits of a field.
473 *
474 * Limits can be set to individual fields, independently, except for AM/PM field.
475 * Any field can display the values only in between these Minimum and Maximum limits unless
476 * the corresponding time value is restricted from MinTime to MaxTime.
477 * That is, Min/ Max field limits always works under the limitations of MinTime/ MaxTime.
478 *
479 * There is no provision to set the limits of AM/PM field.
480 *
481 * @param obj The datetime object
482 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc.
483 * @param min Reference to field's minimum value
484 * @param max Reference to field's maximum value
485 *
486 * @see elm_datetime_field_limit_set()
487 * @ingroup Datetime
488 */
489EAPI void elm_datetime_field_limit_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, int *min, int *max);
490
491/**
492 * @brief Set the field limits of a field.
493 *
494 * Limits can be set to individual fields, independently, except for AM/PM field.
495 * Any field can display the values only in between these Minimum and Maximum limits unless
496 * the corresponding time value is restricted from MinTime to MaxTime.
497 * That is, Min/ Max field limits always works under the limitations of MinTime/ MaxTime.
498 *
499 * There is no provision to set the limits of AM/PM field.
500 *
501 * @param obj The datetime object
502 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc.
503 * @param min Reference to field's minimum value
504 * @param max Reference to field's maximum value
505 *
506 * @see elm_datetime_field_limit_set()
507 * @ingroup Datetime
508 */
509EAPI void elm_datetime_field_limit_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, int min, int max);
510
511/**
512 * @brief Get the current value of a field.
513 *
514 * Year: years since 1900. Negative value represents year below 1900 (year
515 * value -30 represents 1870). Year default range is from 70 to 137.
516 *
517 * Month: default value range is from 0 to 11.
518 *
519 * Date: default value range is from 1 to 31 according to the month value.
520 *
521 * Hour: default value will be in terms of 24 hr format (0~23)
522 *
523 * Minute: default value range is from 0 to 59.
524 *
525 * @param obj The datetime object.
526 * @param currtime Time structure.
527 * @return EINA_TRUE if current time is returned successfully.
528 *
529 * @see elm_datetime_field_value_set()
530 * @ingroup Datetime
531 */
532EAPI Eina_Bool elm_datetime_value_get(const Evas_Object *obj, struct tm *currtime);
533
534/**
535 * @brief Set the current value of a Datetime object.
536 *
537 * Year: years since 1900. Negative value represents year below 1900 (year
538 * value -30 represents 1870). Year default range is from 70 to 137.
539 *
540 * Month: default value range is from 0 to 11.
541 *
542 * Date: default value range is from 1 to 31 according to the month value.
543 *
544 * Hour: default value will be in terms of 24 hr format (0~23)
545 *
546 * Minute: default value range is from 0 to 59.
547 *
548 *
549 * @param obj The datetime object.
550 * @param newtime Time structure filled with values to be set.
551 * @return EINA_TRUE if current time is set successfully.
552 *
553 * @see elm_datetime_value_set()
554 * @ingroup Datetime
555 */
556EAPI Eina_Bool elm_datetime_value_set(Evas_Object *obj, const struct tm *newtime);
557
558/**
559 * @brief Get whether a field can be visible/not
560 *
561 * @param obj The datetime object
562 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc
563 * @return bool @c EINA_TRUE, if field can be visible. @c EINA_FALSE otherwise.
564 *
565 * @see elm_datetime_field_visible_set()
566 * @ingroup Datetime
567 */
568EAPI Eina_Bool elm_datetime_field_visible_get(const Evas_Object *obj, Elm_Datetime_Field_Type fieldtype);
569
570/**
571 * @brief Set a field to be visible or not.
572 * Setting this API True does not ensure that the field is visible, apart from
573 * this, the field's format must be present in Datetime overall format.
574 * If a field's visibility is set to False then it won't appear even though
575 * its format is present in overall format.
576 * So if and only if this API is set true and the corresponding field's format
577 * is present in Datetime format, the field is visible.
578 *
579 * By default the field visibility is set to True.
580 *
581 * @param obj The datetime object
582 * @param fieldtype Type of the field. ELM_DATETIME_YEAR etc.
583 * @param visible @c EINA_TRUE field can be visible, @c EINA_FALSE otherwise.
584 *
585 * @see elm_datetime_field_visible_get()
586 * @ingroup Datetime
587 */
588EAPI void elm_datetime_field_visible_set(Evas_Object *obj, Elm_Datetime_Field_Type fieldtype, Eina_Bool visible);
589
590/**
591 * @}
592 */
diff --git a/libraries/elementary/src/lib/elm_debug.h b/libraries/elementary/src/lib/elm_debug.h
new file mode 100644
index 0000000..f5de943
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_debug.h
@@ -0,0 +1,28 @@
1/**
2 * @defgroup Debug Debug
3 * @ingroup Elementary
4 * Don't use it unless you are sure.
5 *
6 * @{
7 */
8
9/**
10 * Print Tree object hierarchy in stdout
11 *
12 * @param top The root object
13 * @ingroup Debug
14 */
15EAPI void elm_object_tree_dump(const Evas_Object *top);
16
17/**
18 * Print Elm Objects tree hierarchy in file as dot(graphviz) syntax.
19 *
20 * @param top The root object
21 * @param file The path of output file
22 * @ingroup Debug
23 */
24EAPI void elm_object_tree_dot_dump(const Evas_Object *top, const char *file);
25
26/**
27 * @}
28 */
diff --git a/libraries/elementary/src/lib/elm_deprecated.h b/libraries/elementary/src/lib/elm_deprecated.h
new file mode 100644
index 0000000..49f88c2
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_deprecated.h
@@ -0,0 +1,423 @@
1
2EINA_DEPRECATED EAPI Evas_Object *elm_scrolled_entry_add(Evas_Object *parent);
3EINA_DEPRECATED EAPI void elm_scrolled_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line);
4EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_single_line_get(const Evas_Object *obj);
5EINA_DEPRECATED EAPI void elm_scrolled_entry_password_set(Evas_Object *obj, Eina_Bool password);
6EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_password_get(const Evas_Object *obj);
7EINA_DEPRECATED EAPI void elm_scrolled_entry_entry_set(Evas_Object *obj, const char *entry);
8EINA_DEPRECATED EAPI const char *elm_scrolled_entry_entry_get(const Evas_Object *obj);
9EINA_DEPRECATED EAPI void elm_scrolled_entry_entry_append(Evas_Object *obj, const char *entry);
10EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_is_empty(const Evas_Object *obj);
11EINA_DEPRECATED EAPI const char *elm_scrolled_entry_selection_get(const Evas_Object *obj);
12EINA_DEPRECATED EAPI void elm_scrolled_entry_entry_insert(Evas_Object *obj, const char *entry);
13EINA_DEPRECATED EAPI void elm_scrolled_entry_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap);
14EINA_DEPRECATED EAPI void elm_scrolled_entry_editable_set(Evas_Object *obj, Eina_Bool editable);
15EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_editable_get(const Evas_Object *obj);
16EINA_DEPRECATED EAPI void elm_scrolled_entry_select_none(Evas_Object *obj);
17EINA_DEPRECATED EAPI void elm_scrolled_entry_select_all(Evas_Object *obj);
18EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cursor_next(Evas_Object *obj);
19EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cursor_prev(Evas_Object *obj);
20EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cursor_up(Evas_Object *obj);
21EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cursor_down(Evas_Object *obj);
22EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_begin_set(Evas_Object *obj);
23EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_end_set(Evas_Object *obj);
24EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_line_begin_set(Evas_Object *obj);
25EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_line_end_set(Evas_Object *obj);
26EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_selection_begin(Evas_Object *obj);
27EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_selection_end(Evas_Object *obj);
28EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cursor_is_format_get(const Evas_Object *obj);
29EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cursor_is_visible_format_get(const Evas_Object *obj);
30EINA_DEPRECATED EAPI const char *elm_scrolled_entry_cursor_content_get(const Evas_Object *obj);
31EINA_DEPRECATED EAPI void elm_scrolled_entry_cursor_pos_set(Evas_Object *obj, int pos);
32EINA_DEPRECATED EAPI int elm_scrolled_entry_cursor_pos_get(const Evas_Object *obj);
33EINA_DEPRECATED EAPI void elm_scrolled_entry_selection_cut(Evas_Object *obj);
34EINA_DEPRECATED EAPI void elm_scrolled_entry_selection_copy(Evas_Object *obj);
35EINA_DEPRECATED EAPI void elm_scrolled_entry_selection_paste(Evas_Object *obj);
36EINA_DEPRECATED EAPI void elm_scrolled_entry_context_menu_clear(Evas_Object *obj);
37EINA_DEPRECATED 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);
38EINA_DEPRECATED EAPI void elm_scrolled_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled);
39EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_context_menu_disabled_get(const Evas_Object *obj);
40EINA_DEPRECATED EAPI void elm_scrolled_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v);
41EINA_DEPRECATED EAPI void elm_scrolled_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
42EINA_DEPRECATED EAPI void elm_scrolled_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
43EINA_DEPRECATED EAPI void elm_scrolled_entry_icon_set(Evas_Object *obj, Evas_Object *icon);
44EINA_DEPRECATED EAPI Evas_Object *elm_scrolled_entry_icon_get(const Evas_Object *obj);
45EINA_DEPRECATED EAPI Evas_Object *elm_scrolled_entry_icon_unset(Evas_Object *obj);
46EINA_DEPRECATED EAPI void elm_scrolled_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting);
47EINA_DEPRECATED EAPI void elm_scrolled_entry_end_set(Evas_Object *obj, Evas_Object *end);
48EINA_DEPRECATED EAPI Evas_Object *elm_scrolled_entry_end_get(const Evas_Object *obj);
49EINA_DEPRECATED EAPI Evas_Object *elm_scrolled_entry_end_unset(Evas_Object *obj);
50EINA_DEPRECATED EAPI void elm_scrolled_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting);
51EINA_DEPRECATED EAPI void elm_scrolled_entry_item_provider_append(Evas_Object *obj, Evas_Object * (*func)(void *data, Evas_Object * entry, const char *item), void *data);
52EINA_DEPRECATED EAPI void elm_scrolled_entry_item_provider_prepend(Evas_Object *obj, Evas_Object * (*func)(void *data, Evas_Object * entry, const char *item), void *data);
53EINA_DEPRECATED EAPI void elm_scrolled_entry_item_provider_remove(Evas_Object *obj, Evas_Object * (*func)(void *data, Evas_Object * entry, const char *item), void *data);
54EINA_DEPRECATED EAPI void elm_scrolled_entry_text_filter_append(Evas_Object *obj, void (*func)(void *data, Evas_Object *entry, char **text), void *data);
55EINA_DEPRECATED EAPI void elm_scrolled_entry_text_filter_prepend(Evas_Object *obj, void (*func)(void *data, Evas_Object *entry, char **text), void *data);
56EINA_DEPRECATED EAPI void elm_scrolled_entry_text_filter_remove(Evas_Object *obj, void (*func)(void *data, Evas_Object *entry, char **text), void *data);
57EINA_DEPRECATED EAPI void elm_scrolled_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format);
58EINA_DEPRECATED EAPI void elm_scrolled_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format);
59EINA_DEPRECATED EAPI void elm_scrolled_entry_file_save(Evas_Object *obj);
60EINA_DEPRECATED EAPI void elm_scrolled_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave);
61EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_autosave_get(const Evas_Object *obj);
62EINA_DEPRECATED EAPI void elm_scrolled_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly);
63EINA_DEPRECATED EAPI Eina_Bool elm_scrolled_entry_cnp_textonly_get(Evas_Object *obj);
64
65/**
66 * Convert a pixel coordinate (x,y) into a geographic coordinate
67 * (longitude, latitude).
68 *
69 * @param obj The map object.
70 * @param x the coordinate.
71 * @param y the coordinate.
72 * @param size the size in pixels of the map.
73 * The map is a square and generally his size is : pow(2.0, zoom)*256.
74 * @param lon Pointer to store the longitude that correspond to x.
75 * @param lat Pointer to store the latitude that correspond to y.
76 *
77 * @note Origin pixel point is the top left corner of the viewport.
78 * Map zoom and size are taken on account.
79 *
80 * @see elm_map_utils_convert_geo_into_coord() if you need the inverse.
81 *
82 * @deprecated Use elm_map_canvas_to_geo_convert() instead
83 */
84EINA_DEPRECATED EAPI void elm_map_utils_convert_coord_into_geo(const Evas_Object *obj, int x, int y, int size, double *lon, double *lat);
85
86/**
87 * Convert a geographic coordinate (longitude, latitude) into a pixel
88 * coordinate (x, y).
89 *
90 * @param obj The map object.
91 * @param lon the longitude.
92 * @param lat the latitude.
93 * @param size the size in pixels of the map. The map is a square
94 * and generally his size is : pow(2.0, zoom)*256.
95 * @param x Pointer to store the horizontal pixel coordinate that
96 * correspond to the longitude.
97 * @param y Pointer to store the vertical pixel coordinate that
98 * correspond to the latitude.
99 *
100 * @note Origin pixel point is the top left corner of the viewport.
101 * Map zoom and size are taken on account.
102 *
103 * @see elm_map_utils_convert_coord_into_geo() if you need the inverse.
104 *
105 * @deprecatedUse Use elm_map_canvas_to_geo_convert() instead
106 */
107EINA_DEPRECATED EAPI void elm_map_utils_convert_geo_into_coord(const Evas_Object *obj, double lon, double lat, int size, int *x, int *y);
108
109/**
110 * Get the information of downloading status.
111 *
112 * @param obj The map object.
113 * @param try_num Pointer to store number of tiles being downloaded.
114 * @param finish_num Pointer to store number of tiles successfully
115 * downloaded.
116 *
117 * This gets the current downloading status for the map object, the number
118 * of tiles being downloaded and the number of tiles already downloaded.
119 *
120 * @deprecatedUse Use elm_map_tile_load_status_get() instead
121 */
122EINA_DEPRECATED EAPI void elm_map_utils_downloading_status_get(const Evas_Object *obj, int *try_num, int *finish_num);
123
124/**
125 * Convert a geographic coordinate (longitude, latitude) into a name
126 * (address).
127 *
128 * @param obj The map object.
129 * @param lon the longitude.
130 * @param lat the latitude.
131 * @return name A #Elm_Map_Name handle for this coordinate.
132 *
133 * To get the string for this address, elm_map_name_address_get()
134 * should be used.
135 *
136 * @see elm_map_utils_convert_name_into_coord() if you need the inverse.
137 * @deprecatedUse Use elm_map_name_add() instead
138 *
139 */
140EINA_DEPRECATED EAPI Elm_Map_Name *elm_map_utils_convert_coord_into_name(const Evas_Object *obj, double lon, double lat);
141
142/**
143 * Convert a name (address) into a geographic coordinate
144 * (longitude, latitude).
145 *
146 * @param obj The map object.
147 * @param address The address.
148 * @return name A #Elm_Map_Name handle for this address.
149 *
150 * To get the longitude and latitude, elm_map_name_region_get()
151 * should be used.
152 *
153 * @see elm_map_utils_convert_coord_into_name() if you need the inverse.
154 * @deprecatedUse Use elm_map_name_geo_request() instead
155 *
156 */
157EINA_DEPRECATED EAPI Elm_Map_Name *elm_map_utils_convert_name_into_coord(const Evas_Object *obj, char *address);
158
159/**
160 * Add a new marker to the map object.
161 *
162 * @param obj The map object.
163 * @param lon The longitude of the marker.
164 * @param lat The latitude of the marker.
165 * @param clas The class, to use when marker @b isn't grouped to others.
166 * @param clas_group The class group, to use when marker is grouped to others
167 * @param data The data passed to the callbacks.
168 *
169 * @return The created marker or @c NULL upon failure.
170 *
171 * A marker will be created and shown in a specific point of the map, defined
172 * by @p lon and @p lat.
173 *
174 * It will be displayed using style defined by @p class when this marker
175 * is displayed alone (not grouped). A new class can be created with
176 * elm_map_marker_class_new().
177 *
178 * If the marker is grouped to other markers, it will be displayed with
179 * style defined by @p class_group. Markers with the same group are grouped
180 * if they are close. A new group class can be created with
181 * elm_map_marker_group_class_new().
182 *
183 * Markers created with this method can be deleted with
184 * elm_map_marker_remove().
185 *
186 * A marker can have associated content to be displayed by a bubble,
187 * when a user click over it, as well as an icon. These objects will
188 * be fetch using class' callback functions.
189 *
190 * @see elm_map_marker_class_new()
191 * @see elm_map_marker_group_class_new()
192 * @see elm_map_marker_remove()
193 *
194 * @deprecated Use Elm_Map_Overlay instead
195 */
196EINA_DEPRECATED 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);
197
198/**
199 * Remove a marker from the map.
200 *
201 * @param marker The marker to remove.
202 *
203 * @see elm_map_marker_add()
204 *
205 * @deprecated Use Elm_Map_Overlay instead
206 */
207EINA_DEPRECATED EAPI void elm_map_marker_remove(Elm_Map_Marker *marker);
208
209/**
210 * Get the current coordinates of the marker.
211 *
212 * @param marker marker.
213 * @param lat Pointer to store the marker's latitude.
214 * @param lon Pointer to store the marker's longitude.
215 *
216 * These values are set when adding markers, with function
217 * elm_map_marker_add().
218 *
219 * @see elm_map_marker_add()
220 *
221 * @deprecated Use Elm_Map_Overlay instead
222 */
223EINA_DEPRECATED EAPI void elm_map_marker_region_get(const Elm_Map_Marker *marker, double *lon, double *lat);
224
225/**
226 * Animatedly bring in given marker to the center of the map.
227 *
228 * @param marker The marker to center at.
229 *
230 * This causes map to jump to the given @p marker's coordinates
231 * and show it (by scrolling) in the center of the viewport, if it is not
232 * already centered. This will use animation to do so and take a period
233 * of time to complete.
234 *
235 * @see elm_map_marker_show() for a function to avoid animation.
236 * @see elm_map_marker_region_get()
237 *
238 * @deprecated Use Elm_Map_Overlay instead
239 */
240EINA_DEPRECATED EAPI void elm_map_marker_bring_in(Elm_Map_Marker *marker);
241
242/**
243 * Show the given marker at the center of the map, @b immediately.
244 *
245 * @param marker The marker to center at.
246 *
247 * This causes map to @b redraw its viewport's contents to the
248 * region containing the given @p marker's coordinates, that will be
249 * moved to the center of the map.
250 *
251 * @see elm_map_marker_bring_in() for a function to move with animation.
252 * @see elm_map_markers_list_show() if more than one marker need to be
253 * displayed.
254 * @see elm_map_marker_region_get()
255 *
256 * @deprecated Use Elm_Map_Overlay instead
257 */
258EINA_DEPRECATED EAPI void elm_map_marker_show(Elm_Map_Marker *marker);
259
260/**
261 * Move and zoom the map to display a list of markers.
262 *
263 * @param markers A list of #Elm_Map_Marker handles.
264 *
265 * The map will be centered on the center point of the markers in the list.
266 * Then the map will be zoomed in order to fit the markers using the maximum
267 * zoom which allows display of all the markers.
268 *
269 * @warning All the markers should belong to the same map object.
270 *
271 * @see elm_map_marker_show() to show a single marker.
272 * @see elm_map_marker_bring_in()
273 *
274 * @deprecated Use Elm_Map_Overlay instead
275 */
276EINA_DEPRECATED EAPI void elm_map_markers_list_show(Eina_List *markers);
277
278/**
279 * Get the Evas object returned by the Elm_Map_Marker_Get_Func callback
280 *
281 * @param marker The marker which content should be returned.
282 * @return Return the evas object if it exists, else @c NULL.
283 *
284 * To set callback function #Elm_Map_Marker_Get_Func for the marker class,
285 * elm_map_marker_class_get_cb_set() should be used.
286 *
287 * This content is what will be inside the bubble that will be displayed
288 * when an user clicks over the marker.
289 *
290 * This returns the actual Evas object used to be placed inside
291 * the bubble. This may be @c NULL, as it may
292 * not have been created or may have been deleted, at any time, by
293 * the map. <b>Do not modify this object</b> (move, resize,
294 * show, hide, etc.), as the map is controlling it. This
295 * function is for querying, emitting custom signals or hooking
296 * lower level callbacks for events on that object. Do not delete
297 * this object under any circumstances.
298 *
299 * @deprecated Use Elm_Map_Overlay instead
300 */
301EINA_DEPRECATED EAPI Evas_Object *elm_map_marker_object_get(const Elm_Map_Marker *marker);
302
303/**
304 * Update the marker
305 *
306 * @param marker The marker to be updated.
307 *
308 * If a content is set to this marker, it will call function to delete it,
309 * #Elm_Map_Marker_Del_Func, and then will fetch the content again with
310 * #Elm_Map_Marker_Get_Func.
311 *
312 * These functions are set for the marker class with
313 * elm_map_marker_class_get_cb_set() and elm_map_marker_class_del_cb_set().
314 *
315 * @deprecated Use Elm_Map_Overlay instead
316 */
317EINA_DEPRECATED EAPI void elm_map_marker_update(Elm_Map_Marker *marker);
318
319/**
320 * Create a new group class.
321 *
322 * @param obj The map object.
323 * @return Returns the new group class.
324 *
325 * Each marker must be associated to a group class. Markers in the same
326 * group are grouped if they are close.
327 *
328 * The group class defines the style of the marker when a marker is grouped
329 * to others markers. When it is alone, another class will be used.
330 *
331 * A group class will need to be provided when creating a marker with
332 * elm_map_marker_add().
333 *
334 * Some properties and functions can be set by class, as:
335 * - style, with elm_map_group_class_style_set()
336 * - data - to be associated to the group class. It can be set using
337 * elm_map_group_class_data_set().
338 * - min zoom to display markers, set with
339 * elm_map_group_class_zoom_displayed_set().
340 * - max zoom to group markers, set using
341 * elm_map_group_class_zoom_grouped_set().
342 * - visibility - set if markers will be visible or not, set with
343 * elm_map_group_class_hide_set().
344 * - #Elm_Map_Group_Icon_Get_Func - used to fetch icon for markers group classes.
345 * It can be set using elm_map_group_class_icon_cb_set().
346 *
347 * @see elm_map_marker_add()
348 * @see elm_map_group_class_style_set()
349 * @see elm_map_group_class_data_set()
350 * @see elm_map_group_class_zoom_displayed_set()
351 * @see elm_map_group_class_zoom_grouped_set()
352 * @see elm_map_group_class_hide_set()
353 * @see elm_map_group_class_icon_cb_set()
354 *
355 * @deprecated Use Elm_Map_Overlay instead
356 */
357EINA_DEPRECATED EAPI Elm_Map_Group_Class *elm_map_group_class_new(Evas_Object *obj);
358
359/**
360 * Create a new marker class.
361 *
362 * @param obj The map object.
363 * @return Returns the new group class.
364 *
365 * Each marker must be associated to a class.
366 *
367 * The marker class defines the style of the marker when a marker is
368 * displayed alone, i.e., not grouped to to others markers. When grouped
369 * it will use group class style.
370 *
371 * A marker class will need to be provided when creating a marker with
372 * elm_map_marker_add().
373 *
374 * Some properties and functions can be set by class, as:
375 * - style, with elm_map_marker_class_style_set()
376 * - #Elm_Map_Marker_Icon_Get_Func - used to fetch icon for markers classes.
377 * It can be set using elm_map_marker_class_icon_cb_set().
378 * - #Elm_Map_Marker_Get_Func - used to fetch bubble content for marker classes.
379 * Set using elm_map_marker_class_get_cb_set().
380 * - #Elm_Map_Marker_Del_Func - used to delete bubble content for marker classes.
381 * Set using elm_map_marker_class_del_cb_set().
382 *
383 * @see elm_map_marker_add()
384 * @see elm_map_marker_class_style_set()
385 * @see elm_map_marker_class_icon_cb_set()
386 * @see elm_map_marker_class_get_cb_set()
387 * @see elm_map_marker_class_del_cb_set()
388 *
389 * @deprecated Use Elm_Map_Overlay instead
390 */
391EINA_DEPRECATED EAPI Elm_Map_Marker_Class *elm_map_marker_class_new(Evas_Object *obj);
392
393/**
394 * Remove a route from the map.
395 *
396 * @param route The route to remove.
397 *
398 * @see elm_map_route_add()
399 * @deprecated Use elm_map_route_del() instead
400 *
401 */
402EINA_DEPRECATED EAPI void elm_map_route_remove(Elm_Map_Route *route);
403
404/**
405 * @deprecated Use elm_object_item_data_get instead.
406 */
407EINA_DEPRECATED EAPI void * elm_multibuttonentry_item_data_get(const Elm_Object_Item *it);
408
409/**
410 * @deprecated Use elm_object_item_data_set instead.
411 */
412EINA_DEPRECATED EAPI void elm_multibuttonentry_item_data_set(Elm_Object_Item *it, void *data);
413
414/**
415 * @deprecated Use elm_calendar_select_mode_set instead.
416 */
417EINA_DEPRECATED EAPI void elm_calendar_day_selection_disabled_set(Evas_Object *obj, Eina_Bool disabled);
418
419/**
420 * @deprecated Use elm_calendar_select_mode_get instead.
421 */
422EINA_DEPRECATED EAPI Eina_Bool elm_calendar_day_selection_disabled_get(const Evas_Object *obj);
423
diff --git a/libraries/elementary/src/lib/elm_diskselector.c b/libraries/elementary/src/lib/elm_diskselector.c
new file mode 100644
index 0000000..8334d37
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_diskselector.c
@@ -0,0 +1,1401 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4
5#ifndef MAX
6# define MAX(a, b) (((a) > (b)) ? (a) : (b))
7#endif
8
9#ifndef CEIL
10#define CEIL(a) (((a) % 2 != 0) ? ((a) / 2 + 1) : ((a) / 2))
11#endif
12
13#define DISPLAY_ITEM_NUM_MIN 3
14
15typedef struct _Widget_Data Widget_Data;
16typedef struct _Elm_Diskselector_Item Elm_Diskselector_Item;
17
18struct _Widget_Data
19{
20 Evas_Object *self;
21 Evas_Object *scroller;
22 Evas_Object *main_box;
23 Evas_Object *left_blank;
24 Evas_Object *right_blank;
25 Elm_Diskselector_Item *selected_item;
26 Elm_Diskselector_Item *first;
27 Elm_Diskselector_Item *second;
28 Elm_Diskselector_Item *s_last;
29 Elm_Diskselector_Item *last;
30 Eina_List *items;
31 Eina_List *r_items;
32 Eina_List *over_items;
33 Eina_List *under_items;
34 int item_count, len_threshold, len_side, display_item_num;
35 Ecore_Idle_Enterer *idler;
36 Ecore_Idle_Enterer *check_idler;
37 Evas_Coord minw, minh;
38 Eina_Bool init:1;
39 Eina_Bool round:1;
40 Eina_Bool display_item_num_by_api:1;
41};
42
43struct _Elm_Diskselector_Item
44{
45 ELM_WIDGET_ITEM;
46 Eina_List *node;
47 Evas_Object *icon;
48 const char *label;
49 Evas_Smart_Cb func;
50};
51
52static const char *widtype = NULL;
53
54static Eina_Bool _move_scroller(void *data);
55static void _del_hook(Evas_Object * obj);
56static void _del_pre_hook(Evas_Object * obj);
57static void _sizing_eval(Evas_Object * obj);
58static void _theme_hook(Evas_Object * obj);
59static void _on_focus_hook(void *data, Evas_Object *obj);
60static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info);
61static void _sub_del(void *data, Evas_Object * obj, void *event_info);
62static void _round_items_del(Widget_Data *wd);
63static void _scroller_move_cb(void *data, Evas_Object *obj, void *event_info);
64static void _item_click_cb(void *data, Evas_Object *obj __UNUSED__,
65 const char *emission __UNUSED__,
66 const char *source __UNUSED__);
67static void _selected_item_indicate(Elm_Diskselector_Item *it);
68static void _item_text_set_hook(Elm_Object_Item *it,
69 const char *part,
70 const char *label);
71static const char * _item_text_get_hook(const Elm_Object_Item *it,
72 const char *part);
73static void _item_content_set_hook(Elm_Object_Item *it,
74 const char *part,
75 Evas_Object *content);
76static Evas_Object * _item_content_get_hook(const Elm_Object_Item *it,
77 const char *part);
78
79static const char SIG_SELECTED[] = "selected";
80static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
81static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
82static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
83static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
84
85static const Evas_Smart_Cb_Description _signals[] = {
86 {SIG_SELECTED, ""},
87 {SIG_SCROLL_ANIM_START, ""},
88 {SIG_SCROLL_ANIM_STOP, ""},
89 {SIG_SCROLL_DRAG_START, ""},
90 {SIG_SCROLL_DRAG_STOP, ""},
91 {NULL, NULL}
92};
93
94static void
95_diskselector_object_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
96{
97 Widget_Data *wd;
98 Evas_Coord w, h;
99
100 wd = elm_widget_data_get(data);
101 if (!wd) return;
102
103 if ((wd->minw == -1) && (wd->minh == -1))
104 elm_coords_finger_size_adjust(6, &wd->minw, 1, &wd->minh);
105 edje_object_size_min_restricted_calc
106 (elm_smart_scroller_edje_object_get
107 (wd->scroller), &wd->minw, &wd->minh, wd->minw, wd->minh);
108 evas_object_size_hint_min_set(obj, wd->minw, wd->minh);
109 evas_object_size_hint_max_set(obj, -1, -1);
110
111 evas_object_geometry_get(wd->scroller, NULL, NULL, &w, &h);
112 if (wd->round)
113 evas_object_resize(wd->main_box, (w / wd->display_item_num) * (wd->item_count + (CEIL(wd->display_item_num) * 2)), h);
114 else
115 evas_object_resize(wd->main_box, (w / wd->display_item_num) * (wd->item_count + CEIL(wd->display_item_num)), h);
116
117 elm_smart_scroller_paging_set(wd->scroller, 0, 0,
118 (int)(w / wd->display_item_num), 0);
119
120 if (!wd->idler)
121 wd->idler = ecore_idle_enterer_before_add(_move_scroller, data);
122}
123
124static void
125_item_del(Elm_Diskselector_Item *item)
126{
127 if (!item) return;
128 eina_stringshare_del(item->label);
129 if (item->icon)
130 evas_object_del(item->icon);
131}
132
133static int
134_count_letter(const char *str)
135{
136 int pos = 0;
137 int code = 0, chnum;
138
139 for (chnum = 0; ; chnum++)
140 {
141 pos = evas_string_char_next_get(str, pos, &code);
142 if (code == 0) break;
143 }
144 return chnum;
145}
146
147static int
148_check_letter(const char *str, int length)
149{
150 int pos = 0;
151 int code = 0, chnum;
152
153 for (chnum = 0; ; chnum++)
154 {
155 if (chnum == length) break;
156 pos = evas_string_char_next_get(str, pos, &code);
157 if (code == 0) break;
158 }
159 return pos;
160}
161
162static Eina_Bool
163_check_string(void *data)
164{
165 int mid, steps, length, diff;
166 Elm_Diskselector_Item *it;
167 Eina_List *list, *l;
168 Evas_Coord ox, ow;
169 char buf[1024];
170 Widget_Data *wd = data;
171
172 evas_object_geometry_get(wd->scroller, &ox, NULL, &ow, NULL);
173 if (ow <= 0)
174 return EINA_FALSE;
175 if (!wd->init)
176 return EINA_FALSE;
177 if (!wd->round)
178 list = wd->items;
179 else
180 list = wd->r_items;
181
182 EINA_LIST_FOREACH(list, l, it)
183 {
184 Evas_Coord x, w;
185 int len;
186 evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
187 /* item not visible */
188 if ((x + w <= ox) || (x >= ox + ow))
189 continue;
190
191 len = _count_letter(it->label);
192// // FIXME: len should be # of ut8f letters. ie count using utf8 string walk, not stringshare len
193// len = eina_stringshare_strlen(it->label);
194
195 if (x <= ox + 5)
196 edje_object_signal_emit(VIEW(it), "elm,state,left_side",
197 "elm");
198 else if (x + w >= ox + ow - 5)
199 edje_object_signal_emit(VIEW(it), "elm,state,right_side",
200 "elm");
201 else
202 {
203 if ((wd->len_threshold) && (len > wd->len_threshold))
204 edje_object_signal_emit(VIEW(it), "elm,state,center_small",
205 "elm");
206 else
207 edje_object_signal_emit(VIEW(it), "elm,state,center",
208 "elm");
209 }
210
211 // if len is les that the limit len, skip anyway
212 if (len <= wd->len_side)
213 continue;
214
215 steps = len - wd->len_side + 1;
216 mid = x + w / 2;
217 if (mid <= ox + ow / 2)
218 diff = (ox + ow / 2) - mid;
219 else
220 diff = mid - (ox + ow / 2);
221
222 length = len - (int)(diff * steps / (ow / 3));
223 length = MAX(length, wd->len_side);
224 // limit string len to "length" ut8f chars
225 length = _check_letter(it->label, length);
226 // cut it off at byte mark returned form _check_letter
227 strncpy(buf, it->label, length);
228 buf[length] = '\0';
229 edje_object_part_text_escaped_set(VIEW(it), "elm.text", buf);
230 }
231
232 if (wd->check_idler)
233 ecore_idle_enterer_del(wd->check_idler);
234 wd->check_idler = NULL;
235 return EINA_FALSE;
236}
237
238static Eina_Bool
239_item_del_pre_hook(Elm_Object_Item *it)
240{
241 Elm_Diskselector_Item *item, *item2, *dit;
242 Eina_List *l;
243 int i = 0;
244 Widget_Data *wd;
245 item = (Elm_Diskselector_Item *)it;
246 wd = elm_widget_data_get(WIDGET(item));
247 if (!wd) return EINA_FALSE;
248
249 elm_box_unpack(wd->main_box, VIEW(item));
250
251 if (wd->round)
252 wd->r_items = eina_list_remove(wd->r_items, item);
253
254 wd->items = eina_list_remove(wd->items, item);
255
256 if (wd->selected_item == item)
257 {
258 dit = (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
259 if (dit != item)
260 wd->selected_item = dit;
261 else
262 wd->selected_item = eina_list_nth(wd->items, 1);
263
264 _selected_item_indicate(wd->selected_item);
265 }
266
267 _item_del(item);
268 wd->item_count -= 1;
269
270 if (wd->round)
271 {
272 if (!wd->item_count)
273 {
274 evas_object_hide(wd->VIEW(first));
275 evas_object_hide(wd->VIEW(second));
276 evas_object_hide(wd->VIEW(last));
277 evas_object_hide(wd->VIEW(s_last));
278
279 EINA_LIST_FOREACH(wd->under_items, l, item2)
280 evas_object_hide(VIEW(item2));
281
282 EINA_LIST_FOREACH(wd->over_items, l, item2)
283 evas_object_hide(VIEW(item2));
284 }
285 else
286 {
287 dit = eina_list_nth(wd->items, 0);
288 if (dit)
289 {
290 eina_stringshare_replace(&wd->first->label, dit->label);
291 edje_object_part_text_escaped_set(wd->VIEW(first), "elm.text",
292 wd->first->label);
293 }
294 dit = eina_list_nth(wd->items, 1);
295 if (dit)
296 {
297 eina_stringshare_replace(&wd->second->label, dit->label);
298 edje_object_part_text_escaped_set(wd->VIEW(second), "elm.text",
299 wd->second->label);
300 }
301 // if more than 3 itmes should be displayed
302 for (i = 2; i < CEIL(wd->display_item_num); i++)
303 {
304 dit = eina_list_nth(wd->items, i);
305 item2 = eina_list_nth(wd->over_items, i - 2);
306 eina_stringshare_replace(&item2->label, dit->label);
307 edje_object_part_text_escaped_set(VIEW(item2), "elm.text", item2->label);
308 }
309
310 dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 1);
311 if (dit)
312 {
313 eina_stringshare_replace(&wd->last->label, dit->label);
314 edje_object_part_text_escaped_set(wd->VIEW(last), "elm.text",
315 wd->last->label);
316 }
317 dit = eina_list_nth(wd->items, eina_list_count(wd->items) - 2);
318 if (dit)
319 {
320 eina_stringshare_replace(&wd->s_last->label, dit->label);
321 edje_object_part_text_escaped_set(wd->VIEW(s_last), "elm.text",
322 wd->s_last->label);
323 }
324 // if more than 3 itmes should be displayed
325 for (i = 3; i <= CEIL(wd->display_item_num); i++)
326 {
327 dit = eina_list_nth(wd->items, wd->item_count - i);
328 item2 = eina_list_nth(wd->under_items, i - 3);
329 eina_stringshare_replace(&item2->label, dit->label);
330 edje_object_part_text_escaped_set(VIEW(item2), "elm.text",
331 item2->label);
332 }
333 }
334 }
335 wd->check_idler = ecore_idle_enterer_before_add(_check_string, wd);
336 _sizing_eval(wd->self);
337
338 return EINA_TRUE;
339}
340
341static Elm_Diskselector_Item *
342_item_new(Evas_Object *obj, Evas_Object *icon, const char *label, Evas_Smart_Cb func, const void *data)
343{
344 Elm_Diskselector_Item *it;
345 const char *style = elm_widget_style_get(obj);
346
347 it = elm_widget_item_new(obj, Elm_Diskselector_Item);
348 if (!it) return NULL;
349
350 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
351 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
352 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
353 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
354 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
355
356 it->label = eina_stringshare_add(label);
357 it->icon = icon;
358 it->func = func;
359 it->base.data = data;
360 VIEW(it) = edje_object_add(evas_object_evas_get(obj));
361 _elm_theme_object_set(obj, VIEW(it), "diskselector", "item", style);
362 evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND,
363 EVAS_HINT_EXPAND);
364 evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL,
365 EVAS_HINT_FILL);
366 evas_object_show(VIEW(it));
367
368 if (it->label)
369 {
370 edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
371 edje_object_signal_callback_add(VIEW(it), "elm,action,click", "", _item_click_cb, it);
372 }
373 if (it->icon)
374 {
375 evas_object_size_hint_min_set(it->icon, 24, 24);
376 evas_object_size_hint_max_set(it->icon, 40, 40);
377 edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
378 evas_object_show(it->icon);
379 elm_widget_sub_object_add(obj, it->icon);
380 }
381 return it;
382}
383
384static void
385_theme_data_get(Widget_Data *wd)
386{
387 const char* str;
388 str = edje_object_data_get(wd->right_blank, "len_threshold");
389 if (str) wd->len_threshold = MAX(0, atoi(str));
390 else wd->len_threshold = 0;
391
392 if (!wd->display_item_num_by_api)
393 {
394 str = edje_object_data_get(wd->right_blank, "display_item_num");
395 if (str) wd->display_item_num = MAX(DISPLAY_ITEM_NUM_MIN, atoi(str));
396 else wd->display_item_num = DISPLAY_ITEM_NUM_MIN;
397 }
398
399 str = edje_object_data_get(wd->right_blank, "min_width");
400 if (str) wd->minw = MAX(-1, atoi(str));
401 else wd->minw = -1;
402
403 str = edje_object_data_get(wd->right_blank, "min_height");
404 if (str) wd->minh = MAX(-1, atoi(str));
405 else wd->minh = -1;
406}
407
408static void
409_del_hook(Evas_Object * obj)
410{
411 Widget_Data *wd = elm_widget_data_get(obj);
412 if (!wd) return;
413 free(wd);
414}
415
416static void
417_del_pre_hook(Evas_Object * obj)
418{
419 Elm_Diskselector_Item *it;
420 Eina_List *l;
421
422 Widget_Data *wd = elm_widget_data_get(obj);
423 if (!wd) return;
424
425 if (wd->left_blank)
426 evas_object_del(wd->left_blank);
427 if (wd->right_blank)
428 evas_object_del(wd->right_blank);
429 if (wd->last)
430 {
431 eina_stringshare_del(wd->last->label);
432 evas_object_del(wd->VIEW(last));
433 free(wd->last);
434 }
435 if (wd->s_last)
436 {
437 eina_stringshare_del(wd->s_last->label);
438 evas_object_del(wd->VIEW(s_last));
439 free(wd->s_last);
440 }
441 if (wd->second)
442 {
443 eina_stringshare_del(wd->second->label);
444 evas_object_del(wd->VIEW(second));
445 free(wd->second);
446 }
447 if (wd->first)
448 {
449 eina_stringshare_del(wd->first->label);
450 evas_object_del(wd->VIEW(first));
451 free(wd->first);
452 }
453
454 EINA_LIST_FOREACH(wd->under_items, l, it)
455 {
456 if (it)
457 {
458 eina_stringshare_del(it->label);
459 evas_object_del(VIEW(it));
460 free(it);
461 }
462 }
463
464 EINA_LIST_FOREACH(wd->over_items, l, it)
465 {
466 if (it)
467 {
468 eina_stringshare_del(it->label);
469 evas_object_del(VIEW(it));
470 free(it);
471 }
472 }
473
474 EINA_LIST_FREE(wd->items, it)
475 {
476 _item_del(it);
477 elm_widget_item_free(it);
478 }
479 eina_list_free(wd->r_items);
480}
481
482static void
483_sizing_eval(Evas_Object * obj)
484{
485 Widget_Data *wd = elm_widget_data_get(obj);
486 if (!wd) return;
487 _diskselector_object_resize(obj, NULL, obj, NULL);
488}
489
490static void
491_theme_hook(Evas_Object * obj)
492{
493 Eina_List *l;
494 Elm_Diskselector_Item *it;
495 Widget_Data *wd = elm_widget_data_get(obj);
496 if (!wd) return;
497
498 if (wd->scroller)
499 elm_smart_scroller_object_theme_set(obj, wd->scroller, "diskselector",
500 "base", elm_widget_style_get(obj));
501 if (wd->round)
502 {
503 EINA_LIST_FOREACH(wd->r_items, l, it)
504 {
505 _elm_theme_object_set(obj, VIEW(it), "diskselector", "item",
506 elm_widget_style_get(obj));
507 edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
508 }
509 }
510 else
511 {
512 EINA_LIST_FOREACH(wd->items, l, it)
513 {
514 _elm_theme_object_set(obj, VIEW(it), "diskselector", "item",
515 elm_widget_style_get(obj));
516 edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
517 }
518 }
519 _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
520 elm_widget_style_get(obj));
521 _theme_data_get(wd);
522 _sizing_eval(obj);
523}
524
525static void
526_sub_del(void *data __UNUSED__, Evas_Object * obj, void *event_info)
527{
528 Widget_Data *wd = elm_widget_data_get(obj);
529 Evas_Object *sub = event_info;
530 Elm_Diskselector_Item *it;
531 const Eina_List *l;
532
533 if (!wd) return;
534 if (!sub) abort();
535 if (sub == wd->scroller)
536 wd->scroller = NULL;
537 else
538 {
539 EINA_LIST_FOREACH(wd->items, l, it)
540 {
541 if (sub == it->icon)
542 {
543 it->icon = NULL;
544 _sizing_eval(obj);
545 break;
546 }
547 }
548 }
549}
550
551static void
552_select_item(Elm_Diskselector_Item *it)
553{
554 if (!it) return;
555 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
556 wd->selected_item = it;
557 _selected_item_indicate(wd->selected_item);
558 if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
559 evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
560}
561
562static void
563_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
564{
565 Widget_Data *wd = elm_widget_data_get(obj);
566 if (!wd)
567 return;
568
569 if (elm_widget_focus_get(obj))
570 {
571 edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
572 evas_object_focus_set(wd->self, EINA_TRUE);
573 }
574 else
575 {
576 edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
577 evas_object_focus_set(wd->self, EINA_FALSE);
578 }
579}
580
581static Eina_Bool
582_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
583{
584 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
585 Evas_Event_Key_Down *ev = event_info;
586 Widget_Data *wd = elm_widget_data_get(obj);
587 if (!wd) return EINA_FALSE;
588 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
589 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
590
591 Elm_Diskselector_Item *it = NULL;
592 Eina_List *l;
593
594 if (!wd->selected_item) {
595 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
596 return EINA_TRUE;
597 }
598
599 if ((!strcmp(ev->keyname, "Left")) ||
600 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)) ||
601 (!strcmp(ev->keyname, "Up")) ||
602 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
603 {
604 l = wd->selected_item->node->prev;
605 if ((!l) && (wd->round))
606 l = eina_list_last(wd->items);
607 }
608 else if ((!strcmp(ev->keyname, "Right")) ||
609 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)) ||
610 (!strcmp(ev->keyname, "Down")) ||
611 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
612 {
613 l = wd->selected_item->node->next;
614 if ((!l) && (wd->round))
615 l = wd->items;
616 }
617 else if ((!strcmp(ev->keyname, "Home")) ||
618 ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
619 l = wd->items;
620 else if ((!strcmp(ev->keyname, "End")) ||
621 ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
622 l = eina_list_last(wd->items);
623 else return EINA_FALSE;
624
625 if (l)
626 it = eina_list_data_get(l);
627
628 if (it)
629 {
630 wd->selected_item = it;
631 if (!wd->idler)
632 wd->idler = ecore_idle_enterer_before_add(_move_scroller, obj);
633 }
634
635 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
636 return EINA_TRUE;
637}
638
639static void
640_selected_item_indicate(Elm_Diskselector_Item *it)
641{
642 Elm_Diskselector_Item *item;
643 Eina_List *l;
644 Widget_Data *wd;
645 wd = elm_widget_data_get(WIDGET(it));
646
647 if (!wd) return;
648 if (!it->label) return;
649
650 EINA_LIST_FOREACH(wd->r_items, l, item)
651 {
652 if (item->label && !strcmp(item->label, it->label))
653 edje_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
654 else
655 edje_object_signal_emit(VIEW(item), "elm,state,default", "elm");
656 }
657}
658
659static void
660_item_click_cb(void *data, Evas_Object *obj __UNUSED__,
661 const char *emission __UNUSED__, const char *source __UNUSED__)
662{
663 Elm_Diskselector_Item *it = data;
664
665 if (!it) return;
666
667 Widget_Data *wd;
668 wd = elm_widget_data_get(WIDGET(it));
669
670 if (!wd) return;
671
672 if (wd->selected_item != it)
673 {
674 wd->selected_item = it;
675 _selected_item_indicate(wd->selected_item);
676 }
677
678 if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
679}
680
681static void
682_scroller_move_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
683{
684 Evas_Coord x, y, w, h, bw;
685 Widget_Data *wd = data;
686
687 _check_string(wd);
688 elm_smart_scroller_child_pos_get(obj, &x, &y);
689 elm_smart_scroller_child_viewport_size_get(obj, &w, &h);
690 if (wd->round)
691 {
692 evas_object_geometry_get(wd->main_box, NULL, NULL, &bw, NULL);
693 if (x > ((w / wd->display_item_num) * (wd->item_count + (wd->display_item_num % 2))))
694 elm_smart_scroller_child_region_show(wd->scroller,
695 x - ((w / wd->display_item_num) * wd->item_count),
696 y, w, h);
697 else if (x < 0)
698 elm_smart_scroller_child_region_show(wd->scroller,
699 x + ((w / wd->display_item_num) * wd->item_count),
700 y, w, h);
701 }
702}
703
704static void
705_scroller_stop_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
706{
707 Elm_Diskselector_Item *it;
708 Widget_Data *wd = elm_widget_data_get(data);
709 Evas_Coord x, w, ow;
710 Eina_List *l, *list;
711
712 if (wd->idler) return;
713
714 if (!wd->round)
715 list = wd->items;
716 else
717 list = wd->r_items;
718
719 evas_object_geometry_get(wd->scroller, NULL, NULL, &ow, NULL);
720 EINA_LIST_FOREACH(list, l, it)
721 {
722 evas_object_geometry_get(VIEW(it), &x, NULL, &w, NULL);
723 if (abs((int)(ow / 2 - (int)(x + w / 2))) < 10) break;
724 }
725
726 if (!it) return;
727 _select_item(it);
728 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, it);
729}
730
731static void
732_scroller_start_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
733{
734 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START,
735 elm_diskselector_selected_item_get(data));
736}
737
738static void
739_drag_start_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
740{
741 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START,
742 elm_diskselector_selected_item_get(data));
743}
744
745static void
746_drag_stop_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
747{
748 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP,
749 elm_diskselector_selected_item_get(data));
750}
751
752static Eina_Bool
753_move_scroller(void *data)
754{
755 Evas_Object *obj = data;
756 Widget_Data *wd;
757 Eina_List *list, *l;
758 Elm_Diskselector_Item *dit;
759 Evas_Coord y, w, h;
760 int i;
761
762 wd = elm_widget_data_get(obj);
763 if (!wd) return EINA_FALSE;
764
765 if (!wd->round)
766 {
767 i = 0;
768 list = wd->items;
769 }
770 else
771 {
772 i = 1;
773 list = wd->r_items;
774 }
775
776 EINA_LIST_FOREACH(list, l, dit)
777 {
778 if (wd->selected_item == dit)
779 break;
780 i++;
781 }
782
783 if (wd->round) i -= CEIL(wd->display_item_num);
784
785 if (!dit)
786 {
787 wd->selected_item =
788 (Elm_Diskselector_Item *) eina_list_nth(wd->items, 0);
789 return EINA_FALSE;
790 }
791
792 evas_object_geometry_get(wd->scroller, NULL, &y, &w, &h);
793 elm_smart_scroller_child_region_show(wd->scroller, w / wd->display_item_num * i, y, w, h);
794 _select_item(dit);
795 if (wd->idler)
796 {
797 ecore_idle_enterer_del(wd->idler);
798 wd->idler = NULL;
799 }
800 wd->init = EINA_TRUE;
801 _check_string(wd);
802
803 return EINA_TRUE;
804}
805
806static void
807_round_item_del(Widget_Data *wd, Elm_Diskselector_Item *it)
808{
809 if (!it) return;
810 elm_box_unpack(wd->main_box, VIEW(it));
811 wd->r_items = eina_list_remove(wd->r_items, it);
812 eina_stringshare_del(it->label);
813 elm_widget_item_free(it);
814}
815
816static void
817_round_items_del(Widget_Data *wd)
818{
819 Eina_List *l;
820 Elm_Diskselector_Item * it;
821
822 _round_item_del(wd, wd->last);
823 wd->last = NULL;
824 _round_item_del(wd, wd->s_last);
825 wd->s_last = NULL;
826 _round_item_del(wd, wd->second);
827 wd->second = NULL;
828 _round_item_del(wd, wd->first);
829 wd->first = NULL;
830
831 EINA_LIST_FOREACH(wd->under_items, l, it)
832 {
833 _round_item_del(wd, it);
834 }
835 wd->under_items = eina_list_free(wd->under_items);
836
837 EINA_LIST_FOREACH(wd->over_items, l, it)
838 {
839 _round_item_del(wd, it);
840 }
841 wd->over_items = eina_list_free(wd->over_items);
842}
843
844static void
845_round_items_add(Widget_Data *wd)
846{
847 Elm_Diskselector_Item *dit;
848 Elm_Diskselector_Item *it;
849 Elm_Diskselector_Item *temp_it;
850 int i = 0;
851 dit = it = eina_list_nth(wd->items, 0);
852 if (!dit) return;
853
854 if (!wd->first)
855 {
856 wd->first = _item_new(WIDGET(it), it->icon, it->label, it->func,
857 it->base.data);
858 wd->first->node = it->node;
859 wd->r_items = eina_list_append(wd->r_items, wd->first);
860 }
861
862 it = eina_list_nth(wd->items, 1);
863 if (!it)
864 it = dit;
865 if (!wd->second)
866 {
867 wd->second = _item_new(WIDGET(it), it->icon, it->label, it->func,
868 it->base.data);
869 wd->second->node = it->node;
870 wd->r_items = eina_list_append(wd->r_items, wd->second);
871 }
872
873 // if more than 3 itmes should be displayed
874 for (i = 2; i < CEIL(wd->display_item_num); i++)
875 {
876 it = eina_list_nth(wd->items, i);
877 if (!it) it = dit;
878 temp_it = _item_new(WIDGET(it), it->icon, it->label, it->func, it->base.data);
879 wd->over_items = eina_list_append(wd->over_items, temp_it);
880 wd->r_items = eina_list_append(wd->r_items, temp_it);
881 }
882
883 it = eina_list_nth(wd->items, wd->item_count - 1);
884 if (!it)
885 it = dit;
886 if (!wd->last)
887 {
888 wd->last = _item_new(WIDGET(it), it->icon, it->label, it->func,
889 it->base.data);
890 wd->last->node = it->node;
891 wd->r_items = eina_list_prepend(wd->r_items, wd->last);
892 }
893
894 it = eina_list_nth(wd->items, wd->item_count - 2);
895 if (!it)
896 it = dit;
897 if (!wd->s_last)
898 {
899 wd->s_last = _item_new(WIDGET(it), it->icon, it->label, it->func,
900 it->base.data);
901 wd->s_last->node = it->node;
902 wd->r_items = eina_list_prepend(wd->r_items, wd->s_last);
903 }
904
905 // if more than 3 itmes should be displayed
906 for (i = 3; i <= CEIL(wd->display_item_num); i++)
907 {
908 it = eina_list_nth(wd->items, wd->item_count - i);
909 if (!it) it = dit;
910 temp_it = _item_new(WIDGET(it), it->icon, it->label, it->func, it->base.data);
911 wd->under_items = eina_list_append(wd->under_items, temp_it);
912 wd->r_items = eina_list_prepend(wd->r_items, temp_it);
913 }
914}
915
916static void
917_item_icon_set(Elm_Diskselector_Item *it, Evas_Object *icon)
918{
919 if (it->icon == icon) return;
920 if (it->icon) evas_object_del(it->icon);
921 it->icon = icon;
922 if (VIEW(it))
923 {
924 evas_object_size_hint_min_set(it->icon, 24, 24);
925 evas_object_size_hint_max_set(it->icon, 40, 40);
926 edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
927 evas_object_show(it->icon);
928 elm_widget_sub_object_add(WIDGET(it), it->icon);
929 }
930}
931
932static void
933_check_identical_item(Elm_Diskselector_Item *it, Evas_Object *icon)
934{
935 Widget_Data *wd;
936 Elm_Diskselector_Item *dit;
937 Eina_List *l;
938 int idx = 0;
939 int ic = 0;
940 int ac = 0;
941
942 wd = elm_widget_data_get(WIDGET(it));
943 if (!wd) return;
944
945 if (wd->round)
946 {
947 // Get index from indentical item from round items
948 EINA_LIST_FOREACH(wd->r_items, l, dit)
949 {
950 if (it == dit) break;
951 idx++;
952 }
953
954 // No item to match
955 ic = eina_list_count(wd->r_items);
956 if (idx >= ic) return;
957 dit = NULL;
958
959 // Number of added items: CEIL(wd->display_item_num)
960 ac = CEIL(wd->display_item_num);
961
962 if (((idx >= 0) && (idx < ac)) ||
963 ((idx >= ac) && (idx < (2 * ac))))
964 {
965 // Selected item: under, low region
966 dit = eina_list_nth(wd->r_items,
967 idx + ic - (2 * ac));
968 }
969 else if (((idx >= (ic - ac)) && (idx < ic)) ||
970 ((idx >= (ic - (2 * ac))) && (idx < ic - ac)))
971 {
972 // Selected item: over, high region
973 dit = eina_list_nth(wd->r_items,
974 idx - ic + (2 * ac));
975 }
976
977 if (dit) _item_icon_set(dit, icon);
978 _sizing_eval(wd->self);
979 }
980}
981
982static void
983_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
984{
985 Elm_Diskselector_Item *item;
986 if (part && strcmp(part, "default")) return;
987 item = (Elm_Diskselector_Item *)it;
988 eina_stringshare_replace(&item->label, label);
989 edje_object_part_text_escaped_set(VIEW(item), "elm.text", item->label);
990}
991
992static const char *
993_item_text_get_hook(const Elm_Object_Item *it, const char *part)
994{
995 if (part && strcmp(part, "default")) return NULL;
996 return ((Elm_Diskselector_Item *)it)->label;
997}
998
999static void
1000_item_content_set_hook(Elm_Object_Item *it,
1001 const char *part,
1002 Evas_Object *content)
1003{
1004 if (part && strcmp(part, "icon")) return;
1005 _item_icon_set((Elm_Diskselector_Item *)it, content);
1006 _check_identical_item((Elm_Diskselector_Item *)it, content);
1007}
1008
1009static Evas_Object *
1010_item_content_get_hook(const Elm_Object_Item *it, const char *part)
1011{
1012 if (part && strcmp(part, "icon")) return NULL;
1013 return ((Elm_Diskselector_Item *)it)->icon;
1014}
1015
1016
1017EAPI Evas_Object *
1018elm_diskselector_add(Evas_Object *parent)
1019{
1020 Evas *e;
1021 Evas_Object *obj;
1022 Widget_Data *wd;
1023
1024 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1025
1026 ELM_SET_WIDTYPE(widtype, "diskselector");
1027 elm_widget_type_set(obj, "diskselector");
1028 elm_widget_sub_object_add(parent, obj);
1029 elm_widget_data_set(obj, wd);
1030 elm_widget_del_hook_set(obj, _del_hook);
1031 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1032 elm_widget_theme_hook_set(obj, _theme_hook);
1033 elm_widget_can_focus_set(obj, EINA_TRUE);
1034 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1035 elm_widget_event_hook_set(obj, _event_hook);
1036
1037 wd->self = obj;
1038 wd->item_count = 0;
1039 wd->round = EINA_FALSE;
1040 wd->init = EINA_FALSE;
1041 wd->len_side = 3;
1042 wd->display_item_num_by_api = EINA_FALSE;
1043
1044 wd->scroller = elm_smart_scroller_add(e);
1045 elm_smart_scroller_widget_set(wd->scroller, obj);
1046 _theme_hook(obj);
1047 elm_widget_resize_object_set(obj, wd->scroller);
1048 elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF,
1049 ELM_SMART_SCROLLER_POLICY_OFF);
1050 elm_smart_scroller_bounce_allow_set(wd->scroller, EINA_TRUE, EINA_FALSE);
1051 evas_object_smart_callback_add(wd->scroller, "scroll", _scroller_move_cb,
1052 wd);
1053 evas_object_smart_callback_add(wd->scroller, "animate,stop",
1054 _scroller_stop_cb, obj);
1055 evas_object_smart_callback_add(wd->scroller, "animate,start",
1056 _scroller_start_cb, obj);
1057 evas_object_smart_callback_add(wd->scroller, "drag,stop",
1058 _drag_stop_cb, obj);
1059 evas_object_smart_callback_add(wd->scroller, "drag,start",
1060 _drag_start_cb, obj);
1061
1062 _elm_theme_object_set(obj, wd->scroller, "diskselector", "base",
1063 "default");
1064 evas_object_event_callback_add(wd->scroller, EVAS_CALLBACK_RESIZE,
1065 _diskselector_object_resize, obj);
1066
1067 wd->main_box = elm_box_add(parent);
1068 elm_box_horizontal_set(wd->main_box, EINA_TRUE);
1069 elm_box_homogeneous_set(wd->main_box, EINA_TRUE);
1070 evas_object_size_hint_weight_set(wd->main_box, EVAS_HINT_EXPAND,
1071 EVAS_HINT_EXPAND);
1072 evas_object_size_hint_align_set(wd->main_box, EVAS_HINT_FILL,
1073 EVAS_HINT_FILL);
1074 _elm_theme_object_set(obj, wd->main_box, "diskselector", "base",
1075 "default");
1076 elm_widget_sub_object_add(obj, wd->main_box);
1077
1078 elm_smart_scroller_child_set(wd->scroller, wd->main_box);
1079
1080 wd->left_blank = edje_object_add(evas_object_evas_get(obj));
1081 _elm_theme_object_set(obj, wd->left_blank, "diskselector", "item",
1082 "default");
1083 evas_object_size_hint_weight_set(wd->left_blank, EVAS_HINT_EXPAND,
1084 EVAS_HINT_EXPAND);
1085 evas_object_size_hint_align_set(wd->left_blank, EVAS_HINT_FILL,
1086 EVAS_HINT_FILL);
1087 elm_box_pack_end(wd->main_box, wd->left_blank);
1088 evas_object_show(wd->left_blank);
1089
1090 wd->right_blank = edje_object_add(evas_object_evas_get(obj));
1091 _elm_theme_object_set(obj, wd->right_blank, "diskselector", "item",
1092 "default");
1093 evas_object_size_hint_weight_set(wd->right_blank, EVAS_HINT_EXPAND,
1094 EVAS_HINT_EXPAND);
1095 evas_object_size_hint_align_set(wd->right_blank, EVAS_HINT_FILL,
1096 EVAS_HINT_FILL);
1097 elm_box_pack_end(wd->main_box, wd->right_blank);
1098 evas_object_show(wd->right_blank);
1099
1100 _theme_data_get(wd);
1101
1102 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1103 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1104 _sizing_eval(obj);
1105 return obj;
1106}
1107
1108EAPI Eina_Bool
1109elm_diskselector_round_enabled_get(const Evas_Object *obj)
1110{
1111 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1112 Widget_Data *wd = elm_widget_data_get(obj);
1113 if (!wd) return EINA_FALSE;
1114 return wd->round;
1115}
1116
1117EAPI void
1118elm_diskselector_round_enabled_set(Evas_Object * obj, Eina_Bool enabled)
1119{
1120 Eina_List *elist;
1121 Elm_Diskselector_Item *it;
1122
1123 ELM_CHECK_WIDTYPE(obj, widtype);
1124 Widget_Data *wd = elm_widget_data_get(obj);
1125 if (!wd) return;
1126
1127 if (wd->round == enabled)
1128 return;
1129
1130 wd->round = !!enabled;
1131 if (enabled)
1132 {
1133 wd->r_items = eina_list_clone(wd->items);
1134 elm_box_unpack(wd->main_box, wd->left_blank);
1135 evas_object_hide(wd->left_blank);
1136 elm_box_unpack(wd->main_box, wd->right_blank);
1137 evas_object_hide(wd->right_blank);
1138 if (!wd->items)
1139 return;
1140
1141 _round_items_add(wd);
1142
1143 if (wd->last)
1144 elm_box_pack_start(wd->main_box, wd->VIEW(last));
1145 if (wd->s_last)
1146 elm_box_pack_start(wd->main_box, wd->VIEW(s_last));
1147
1148 // if more than 3 items should be displayed
1149 EINA_LIST_FOREACH(wd->under_items, elist, it)
1150 elm_box_pack_start(wd->main_box, VIEW(it));
1151
1152 if (wd->first)
1153 elm_box_pack_end(wd->main_box, wd->VIEW(first));
1154 if (wd->second)
1155 elm_box_pack_end(wd->main_box, wd->VIEW(second));
1156
1157 // if more than 3 items should be displayed
1158 EINA_LIST_FOREACH(wd->over_items, elist, it)
1159 elm_box_pack_end(wd->main_box, VIEW(it));
1160 }
1161 else
1162 {
1163 _round_items_del(wd);
1164 elm_box_pack_start(wd->main_box, wd->left_blank);
1165 elm_box_pack_end(wd->main_box, wd->right_blank);
1166 eina_list_free(wd->r_items);
1167 wd->r_items = NULL;
1168 }
1169
1170 _selected_item_indicate(wd->selected_item);
1171 _sizing_eval(obj);
1172}
1173
1174EAPI int
1175elm_diskselector_side_text_max_length_get(const Evas_Object *obj)
1176{
1177 ELM_CHECK_WIDTYPE(obj, widtype) 0;
1178 Widget_Data *wd = elm_widget_data_get(obj);
1179 if (!wd) return 0;
1180 return wd->len_side;
1181}
1182
1183EAPI void
1184elm_diskselector_side_text_max_length_set(Evas_Object *obj, int len)
1185{
1186 ELM_CHECK_WIDTYPE(obj, widtype);
1187 Widget_Data *wd = elm_widget_data_get(obj);
1188 if (!wd) return;
1189 wd->len_side = len;
1190}
1191
1192EAPI void
1193elm_diskselector_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1194{
1195 ELM_CHECK_WIDTYPE(obj, widtype);
1196 Widget_Data *wd = elm_widget_data_get(obj);
1197 if (!wd) return;
1198 if (wd->scroller)
1199 elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
1200}
1201
1202EAPI void
1203elm_diskselector_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
1204{
1205 ELM_CHECK_WIDTYPE(obj, widtype);
1206 Widget_Data *wd = elm_widget_data_get(obj);
1207 if (!wd) return;
1208 elm_smart_scroller_bounce_allow_get(wd->scroller, h_bounce, v_bounce);
1209}
1210
1211EAPI void
1212elm_diskselector_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
1213{
1214 ELM_CHECK_WIDTYPE(obj, widtype);
1215 Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
1216 Widget_Data *wd = elm_widget_data_get(obj);
1217 if ((!wd) || (!wd->scroller)) return;
1218 elm_smart_scroller_policy_get(wd->scroller, &s_policy_h, &s_policy_v);
1219 *policy_h = (Elm_Scroller_Policy) s_policy_h;
1220 *policy_v = (Elm_Scroller_Policy) s_policy_v;
1221}
1222
1223EAPI void
1224elm_diskselector_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
1225{
1226 ELM_CHECK_WIDTYPE(obj, widtype);
1227 Widget_Data *wd = elm_widget_data_get(obj);
1228 if ((!wd) || (!wd->scroller)) return;
1229 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
1230 (policy_v >= ELM_SCROLLER_POLICY_LAST))
1231 return;
1232 elm_smart_scroller_policy_set(wd->scroller, policy_h, policy_v);
1233}
1234
1235EAPI void
1236elm_diskselector_clear(Evas_Object *obj)
1237{
1238 ELM_CHECK_WIDTYPE(obj, widtype);
1239 Widget_Data *wd = elm_widget_data_get(obj);
1240 Elm_Diskselector_Item *it;
1241
1242 if (!wd) return;
1243 if (!wd->items) return;
1244
1245 wd->selected_item = NULL;
1246 EINA_LIST_FREE(wd->items, it)
1247 {
1248 _item_del(it);
1249 elm_widget_item_free(it);
1250 }
1251 _round_items_del(wd);
1252 _sizing_eval(obj);
1253}
1254
1255EAPI const Eina_List *
1256elm_diskselector_items_get(const Evas_Object *obj)
1257{
1258 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1259 Widget_Data *wd = elm_widget_data_get(obj);
1260 if (!wd) return NULL;
1261 return wd->items;
1262}
1263
1264EAPI Elm_Object_Item *
1265elm_diskselector_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
1266{
1267 Elm_Diskselector_Item *it;
1268 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1269 Widget_Data *wd = elm_widget_data_get(obj);
1270 if (!wd) return NULL;
1271
1272 it = _item_new(obj, icon, label, func, data);
1273 wd->items = eina_list_append(wd->items, it);
1274 it->node = eina_list_last(wd->items);
1275 wd->item_count++;
1276 if (wd->round)
1277 {
1278 _round_items_del(wd);
1279 wd->r_items = eina_list_append(wd->r_items, it);
1280 _round_items_add(wd);
1281 if (wd->last)
1282 elm_box_pack_start(wd->main_box, wd->VIEW(last));
1283 if (wd->s_last)
1284 elm_box_pack_start(wd->main_box, wd->VIEW(s_last));
1285 elm_box_pack_end(wd->main_box, VIEW(it));
1286 if (wd->first)
1287 elm_box_pack_end(wd->main_box, wd->VIEW(first));
1288 if (wd->second)
1289 elm_box_pack_end(wd->main_box, wd->VIEW(second));
1290 }
1291 else
1292 {
1293 elm_box_unpack(wd->main_box, wd->right_blank);
1294 elm_box_pack_end(wd->main_box, VIEW(it));
1295 elm_box_pack_end(wd->main_box, wd->right_blank);
1296 }
1297 if (!wd->selected_item)
1298 wd->selected_item = it;
1299 if (!wd->idler)
1300 wd->idler = ecore_idle_enterer_before_add(_move_scroller, obj);
1301 _sizing_eval(obj);
1302 return (Elm_Object_Item *)it;
1303}
1304
1305EAPI Elm_Object_Item *
1306elm_diskselector_selected_item_get(const Evas_Object *obj)
1307{
1308 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1309 Widget_Data *wd = elm_widget_data_get(obj);
1310 if (!wd) return NULL;
1311 return (Elm_Object_Item *) wd->selected_item;
1312}
1313
1314EAPI void
1315elm_diskselector_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
1316{
1317 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1318 Widget_Data *wd;
1319 Elm_Diskselector_Item *item = (Elm_Diskselector_Item *)it;
1320 wd = elm_widget_data_get(WIDGET(item));
1321 if (!wd) return;
1322
1323 if ((wd->selected_item == item) && (selected))
1324 return;
1325
1326 if ((wd->selected_item == item) && (!selected))
1327 wd->selected_item = eina_list_data_get(wd->items);
1328 else
1329 {
1330 wd->selected_item = item;
1331 _selected_item_indicate(wd->selected_item);
1332 }
1333
1334 if (!wd->idler)
1335 wd->idler = ecore_idle_enterer_before_add(_move_scroller, WIDGET(item));
1336}
1337
1338EAPI Eina_Bool
1339elm_diskselector_item_selected_get(const Elm_Object_Item *it)
1340{
1341 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1342 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
1343 if (!wd) return EINA_FALSE;
1344 return (wd->selected_item == ((Elm_Diskselector_Item *)it));
1345}
1346
1347EAPI Elm_Object_Item *
1348elm_diskselector_item_prev_get(const Elm_Object_Item *it)
1349{
1350 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1351 Elm_Diskselector_Item *item = (Elm_Diskselector_Item *)it;
1352 if (item->node->prev) return item->node->prev->data;
1353 else return NULL;
1354}
1355
1356EAPI Elm_Object_Item *
1357elm_diskselector_item_next_get(const Elm_Object_Item *it)
1358{
1359 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1360 Elm_Diskselector_Item *item = (Elm_Diskselector_Item *)it;
1361 if (item->node->next) return item->node->next->data;
1362 else return NULL;
1363}
1364
1365EAPI Elm_Object_Item *
1366elm_diskselector_first_item_get(const Evas_Object *obj)
1367{
1368 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1369 Widget_Data *wd = elm_widget_data_get(obj);
1370 if (!wd || !wd->items) return NULL;
1371 return eina_list_data_get(wd->items);
1372}
1373
1374EAPI Elm_Object_Item *
1375elm_diskselector_last_item_get(const Evas_Object *obj)
1376{
1377 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1378 Widget_Data *wd = elm_widget_data_get(obj);
1379 if (!wd || !wd->items) return NULL;
1380 return eina_list_data_get(eina_list_last(wd->items));
1381}
1382
1383EAPI void
1384elm_diskselector_display_item_num_set(Evas_Object *obj, int num)
1385{
1386 ELM_CHECK_WIDTYPE(obj, widtype);
1387 Widget_Data *wd = elm_widget_data_get(obj);
1388 if (!wd) return;
1389 if (num < DISPLAY_ITEM_NUM_MIN) num = DISPLAY_ITEM_NUM_MIN;
1390 wd->display_item_num = num;
1391 wd->display_item_num_by_api = EINA_TRUE;
1392}
1393
1394EAPI int
1395elm_diskselector_display_item_num_get(const Evas_Object *item)
1396{
1397 ELM_CHECK_WIDTYPE(item, widtype) (-1);
1398 Widget_Data *wd = elm_widget_data_get(item);
1399 if (!wd) return -1;
1400 return wd->display_item_num;
1401}
diff --git a/libraries/elementary/src/lib/elm_diskselector.h b/libraries/elementary/src/lib/elm_diskselector.h
new file mode 100644
index 0000000..76eed8d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_diskselector.h
@@ -0,0 +1,440 @@
1/**
2 * @defgroup Diskselector Diskselector
3 * @ingroup Elementary
4 *
5 * @image html img/widget/diskselector/preview-00.png
6 * @image latex img/widget/diskselector/preview-00.eps
7 *
8 * A diskselector is a kind of list widget. It scrolls horizontally,
9 * and can contain label and icon objects. Three items are displayed
10 * with the selected one in the middle.
11 *
12 * It can act like a circular list with round mode and labels can be
13 * reduced for a defined length for side items.
14 *
15 * Smart callbacks one can listen to:
16 * @li "selected" - when item is selected, i.e. scroller stops.
17 * @li "scroll,anim,start" - scrolling animation has started
18 * @li "scroll,anim,stop" - scrolling animation has stopped
19 * @li "scroll,drag,start" - dragging the diskselector has started
20 * @li "scroll,drag,stop" - dragging the diskselector has stopped
21 * @note The "scroll,anim,*" and "scroll,drag,*" signals are only emitted by
22 * user intervention.
23 *
24 * Available styles for it:
25 * - @c "default"
26 *
27 * Default content parts of the diskselector items that you can use for are:
28 * @li "icon" - An icon in the diskselector item
29 *
30 * Default text parts of the diskselector items that you can use for are:
31 * @li "default" - Label of the diskselector item
32 *
33 * Supported elm_object_item common APIs.
34 * @li @ref elm_object_item_part_text_set
35 * @li @ref elm_object_item_part_text_get
36 * @li @ref elm_object_item_part_content_set
37 * @li @ref elm_object_item_part_content_get
38 *
39 * List of examples:
40 * @li @ref diskselector_example_01
41 * @li @ref diskselector_example_02
42 */
43
44/**
45 * @addtogroup Diskselector
46 * @{
47 */
48
49/**
50 * Add a new diskselector widget to the given parent Elementary
51 * (container) object.
52 *
53 * @param parent The parent object.
54 * @return a new diskselector widget handle or @c NULL, on errors.
55 *
56 * This function inserts a new diskselector widget on the canvas.
57 *
58 * @ingroup Diskselector
59 */
60EAPI Evas_Object *elm_diskselector_add(Evas_Object *parent);
61
62/**
63 * Enable or disable round mode.
64 *
65 * @param obj The diskselector object.
66 * @param enabled @c EINA_TRUE to enable round mode or @c EINA_FALSE to
67 * disable it.
68 *
69 * Disabled by default. If round mode is enabled the items list will
70 * work like a circular list, so when the user reaches the last item,
71 * the first one will popup.
72 *
73 * @see elm_diskselector_round_enabled_get()
74 *
75 * @ingroup Diskselector
76 */
77EAPI void elm_diskselector_round_enabled_set(Evas_Object *obj, Eina_Bool enabled);
78
79/**
80 * Get a value whether round mode is enabled or not.
81 *
82 * @see elm_diskselector_round_enabled_set() for details.
83 *
84 * @param obj The diskselector object.
85 * @return @c EINA_TRUE means round mode is enabled. @c EINA_FALSE indicates
86 * it's disabled. If @p obj is @c NULL, @c EINA_FALSE is returned.
87 *
88 * @ingroup Diskselector
89 */
90EAPI Eina_Bool elm_diskselector_round_enabled_get(const Evas_Object *obj);
91
92/**
93 * Get the side labels max length.
94 *
95 * @see elm_diskselector_side_text_max_length_set() for details.
96 *
97 * @param obj The diskselector object.
98 * @return The max length defined for side labels, or 0 if not a valid
99 * diskselector.
100 *
101 * @ingroup Diskselector
102 */
103EAPI int elm_diskselector_side_text_max_length_get(const Evas_Object *obj);
104
105/**
106 * Set the side labels max length.
107 *
108 * @param obj The diskselector object.
109 * @param len The max length defined for side labels.
110 *
111 * Length is the number of characters of items' label that will be
112 * visible when it's set on side positions. It will just crop
113 * the string after defined size. E.g.:
114 *
115 * An item with label "January" would be displayed on side position as
116 * "Jan" if max length is set to 3, or "Janu", if this property
117 * is set to 4.
118 *
119 * When it's selected, the entire label will be displayed, except for
120 * width restrictions. In this case label will be cropped and "..."
121 * will be concatenated.
122 *
123 * Default side label max length is 3.
124 *
125 * This property will be applied over all items, included before or
126 * later this function call.
127 *
128 * @ingroup Diskselector
129 */
130EAPI void elm_diskselector_side_text_max_length_set(Evas_Object *obj, int len);
131
132/**
133 * Set the number of items to be displayed.
134 *
135 * @param obj The diskselector object.
136 * @param num The number of items the diskselector will display.
137 *
138 * Default value is 3, and also it's the minimum. If @p num is less
139 * than 3, it will be set to 3.
140 *
141 * Also, it can be set on theme, using data item @c display_item_num
142 * on group "elm/diskselector/item/X", where X is style set.
143 * E.g.:
144 *
145 * group { name: "elm/diskselector/item/X";
146 * data {
147 * item: "display_item_num" "5";
148 * }
149 *
150 * @ingroup Diskselector
151 */
152EAPI void elm_diskselector_display_item_num_set(Evas_Object *obj, int num);
153
154/**
155 * Get the number of items in the diskselector object.
156 *
157 * @param obj The diskselector object.
158 *
159 * @ingroup Diskselector
160 */
161EAPI int elm_diskselector_display_item_num_get(const Evas_Object *obj);
162
163/**
164 * Set bouncing behaviour when the scrolled content reaches an edge.
165 *
166 * Tell the internal scroller object whether it should bounce or not
167 * when it reaches the respective edges for each axis.
168 *
169 * @param obj The diskselector object.
170 * @param h_bounce Whether to bounce or not in the horizontal axis.
171 * @param v_bounce Whether to bounce or not in the vertical axis.
172 *
173 * @see elm_scroller_bounce_set()
174 *
175 * @ingroup Diskselector
176 */
177EAPI void elm_diskselector_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
178
179/**
180 * Get the bouncing behaviour of the internal scroller.
181 *
182 * Get whether the internal scroller should bounce when the edge of each
183 * axis is reached scrolling.
184 *
185 * @param obj The diskselector object.
186 * @param h_bounce Pointer to store the bounce state of the horizontal
187 * axis.
188 * @param v_bounce Pointer to store the bounce state of the vertical
189 * axis.
190 *
191 * @see elm_scroller_bounce_get()
192 * @see elm_diskselector_bounce_set()
193 *
194 * @ingroup Diskselector
195 */
196EAPI void elm_diskselector_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
197
198/**
199 * Get the scrollbar policy.
200 *
201 * @see elm_diskselector_scroller_policy_get() for details.
202 *
203 * @param obj The diskselector object.
204 * @param policy_h Pointer to store horizontal scrollbar policy.
205 * @param policy_v Pointer to store vertical scrollbar policy.
206 *
207 * @ingroup Diskselector
208 */
209EAPI void elm_diskselector_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
210
211/**
212 * Set the scrollbar policy.
213 *
214 * @param obj The diskselector object.
215 * @param policy_h Horizontal scrollbar policy.
216 * @param policy_v Vertical scrollbar policy.
217 *
218 * This sets the scrollbar visibility policy for the given scroller.
219 * #ELM_SCROLLER_POLICY_AUTO means the scrollbar is made visible if it
220 * is needed, and otherwise kept hidden. #ELM_SCROLLER_POLICY_ON turns
221 * it on all the time, and #ELM_SCROLLER_POLICY_OFF always keeps it off.
222 * This applies respectively for the horizontal and vertical scrollbars.
223 *
224 * The both are disabled by default, i.e., are set to
225 * #ELM_SCROLLER_POLICY_OFF.
226 *
227 * @ingroup Diskselector
228 */
229EAPI void elm_diskselector_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
230
231/**
232 * Remove all diskselector's items.
233 *
234 * @param obj The diskselector object.
235 *
236 * @see elm_object_item_del()
237 * @see elm_diskselector_item_append()
238 *
239 * @ingroup Diskselector
240 */
241EAPI void elm_diskselector_clear(Evas_Object *obj);
242
243/**
244 * Get a list of all the diskselector items.
245 *
246 * @param obj The diskselector object.
247 * @return An @c Eina_List of diskselector items, #Elm_Object_Item,
248 * or @c NULL on failure.
249 *
250 * @see elm_diskselector_item_append()
251 * @see elm_object_item_del()
252 * @see elm_diskselector_clear()
253 *
254 * @ingroup Diskselector
255 */
256EAPI const Eina_List *elm_diskselector_items_get(const Evas_Object *obj);
257
258/**
259 * Appends a new item to the diskselector object.
260 *
261 * @param obj The diskselector object.
262 * @param label The label of the diskselector item.
263 * @param icon The icon object to use at left side of the item. An
264 * icon can be any Evas object, but usually it is an icon created
265 * with elm_icon_add().
266 * @param func The function to call when the item is selected.
267 * @param data The data to associate with the item for related callbacks.
268 *
269 * @return The created item or @c NULL upon failure.
270 *
271 * A new item will be created and appended to the diskselector, i.e., will
272 * be set as last item. Also, if there is no selected item, it will
273 * be selected. This will always happens for the first appended item.
274 *
275 * If no icon is set, label will be centered on item position, otherwise
276 * the icon will be placed at left of the label, that will be shifted
277 * to the right.
278 *
279 * Items created with this method can be deleted with
280 * elm_object_item_del().
281 *
282 * Associated @p data can be properly freed when item is deleted if a
283 * callback function is set with elm_object_item_del_cb_set().
284 *
285 * If a function is passed as argument, it will be called every time this item
286 * is selected, i.e., the user stops the diskselector with this
287 * item on center position. If such function isn't needed, just passing
288 * @c NULL as @p func is enough. The same should be done for @p data.
289 *
290 * Simple example (with no function callback or data associated):
291 * @code
292 * disk = elm_diskselector_add(win);
293 * ic = elm_icon_add(win);
294 * elm_icon_file_set(ic, "path/to/image", NULL);
295 * elm_icon_resizable_set(ic, EINA_TRUE, EINA_TRUE);
296 * elm_diskselector_item_append(disk, "label", ic, NULL, NULL);
297 * @endcode
298 *
299 * @see elm_object_item_del()
300 * @see elm_diskselector_clear()
301 * @see elm_icon_add()
302 *
303 * @ingroup Diskselector
304 */
305EAPI Elm_Object_Item *elm_diskselector_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Smart_Cb func, const void *data);
306
307/**
308 * Get the selected item.
309 *
310 * @param obj The diskselector object.
311 * @return The selected diskselector item.
312 *
313 * The selected item can be unselected with function
314 * elm_diskselector_item_selected_set(), and the first item of
315 * diskselector will be selected.
316 *
317 * The selected item always will be centered on diskselector, with
318 * full label displayed, i.e., max length set to side labels won't
319 * apply on the selected item. More details on
320 * elm_diskselector_side_text_max_length_set().
321 *
322 * @ingroup Diskselector
323 */
324EAPI Elm_Object_Item *elm_diskselector_selected_item_get(const Evas_Object *obj);
325
326/**
327 * Set the selected state of an item.
328 *
329 * @param it The diskselector item
330 * @param selected The selected state
331 *
332 * This sets the selected state of the given item @p it.
333 * @c EINA_TRUE for selected, @c EINA_FALSE for not selected.
334 *
335 * If a new item is selected the previously selected will be unselected.
336 * Previously selected item can be get with function
337 * elm_diskselector_selected_item_get().
338 *
339 * If the item @p it is unselected, the first item of diskselector will
340 * be selected.
341 *
342 * Selected items will be visible on center position of diskselector.
343 * So if it was on another position before selected, or was invisible,
344 * diskselector will animate items until the selected item reaches center
345 * position.
346 *
347 * @see elm_diskselector_item_selected_get()
348 * @see elm_diskselector_selected_item_get()
349 *
350 * @ingroup Diskselector
351 */
352EAPI void elm_diskselector_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
353
354/*
355 * Get whether the @p item is selected or not.
356 *
357 * @param it The diskselector item.
358 * @return @c EINA_TRUE means item is selected. @c EINA_FALSE indicates
359 * it's not. If @p obj is @c NULL, @c EINA_FALSE is returned.
360 *
361 * @see elm_diskselector_selected_item_set() for details.
362 * @see elm_diskselector_item_selected_get()
363 *
364 * @ingroup Diskselector
365 */
366EAPI Eina_Bool elm_diskselector_item_selected_get(const Elm_Object_Item *it);
367
368/**
369 * Get the first item of the diskselector.
370 *
371 * @param obj The diskselector object.
372 * @return The first item, or @c NULL if none.
373 *
374 * The list of items follows append order. So it will return the first
375 * item appended to the widget that wasn't deleted.
376 *
377 * @see elm_diskselector_item_append()
378 * @see elm_diskselector_items_get()
379 *
380 * @ingroup Diskselector
381 */
382EAPI Elm_Object_Item *elm_diskselector_first_item_get(const Evas_Object *obj);
383
384/**
385 * Get the last item of the diskselector.
386 *
387 * @param obj The diskselector object.
388 * @return The last item, or @c NULL if none.
389 *
390 * The list of items follows append order. So it will return last first
391 * item appended to the widget that wasn't deleted.
392 *
393 * @see elm_diskselector_item_append()
394 * @see elm_diskselector_items_get()
395 *
396 * @ingroup Diskselector
397 */
398EAPI Elm_Object_Item *elm_diskselector_last_item_get(const Evas_Object *obj);
399
400/**
401 * Get the item before @p item in diskselector.
402 *
403 * @param it The diskselector item.
404 * @return The item before @p item, or @c NULL if none or on failure.
405 *
406 * The list of items follows append order. So it will return item appended
407 * just before @p item and that wasn't deleted.
408 *
409 * If it is the first item, @c NULL will be returned.
410 * First item can be get by elm_diskselector_first_item_get().
411 *
412 * @see elm_diskselector_item_append()
413 * @see elm_diskselector_items_get()
414 *
415 * @ingroup Diskselector
416 */
417EAPI Elm_Object_Item *elm_diskselector_item_prev_get(const Elm_Object_Item *it);
418
419/**
420 * Get the item after @p item in diskselector.
421 *
422 * @param it The diskselector item.
423 * @return The item after @p item, or @c NULL if none or on failure.
424 *
425 * The list of items follows append order. So it will return item appended
426 * just after @p item and that wasn't deleted.
427 *
428 * If it is the last item, @c NULL will be returned.
429 * Last item can be get by elm_diskselector_last_item_get().
430 *
431 * @see elm_diskselector_item_append()
432 * @see elm_diskselector_items_get()
433 *
434 * @ingroup Diskselector
435 */
436EAPI Elm_Object_Item *elm_diskselector_item_next_get(const Elm_Object_Item *it);
437
438/**
439 * @}
440 */
diff --git a/libraries/elementary/src/lib/elm_entry.c b/libraries/elementary/src/lib/elm_entry.c
new file mode 100644
index 0000000..cdf5f31
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_entry.c
@@ -0,0 +1,3934 @@
1#include <Elementary.h>
2#include <Elementary_Cursor.h>
3#include "elm_priv.h"
4#include "els_scroller.h"
5
6
7/* Maximum chunk size to be inserted to the entry at once
8 * FIXME: This size is arbitrary, should probably choose a better size.
9 * Possibly also find a way to set it to a low value for weak computers,
10 * and to a big value for better computers. */
11#define _CHUNK_SIZE 10000
12
13typedef struct _Mod_Api Mod_Api;
14
15typedef struct _Widget_Data Widget_Data;
16typedef struct _Elm_Entry_Context_Menu_Item Elm_Entry_Context_Menu_Item;
17typedef struct _Elm_Entry_Item_Provider Elm_Entry_Item_Provider;
18typedef struct _Elm_Entry_Markup_Filter Elm_Entry_Markup_Filter;
19
20struct _Widget_Data
21{
22 Evas_Object *ent, *scroller;
23 Evas_Object *hoversel;
24 Ecore_Job *deferred_recalc_job;
25 Ecore_Event_Handler *sel_notify_handler;
26 Ecore_Event_Handler *sel_clear_handler;
27 Ecore_Timer *longpress_timer;
28 Ecore_Timer *delay_write;
29 /* for deferred appending */
30 Ecore_Idler *append_text_idler;
31 char *append_text_left;
32 int append_text_position;
33 int append_text_len;
34 /* Only for clipboard */
35 const char *cut_sel;
36 const char *text;
37 const char *file;
38 Elm_Text_Format format;
39 Evas_Coord lastw, entmw, entmh;
40 Evas_Coord downx, downy;
41 Eina_List *items;
42 Eina_List *item_providers;
43 Eina_List *text_filters;
44 Eina_List *markup_filters;
45 Ecore_Job *hovdeljob;
46 Mod_Api *api; // module api if supplied
47 int cursor_pos;
48 Elm_Scroller_Policy policy_h, policy_v;
49 Elm_Wrap_Type linewrap;
50 Elm_Input_Panel_Layout input_panel_layout;
51 Elm_Autocapital_Type autocapital_type;
52 Elm_Input_Panel_Lang input_panel_lang;
53 Elm_Input_Panel_Return_Key_Type input_panel_return_key_type;
54 void *input_panel_imdata;
55 int input_panel_imdata_len;
56 struct
57 {
58 Evas_Object *hover_parent;
59 Evas_Object *pop, *hover;
60 const char *hover_style;
61 } anchor_hover;
62 Eina_Bool changed : 1;
63 Eina_Bool single_line : 1;
64 Eina_Bool password : 1;
65 Eina_Bool editable : 1;
66 Eina_Bool selection_asked : 1;
67 Eina_Bool have_selection : 1;
68 Eina_Bool selmode : 1;
69 Eina_Bool deferred_cur : 1;
70 Eina_Bool cur_changed : 1;
71 Eina_Bool disabled : 1;
72 Eina_Bool context_menu : 1;
73 Eina_Bool drag_selection_asked : 1;
74 Eina_Bool can_write : 1;
75 Eina_Bool autosave : 1;
76 Eina_Bool usedown : 1;
77 Eina_Bool scroll : 1;
78 Eina_Bool h_bounce : 1;
79 Eina_Bool v_bounce : 1;
80 Eina_Bool input_panel_enable : 1;
81 Eina_Bool prediction_allow : 1;
82 Eina_Bool input_panel_return_key_disabled : 1;
83 Eina_Bool autoreturnkey : 1;
84 Eina_Bool havetext : 1;
85 Elm_Cnp_Mode cnp_mode : 2;
86};
87
88struct _Elm_Entry_Context_Menu_Item
89{
90 Evas_Object *obj;
91 const char *label;
92 const char *icon_file;
93 const char *icon_group;
94 Elm_Icon_Type icon_type;
95 Evas_Smart_Cb func;
96 void *data;
97};
98
99struct _Elm_Entry_Item_Provider
100{
101 Evas_Object *(*func) (void *data, Evas_Object *entry, const char *item);
102 void *data;
103};
104
105struct _Elm_Entry_Markup_Filter
106{
107 Elm_Entry_Filter_Cb func;
108 void *data;
109};
110
111typedef enum _Length_Unit
112{
113 LENGTH_UNIT_CHAR,
114 LENGTH_UNIT_BYTE,
115 LENGTH_UNIT_LAST
116} Length_Unit;
117
118static const char *widtype = NULL;
119
120#ifdef HAVE_ELEMENTARY_X
121static Eina_Bool _drag_drop_cb(void *data, Evas_Object *obj, Elm_Selection_Data *);
122#endif
123static void _del_hook(Evas_Object *obj);
124static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
125static void _theme_hook(Evas_Object *obj);
126static void _disable_hook(Evas_Object *obj);
127static void _sizing_eval(Evas_Object *obj);
128static void _on_focus_hook(void *data, Evas_Object *obj);
129static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
130static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
131static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
132static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
133static const char *_getbase(Evas_Object *obj);
134static void _signal_entry_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
135static void _signal_selection_start(void *data, Evas_Object *obj, const char *emission, const char *source);
136static void _signal_selection_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
137static void _signal_selection_cleared(void *data, Evas_Object *obj, const char *emission, const char *source);
138static void _signal_entry_paste_request(void *data, Evas_Object *obj, const char *emission, const char *source);
139static void _signal_entry_copy_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
140static void _signal_entry_cut_notify(void *data, Evas_Object *obj, const char *emission, const char *source);
141static void _signal_cursor_changed(void *data, Evas_Object *obj, const char *emission, const char *source);
142static void _add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit unit);
143static void _entry_hover_anchor_clicked(void *data, Evas_Object *obj, void *event_info);
144
145static const char SIG_CHANGED[] = "changed";
146static const char SIG_CHANGED_USER[] = "changed,user";
147static const char SIG_ACTIVATED[] = "activated";
148static const char SIG_PRESS[] = "press";
149static const char SIG_LONGPRESSED[] = "longpressed";
150static const char SIG_CLICKED[] = "clicked";
151static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
152static const char SIG_CLICKED_TRIPLE[] = "clicked,triple";
153static const char SIG_FOCUSED[] = "focused";
154static const char SIG_UNFOCUSED[] = "unfocused";
155static const char SIG_SELECTION_PASTE[] = "selection,paste";
156static const char SIG_SELECTION_COPY[] = "selection,copy";
157static const char SIG_SELECTION_CUT[] = "selection,cut";
158static const char SIG_SELECTION_START[] = "selection,start";
159static const char SIG_SELECTION_CHANGED[] = "selection,changed";
160static const char SIG_SELECTION_CLEARED[] = "selection,cleared";
161static const char SIG_CURSOR_CHANGED[] = "cursor,changed";
162static const char SIG_CURSOR_CHANGED_MANUAL[] = "cursor,changed,manual";
163static const char SIG_ANCHOR_CLICKED[] = "anchor,clicked";
164static const char SIG_ANCHOR_HOVER_OPENED[] = "anchor,hover,opened";
165static const char SIG_ANCHOR_DOWN[] = "anchor,down";
166static const char SIG_ANCHOR_UP[] = "anchor,up";
167static const char SIG_ANCHOR_IN[] = "anchor,in";
168static const char SIG_ANCHOR_OUT[] = "anchor,out";
169static const char SIG_PREEDIT_CHANGED[] = "preedit,changed";
170static const char SIG_UNDO_REQUEST[] = "undo,request";
171static const char SIG_REDO_REQUEST[] = "redo,request";
172static const Evas_Smart_Cb_Description _signals[] = {
173 {SIG_CHANGED, ""},
174 {SIG_ACTIVATED, ""},
175 {SIG_PRESS, ""},
176 {SIG_LONGPRESSED, ""},
177 {SIG_CLICKED, ""},
178 {SIG_CLICKED_DOUBLE, ""},
179 {SIG_CLICKED_TRIPLE, ""},
180 {SIG_FOCUSED, ""},
181 {SIG_UNFOCUSED, ""},
182 {SIG_SELECTION_PASTE, ""},
183 {SIG_SELECTION_COPY, ""},
184 {SIG_SELECTION_CUT, ""},
185 {SIG_SELECTION_START, ""},
186 {SIG_SELECTION_CHANGED, ""},
187 {SIG_SELECTION_CLEARED, ""},
188 {SIG_CURSOR_CHANGED, ""},
189 {SIG_CURSOR_CHANGED_MANUAL, ""},
190 {SIG_ANCHOR_CLICKED, ""},
191 {SIG_ANCHOR_HOVER_OPENED, ""},
192 {SIG_ANCHOR_DOWN, ""},
193 {SIG_ANCHOR_UP, ""},
194 {SIG_ANCHOR_IN, ""},
195 {SIG_ANCHOR_OUT, ""},
196 {SIG_PREEDIT_CHANGED, ""},
197 {SIG_CHANGED_USER, ""},
198 {SIG_UNDO_REQUEST, ""},
199 {SIG_REDO_REQUEST, ""},
200 {NULL, NULL}
201};
202
203static Eina_List *entries = NULL;
204
205struct _Mod_Api
206{
207 void (*obj_hook) (Evas_Object *obj);
208 void (*obj_unhook) (Evas_Object *obj);
209 void (*obj_longpress) (Evas_Object *obj);
210};
211
212static Mod_Api *
213_module(Evas_Object *obj __UNUSED__)
214{
215 static Elm_Module *m = NULL;
216 if (m) goto ok; // already found - just use
217 if (!(m = _elm_module_find_as("entry/api"))) return NULL;
218 // get module api
219 m->api = malloc(sizeof(Mod_Api));
220 if (!m->api) return NULL;
221 ((Mod_Api *)(m->api) )->obj_hook = // called on creation
222 _elm_module_symbol_get(m, "obj_hook");
223 ((Mod_Api *)(m->api) )->obj_unhook = // called on deletion
224 _elm_module_symbol_get(m, "obj_unhook");
225 ((Mod_Api *)(m->api) )->obj_longpress = // called on long press menu
226 _elm_module_symbol_get(m, "obj_longpress");
227ok: // ok - return api
228 return m->api;
229}
230
231static char *
232_buf_append(char *buf, const char *str, int *len, int *alloc)
233{
234 int len2 = strlen(str);
235 if ((*len + len2) >= *alloc)
236 {
237 char *buf2 = realloc(buf, *alloc + len2 + 512);
238 if (!buf2) return NULL;
239 buf = buf2;
240 *alloc += (512 + len2);
241 }
242 strcpy(buf + *len, str);
243 *len += len2;
244 return buf;
245}
246
247static char *
248_load_file(const char *file)
249{
250 FILE *f;
251 size_t size;
252 int alloc = 0, len = 0;
253 char *text = NULL, buf[16384 + 1];
254
255 f = fopen(file, "rb");
256 if (!f) return NULL;
257 while ((size = fread(buf, 1, sizeof(buf) - 1, f)))
258 {
259 char *tmp_text;
260 buf[size] = 0;
261 tmp_text = _buf_append(text, buf, &len, &alloc);
262 if (!tmp_text) break;
263 text = tmp_text;
264 }
265 fclose(f);
266 return text;
267}
268
269static char *
270_load_plain(const char *file)
271{
272 char *text;
273
274 text = _load_file(file);
275 if (text)
276 {
277 char *text2;
278
279 text2 = elm_entry_utf8_to_markup(text);
280 free(text);
281 return text2;
282 }
283 return NULL;
284}
285
286static Eina_Bool
287_load(Evas_Object *obj)
288{
289 Widget_Data *wd = elm_widget_data_get(obj);
290 char *text;
291 if (!wd) return EINA_FALSE;
292 if (!wd->file)
293 {
294 elm_object_text_set(obj, "");
295 return EINA_TRUE;
296 }
297 switch (wd->format)
298 {
299 case ELM_TEXT_FORMAT_PLAIN_UTF8:
300 text = _load_plain(wd->file);
301 break;
302 case ELM_TEXT_FORMAT_MARKUP_UTF8:
303 text = _load_file(wd->file);
304 break;
305 default:
306 text = NULL;
307 break;
308 }
309 if (text)
310 {
311 elm_object_text_set(obj, text);
312 free(text);
313 return EINA_TRUE;
314 }
315 else
316 {
317 elm_object_text_set(obj, "");
318 return EINA_FALSE;
319 }
320}
321
322static void
323_save_markup_utf8(const char *file, const char *text)
324{
325 FILE *f;
326
327 if ((!text) || (!text[0]))
328 {
329 ecore_file_unlink(file);
330 return;
331 }
332 f = fopen(file, "wb");
333 if (!f)
334 {
335 // FIXME: report a write error
336 return;
337 }
338 fputs(text, f); // FIXME: catch error
339 fclose(f);
340}
341
342static void
343_save_plain_utf8(const char *file, const char *text)
344{
345 char *text2;
346
347 text2 = elm_entry_markup_to_utf8(text);
348 if (!text2)
349 return;
350 _save_markup_utf8(file, text2);
351 free(text2);
352}
353
354static void
355_save(Evas_Object *obj)
356{
357 Widget_Data *wd = elm_widget_data_get(obj);
358 if (!wd) return;
359 if (!wd->file) return;
360 switch (wd->format)
361 {
362 case ELM_TEXT_FORMAT_PLAIN_UTF8:
363 _save_plain_utf8(wd->file, elm_object_text_get(obj));
364 break;
365 case ELM_TEXT_FORMAT_MARKUP_UTF8:
366 _save_markup_utf8(wd->file, elm_object_text_get(obj));
367 break;
368 default:
369 break;
370 }
371}
372
373static Eina_Bool
374_delay_write(void *data)
375{
376 Widget_Data *wd = elm_widget_data_get(data);
377 if (!wd) return ECORE_CALLBACK_CANCEL;
378 _save(data);
379 wd->delay_write = NULL;
380 return ECORE_CALLBACK_CANCEL;
381}
382
383static void
384_elm_entry_update_guide(Evas_Object *obj, Eina_Bool havetext)
385{
386 Widget_Data *wd = elm_widget_data_get(obj);
387 if (!wd) return;
388 if ((havetext) && (!wd->havetext))
389 edje_object_signal_emit(wd->ent, "elm,guide,disabled", "elm");
390 else if ((!havetext) && (wd->havetext))
391 edje_object_signal_emit(wd->ent, "elm,guide,enabled", "elm");
392 wd->havetext = havetext;
393}
394
395static Elm_Entry_Markup_Filter *
396_filter_new(Elm_Entry_Filter_Cb func, void *data)
397{
398 Elm_Entry_Markup_Filter *tf = ELM_NEW(Elm_Entry_Markup_Filter);
399 if (!tf) return NULL;
400
401 tf->func = func;
402 if (func == elm_entry_filter_limit_size)
403 {
404 Elm_Entry_Filter_Limit_Size *lim = data, *lim2;
405
406 if (!data)
407 {
408 free(tf);
409 return NULL;
410 }
411 lim2 = malloc(sizeof(Elm_Entry_Filter_Limit_Size));
412 if (!lim2)
413 {
414 free(tf);
415 return NULL;
416 }
417 memcpy(lim2, lim, sizeof(Elm_Entry_Filter_Limit_Size));
418 tf->data = lim2;
419 }
420 else if (func == elm_entry_filter_accept_set)
421 {
422 Elm_Entry_Filter_Accept_Set *as = data, *as2;
423
424 if (!data)
425 {
426 free(tf);
427 return NULL;
428 }
429 as2 = malloc(sizeof(Elm_Entry_Filter_Accept_Set));
430 if (!as2)
431 {
432 free(tf);
433 return NULL;
434 }
435 if (as->accepted)
436 as2->accepted = eina_stringshare_add(as->accepted);
437 else
438 as2->accepted = NULL;
439 if (as->rejected)
440 as2->rejected = eina_stringshare_add(as->rejected);
441 else
442 as2->rejected = NULL;
443 tf->data = as2;
444 }
445 else
446 tf->data = data;
447 return tf;
448}
449
450static void
451_filter_free(Elm_Entry_Markup_Filter *tf)
452{
453 if (tf->func == elm_entry_filter_limit_size)
454 {
455 Elm_Entry_Filter_Limit_Size *lim = tf->data;
456 if (lim) free(lim);
457 }
458 else if (tf->func == elm_entry_filter_accept_set)
459 {
460 Elm_Entry_Filter_Accept_Set *as = tf->data;
461 if (as)
462 {
463 if (as->accepted) eina_stringshare_del(as->accepted);
464 if (as->rejected) eina_stringshare_del(as->rejected);
465 free(as);
466 }
467 }
468 free(tf);
469}
470
471static void
472_del_pre_hook(Evas_Object *obj)
473{
474 Widget_Data *wd = elm_widget_data_get(obj);
475 if (!wd) return;
476 if (wd->delay_write)
477 {
478 ecore_timer_del(wd->delay_write);
479 wd->delay_write = NULL;
480 if (wd->autosave) _save(obj);
481 }
482 elm_entry_anchor_hover_end(obj);
483 elm_entry_anchor_hover_parent_set(obj, NULL);
484}
485
486static void
487_del_hook(Evas_Object *obj)
488{
489 Widget_Data *wd = elm_widget_data_get(obj);
490 Elm_Entry_Context_Menu_Item *it;
491 Elm_Entry_Item_Provider *ip;
492 Elm_Entry_Markup_Filter *tf;
493
494 evas_event_freeze(evas_object_evas_get(obj));
495
496 if (wd->file) eina_stringshare_del(wd->file);
497
498 if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
499 if ((wd->api) && (wd->api->obj_unhook)) wd->api->obj_unhook(obj); // module - unhook
500
501 entries = eina_list_remove(entries, obj);
502#ifdef HAVE_ELEMENTARY_X
503 if (wd->sel_notify_handler)
504 ecore_event_handler_del(wd->sel_notify_handler);
505 if (wd->sel_clear_handler)
506 ecore_event_handler_del(wd->sel_clear_handler);
507#endif
508 if (wd->cut_sel) eina_stringshare_del(wd->cut_sel);
509 if (wd->text) eina_stringshare_del(wd->text);
510 if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
511 if (wd->append_text_idler)
512 {
513 ecore_idler_del(wd->append_text_idler);
514 free(wd->append_text_left);
515 wd->append_text_left = NULL;
516 wd->append_text_idler = NULL;
517 }
518 if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
519 EINA_LIST_FREE(wd->items, it)
520 {
521 eina_stringshare_del(it->label);
522 eina_stringshare_del(it->icon_file);
523 eina_stringshare_del(it->icon_group);
524 free(it);
525 }
526 EINA_LIST_FREE(wd->item_providers, ip)
527 {
528 free(ip);
529 }
530 EINA_LIST_FREE(wd->text_filters, tf)
531 {
532 _filter_free(tf);
533 }
534 EINA_LIST_FREE(wd->markup_filters, tf)
535 {
536 _filter_free(tf);
537 }
538 if (wd->delay_write) ecore_timer_del(wd->delay_write);
539 if (wd->input_panel_imdata) free(wd->input_panel_imdata);
540
541 if (wd->anchor_hover.hover_style) eina_stringshare_del(wd->anchor_hover.hover_style);
542 evas_event_thaw(evas_object_evas_get(obj));
543 evas_event_thaw_eval(evas_object_evas_get(obj));
544 free(wd);
545}
546
547static void
548_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
549{
550 Widget_Data *wd = elm_widget_data_get(obj);
551 edje_object_mirrored_set(wd->ent, rtl);
552 if (wd->anchor_hover.hover)
553 elm_widget_mirrored_set(wd->anchor_hover.hover, rtl);
554}
555
556static void
557_theme_hook(Evas_Object *obj)
558{
559 Widget_Data *wd = elm_widget_data_get(obj);
560 const char *t;
561
562 evas_event_freeze(evas_object_evas_get(obj));
563 _elm_widget_mirrored_reload(obj);
564 _mirrored_set(obj, elm_widget_mirrored_get(obj));
565
566 t = eina_stringshare_add(elm_object_text_get(obj));
567 _elm_theme_object_set(obj, wd->ent, "entry", _getbase(obj), elm_widget_style_get(obj));
568 if (_elm_config->desktop_entry)
569 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
570 elm_object_text_set(obj, t);
571 eina_stringshare_del(t);
572 if (elm_widget_disabled_get(obj))
573 edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
574 edje_object_part_text_input_panel_layout_set(wd->ent, "elm.text", wd->input_panel_layout);
575 edje_object_part_text_autocapital_type_set(wd->ent, "elm.text", wd->autocapital_type);
576 edje_object_part_text_prediction_allow_set(wd->ent, "elm.text", wd->prediction_allow);
577 edje_object_part_text_input_panel_enabled_set(wd->ent, "elm.text", wd->input_panel_enable);
578 edje_object_part_text_input_panel_imdata_set(wd->ent, "elm.text", wd->input_panel_imdata, wd->input_panel_imdata_len);
579 edje_object_part_text_input_panel_return_key_type_set(wd->ent, "elm.text", wd->input_panel_return_key_type);
580 edje_object_part_text_input_panel_return_key_disabled_set(wd->ent, "elm.text", wd->input_panel_return_key_disabled);
581
582 if (wd->cursor_pos != 0)
583 elm_entry_cursor_pos_set(obj, wd->cursor_pos);
584 if (elm_widget_focus_get(obj))
585 edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
586 edje_object_message_signal_process(wd->ent);
587 edje_object_scale_set(wd->ent, elm_widget_scale_get(obj) * _elm_config->scale);
588 if (wd->scroll)
589 {
590 const char *str;
591 Evas_Object *edj;
592
593 elm_smart_scroller_mirrored_set(wd->scroller, elm_widget_mirrored_get(obj));
594 elm_smart_scroller_object_theme_set(obj, wd->scroller, "scroller", "entry",
595 elm_widget_style_get(obj));
596 edj = elm_smart_scroller_edje_object_get(wd->scroller);
597 str = edje_object_data_get(edj, "focus_highlight");
598 if ((str) && (!strcmp(str, "on")))
599 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
600 else
601 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
602 }
603 _sizing_eval(obj);
604 wd->havetext = !wd->havetext;
605 _elm_entry_update_guide(obj, !wd->havetext);
606 evas_event_thaw(evas_object_evas_get(obj));
607 evas_event_thaw_eval(evas_object_evas_get(obj));
608}
609
610static void
611_disable_hook(Evas_Object *obj)
612{
613 Widget_Data *wd = elm_widget_data_get(obj);
614
615 if (elm_widget_disabled_get(obj))
616 {
617 edje_object_signal_emit(wd->ent, "elm,state,disabled", "elm");
618 wd->disabled = EINA_TRUE;
619 }
620 else
621 {
622 edje_object_signal_emit(wd->ent, "elm,state,enabled", "elm");
623 wd->disabled = EINA_FALSE;
624 }
625}
626
627static void
628_recalc_cursor_geometry(Evas_Object *obj)
629{
630 Widget_Data *wd = elm_widget_data_get(obj);
631 if (!wd) return;
632 evas_object_smart_callback_call(obj, SIG_CURSOR_CHANGED, NULL);
633 if (!wd->deferred_recalc_job)
634 {
635 Evas_Coord cx, cy, cw, ch;
636 edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
637 &cx, &cy, &cw, &ch);
638 if (wd->cur_changed)
639 {
640 elm_widget_show_region_set(obj, cx, cy, cw, ch, EINA_FALSE);
641 wd->cur_changed = EINA_FALSE;
642 }
643 }
644 else
645 wd->deferred_cur = EINA_TRUE;
646}
647
648static void
649_elm_deferred_recalc_job(void *data)
650{
651 Widget_Data *wd = elm_widget_data_get(data);
652 Evas_Coord minh = -1, resw = -1, minw = -1, fw = 0, fh = 0;
653 if (!wd) return;
654 wd->deferred_recalc_job = NULL;
655
656 evas_object_geometry_get(wd->ent, NULL, NULL, &resw, NULL);
657 edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, resw, 0);
658 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
659 /* This is a hack to workaround the way min size hints are treated.
660 * If the minimum width is smaller than the restricted width, it means
661 * the mininmum doesn't matter. */
662 if (minw <= resw)
663 {
664 Evas_Coord ominw = -1;
665 evas_object_size_hint_min_get(data, &ominw, NULL);
666 minw = ominw;
667 }
668
669 wd->entmw = minw;
670 wd->entmh = minh;
671
672 elm_coords_finger_size_adjust(1, &fw, 1, &fh);
673 if (wd->scroll)
674 {
675 Evas_Coord vmw = 0, vmh = 0;
676
677 edje_object_size_min_calc
678 (elm_smart_scroller_edje_object_get(wd->scroller),
679 &vmw, &vmh);
680 if (wd->single_line)
681 {
682 evas_object_size_hint_min_set(data, vmw, minh + vmh);
683 evas_object_size_hint_max_set(data, -1, minh + vmh);
684 }
685 else
686 {
687 evas_object_size_hint_min_set(data, vmw, vmh);
688 evas_object_size_hint_max_set(data, -1, -1);
689 }
690 }
691 else
692 {
693 if (wd->single_line)
694 {
695 evas_object_size_hint_min_set(data, minw, minh);
696 evas_object_size_hint_max_set(data, -1, minh);
697 }
698 else
699 {
700 evas_object_size_hint_min_set(data, fw, minh);
701 evas_object_size_hint_max_set(data, -1, -1);
702 }
703 }
704
705 if (wd->deferred_cur)
706 {
707 Evas_Coord cx, cy, cw, ch;
708 edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
709 &cx, &cy, &cw, &ch);
710 if (wd->cur_changed)
711 {
712 elm_widget_show_region_set(data, cx, cy, cw, ch, EINA_FALSE);
713 wd->cur_changed = EINA_FALSE;
714 }
715 }
716}
717
718static void
719_sizing_eval(Evas_Object *obj)
720{
721 Widget_Data *wd = elm_widget_data_get(obj);
722 Evas_Coord minw = -1, minh = -1;
723 Evas_Coord resw, resh;
724 if (!wd) return;
725
726 evas_object_geometry_get(obj, NULL, NULL, &resw, &resh);
727 if (wd->linewrap)
728 {
729 if ((resw == wd->lastw) && (!wd->changed)) return;
730 evas_event_freeze(evas_object_evas_get(obj));
731 wd->changed = EINA_FALSE;
732 wd->lastw = resw;
733 if (wd->scroll)
734 {
735 Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
736
737 evas_object_resize(wd->scroller, resw, resh);
738 edje_object_size_min_calc
739 (elm_smart_scroller_edje_object_get(wd->scroller),
740 &vmw, &vmh);
741 elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
742 edje_object_size_min_restricted_calc(wd->ent, &minw, &minh, vw, 0);
743 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
744 /* This is a hack to workaround the way min size hints are treated.
745 * If the minimum width is smaller than the restricted width, it means
746 * the mininmum doesn't matter. */
747 if (minw <= vw)
748 {
749 Evas_Coord ominw = -1;
750 evas_object_size_hint_min_get(wd->ent, &ominw, NULL);
751 minw = ominw;
752 }
753 wd->entmw = minw;
754 wd->entmh = minh;
755
756 if ((minw > 0) && (vw < minw)) vw = minw;
757 if (minh > vh) vh = minh;
758
759 if (wd->single_line) h = vmh + minh;
760 else h = vmh;
761 evas_object_resize(wd->ent, vw, vh);
762 evas_object_size_hint_min_set(obj, w, h);
763 if (wd->single_line)
764 evas_object_size_hint_max_set(obj, -1, h);
765 else
766 evas_object_size_hint_max_set(obj, -1, -1);
767 }
768 else
769 {
770 if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
771 wd->deferred_recalc_job = ecore_job_add(_elm_deferred_recalc_job, obj);
772 }
773 evas_event_thaw(evas_object_evas_get(obj));
774 evas_event_thaw_eval(evas_object_evas_get(obj));
775 }
776 else
777 {
778 if (!wd->changed) return;
779 evas_event_freeze(evas_object_evas_get(obj));
780 wd->changed = EINA_FALSE;
781 wd->lastw = resw;
782 if (wd->scroll)
783 {
784 Evas_Coord vw = 0, vh = 0, vmw = 0, vmh = 0, w = -1, h = -1;
785
786 edje_object_size_min_calc(wd->ent, &minw, &minh);
787 wd->entmw = minw;
788 wd->entmh = minh;
789 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
790
791 elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
792
793 if (minw > vw) vw = minw;
794 if (minh > vh) vh = minh;
795
796 evas_object_resize(wd->ent, vw, vh);
797 edje_object_size_min_calc
798 (elm_smart_scroller_edje_object_get(wd->scroller),
799 &vmw, &vmh);
800 if (wd->single_line) h = vmh + minh;
801 else h = vmh;
802 evas_object_size_hint_min_set(obj, w, h);
803 if (wd->single_line)
804 evas_object_size_hint_max_set(obj, -1, h);
805 else
806 evas_object_size_hint_max_set(obj, -1, -1);
807 }
808 else
809 {
810 edje_object_size_min_calc(wd->ent, &minw, &minh);
811 wd->entmw = minw;
812 wd->entmh = minh;
813 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
814 evas_object_size_hint_min_set(obj, minw, minh);
815 if (wd->single_line)
816 evas_object_size_hint_max_set(obj, -1, minh);
817 else
818 evas_object_size_hint_max_set(obj, -1, -1);
819 }
820 evas_event_thaw(evas_object_evas_get(obj));
821 evas_event_thaw_eval(evas_object_evas_get(obj));
822 }
823
824 _recalc_cursor_geometry(obj);
825}
826
827static void
828_check_enable_return_key(Evas_Object *obj)
829{
830 Widget_Data *wd = elm_widget_data_get(obj);
831 Eina_Bool return_key_disabled = EINA_FALSE;
832 if (!wd) return;
833
834 if (!wd->autoreturnkey) return;
835
836 if (elm_entry_is_empty(obj) == EINA_TRUE)
837 return_key_disabled = EINA_TRUE;
838
839 elm_entry_input_panel_return_key_disabled_set(obj, return_key_disabled);
840}
841
842static void
843_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
844{
845 Widget_Data *wd = elm_widget_data_get(obj);
846 Evas_Object *top = elm_widget_top_get(obj);
847 if (!wd) return;
848 if (!wd->editable) return;
849 if (elm_widget_focus_get(obj))
850 {
851 evas_object_focus_set(wd->ent, EINA_TRUE);
852 edje_object_signal_emit(wd->ent, "elm,action,focus", "elm");
853 if (top && wd->input_panel_enable)
854 elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_ON);
855 evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
856 _check_enable_return_key(obj);
857 }
858 else
859 {
860 edje_object_signal_emit(wd->ent, "elm,action,unfocus", "elm");
861 evas_object_focus_set(wd->ent, EINA_FALSE);
862 if (top && wd->input_panel_enable)
863 elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
864 evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
865 }
866}
867
868static void
869_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
870{
871 Widget_Data *wd = elm_widget_data_get(obj);
872 Evas_Object *edje;
873 Evas_Object *prev_content;
874 if ((!wd) || (!content)) return;
875
876 if (wd->scroll)
877 edje = elm_smart_scroller_edje_object_get(wd->scroller);
878 else
879 edje = wd->ent;
880
881 if (!part || !strcmp(part, "icon"))
882 {
883 prev_content = edje_object_part_swallow_get(edje, "elm.swallow.icon");
884 edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
885 }
886 else if (!strcmp(part, "end"))
887 {
888 prev_content = edje_object_part_swallow_get(edje, "elm.swallow.end");
889 edje_object_signal_emit(edje, "elm,action,show,end", "elm");
890 }
891 else
892 prev_content = edje_object_part_swallow_get(edje, part);
893
894 if (prev_content) evas_object_del(prev_content);
895
896 evas_event_freeze(evas_object_evas_get(obj));
897 elm_widget_sub_object_add(obj, content);
898
899 if (!part || !strcmp(part, "icon"))
900 edje_object_part_swallow(edje, "elm.swallow.icon", content);
901 else if (!strcmp(part, "end"))
902 edje_object_part_swallow(edje, "elm.swallow.end", content);
903 else
904 edje_object_part_swallow(edje, part, content);
905
906 _sizing_eval(obj);
907 evas_event_thaw(evas_object_evas_get(obj));
908 evas_event_thaw_eval(evas_object_evas_get(obj));
909}
910
911static Evas_Object *
912_content_unset_hook(Evas_Object *obj, const char *part)
913{
914 Widget_Data *wd = elm_widget_data_get(obj);
915 Evas_Object *content, *edje;
916 if (!wd) return NULL;
917
918 if (wd->scroll)
919 edje = elm_smart_scroller_edje_object_get(wd->scroller);
920 else
921 edje = wd->ent;
922
923 if (!part || !strcmp(part, "icon"))
924 {
925 edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
926 content = edje_object_part_swallow_get(edje, "elm.swallow.icon");
927 }
928 else if (!strcmp(part, "end"))
929 {
930 edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
931 content = edje_object_part_swallow_get(edje, "elm.swallow.end");
932 }
933 else
934 content = edje_object_part_swallow_get(edje, part);
935
936 edje_object_part_swallow(edje, part, NULL);
937 if (!content) return NULL;
938 evas_event_freeze(evas_object_evas_get(obj));
939 elm_widget_sub_object_del(obj, content);
940 edje_object_part_unswallow(wd->ent, content);
941 _sizing_eval(obj);
942 evas_event_thaw(evas_object_evas_get(obj));
943 evas_event_thaw_eval(evas_object_evas_get(obj));
944
945 return content;
946}
947
948static Evas_Object *
949_content_get_hook(const Evas_Object *obj, const char *part)
950{
951 Widget_Data *wd = elm_widget_data_get(obj);
952 Evas_Object *content = NULL, *edje;
953 if (!wd) return NULL;
954
955 if (wd->scroll)
956 edje = elm_smart_scroller_edje_object_get(wd->scroller);
957 else
958 edje = wd->ent;
959
960 if (!edje) return NULL;
961
962 if (!part || !strcmp(part, "icon"))
963 content = edje_object_part_swallow_get(edje, "elm.swallow.icon");
964 else if (!strcmp(part, "end"))
965 content = edje_object_part_swallow_get(edje, "elm.swallow.end");
966 else
967 content = edje_object_part_swallow_get(edje, part);
968
969 return content;
970}
971
972static void
973_translate_hook(Evas_Object *obj)
974{
975 evas_object_smart_callback_call(obj, "language,changed", NULL);
976}
977
978static void
979_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
980{
981 Widget_Data *wd = elm_widget_data_get(obj);
982 if (!wd) return;
983 edje_object_signal_emit(wd->ent, emission, source);
984 if (wd->scroller)
985 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scroller),
986 emission, source);
987}
988
989static void
990_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
991{
992 Widget_Data *wd = elm_widget_data_get(obj);
993 if (!wd) return;
994 edje_object_signal_callback_add(wd->ent, emission, source, func_cb, data);
995 if (wd->scroller)
996 edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scroller),
997 emission, source, func_cb, data);
998}
999
1000static void
1001_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
1002{
1003 Widget_Data *wd = elm_widget_data_get(obj);
1004 edje_object_signal_callback_del_full(wd->ent, emission, source, func_cb,
1005 data);
1006 if (wd->scroller)
1007 edje_object_signal_callback_del_full(elm_smart_scroller_edje_object_get(wd->scroller),
1008 emission, source, func_cb, data);
1009}
1010
1011static void
1012_on_focus_region_hook(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1013{
1014 Widget_Data *wd = elm_widget_data_get(obj);
1015 edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
1016}
1017
1018static void
1019_focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1020{
1021 Widget_Data *wd = elm_widget_data_get(obj);
1022 if (wd->scroll)
1023 elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
1024}
1025
1026static void
1027_show_region_hook(void *data, Evas_Object *obj)
1028{
1029 Widget_Data *wd = elm_widget_data_get(data);
1030 Evas_Coord x, y, w, h;
1031 if (!wd) return;
1032 elm_widget_show_region_get(obj, &x, &y, &w, &h);
1033 if (wd->scroll)
1034 elm_smart_scroller_child_region_show(wd->scroller, x, y, w, h);
1035}
1036
1037static void
1038_sub_del(void *data, Evas_Object *obj, void *event_info)
1039{
1040 Widget_Data *wd = data;
1041 Evas_Object *sub = event_info;
1042 Evas_Object *edje;
1043
1044 if (wd->scroll)
1045 edje = elm_smart_scroller_edje_object_get(wd->scroller);
1046 else
1047 edje = wd->ent;
1048
1049 if (sub == edje_object_part_swallow_get(edje, "elm.swallow.icon"))
1050 {
1051 edje_object_part_unswallow(edje, sub);
1052 if (edje)
1053 edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
1054 }
1055 else if (sub == edje_object_part_swallow_get(edje, "elm.swallow.end"))
1056 {
1057 edje_object_part_unswallow(edje, sub);
1058 if (edje)
1059 edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
1060 }
1061 _sizing_eval(obj);
1062}
1063
1064static void
1065_hoversel_position(Evas_Object *obj)
1066{
1067 Widget_Data *wd = elm_widget_data_get(obj);
1068 Evas_Coord cx, cy, cw, ch, x, y, mw, mh;
1069 if (!wd) return;
1070
1071 cx = cy = 0;
1072 cw = ch = 1;
1073 evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
1074 if (wd->usedown)
1075 {
1076 cx = wd->downx - x;
1077 cy = wd->downy - y;
1078 cw = 1;
1079 ch = 1;
1080 }
1081 else
1082 edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text",
1083 &cx, &cy, &cw, &ch);
1084 evas_object_size_hint_min_get(wd->hoversel, &mw, &mh);
1085 if (cw < mw)
1086 {
1087 cx += (cw - mw) / 2;
1088 cw = mw;
1089 }
1090 if (ch < mh)
1091 {
1092 cy += (ch - mh) / 2;
1093 ch = mh;
1094 }
1095 evas_object_move(wd->hoversel, x + cx, y + cy);
1096 evas_object_resize(wd->hoversel, cw, ch);
1097}
1098
1099static void
1100_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1101{
1102 Widget_Data *wd = elm_widget_data_get(data);
1103
1104 if (wd->hoversel) _hoversel_position(data);
1105}
1106
1107static void
1108_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1109{
1110 Widget_Data *wd = elm_widget_data_get(data);
1111 if (!wd) return;
1112
1113 if (wd->linewrap)
1114 {
1115 _sizing_eval(data);
1116 }
1117 else if (wd->scroll)
1118 {
1119 Evas_Coord vw = 0, vh = 0;
1120
1121 elm_smart_scroller_child_viewport_size_get(wd->scroller, &vw, &vh);
1122 if (vw < wd->entmw) vw = wd->entmw;
1123 if (vh < wd->entmh) vh = wd->entmh;
1124 evas_object_resize(wd->ent, vw, vh);
1125 }
1126 if (wd->hoversel) _hoversel_position(data);
1127}
1128
1129static void
1130_hover_del(void *data)
1131{
1132 Widget_Data *wd = elm_widget_data_get(data);
1133 if (!wd) return;
1134
1135 if (wd->hoversel)
1136 {
1137 evas_object_del(wd->hoversel);
1138 wd->hoversel = NULL;
1139 }
1140 wd->hovdeljob = NULL;
1141}
1142
1143static void
1144_dismissed(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1145{
1146 Widget_Data *wd = elm_widget_data_get(data);
1147 if (!wd) return;
1148 wd->usedown = 0;
1149 if (wd->hoversel) evas_object_hide(wd->hoversel);
1150 if (wd->selmode)
1151 {
1152 if (!_elm_config->desktop_entry)
1153 {
1154 if (!wd->password)
1155 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
1156 }
1157 }
1158 elm_widget_scroll_freeze_pop(data);
1159 if (wd->hovdeljob) ecore_job_del(wd->hovdeljob);
1160 wd->hovdeljob = ecore_job_add(_hover_del, data);
1161}
1162
1163static void
1164_select(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1165{
1166 Widget_Data *wd = elm_widget_data_get(data);
1167 if (!wd) return;
1168 wd->selmode = EINA_TRUE;
1169 edje_object_part_text_select_none(wd->ent, "elm.text");
1170 if (!_elm_config->desktop_entry)
1171 {
1172 if (!wd->password)
1173 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
1174 }
1175 edje_object_signal_emit(wd->ent, "elm,state,select,on", "elm");
1176 if (!_elm_config->desktop_entry)
1177 elm_widget_scroll_hold_push(data);
1178}
1179
1180static char *
1181_remove_item_tags(const char *str)
1182{
1183 char *ret;
1184 if (!str)
1185 return NULL;
1186
1187 Eina_Strbuf *buf = eina_strbuf_new();
1188 if (!buf)
1189 return NULL;
1190
1191 if (!eina_strbuf_append(buf, str))
1192 return NULL;
1193
1194 while (EINA_TRUE)
1195 {
1196 const char *temp = eina_strbuf_string_get(buf);
1197
1198 char *startTag = NULL;
1199 char *endTag = NULL;
1200
1201 startTag = strstr(temp, "<item");
1202 if (!startTag)
1203 startTag = strstr(temp, "</item");
1204 if (startTag)
1205 endTag = strstr(startTag, ">");
1206 else
1207 break;
1208 if (!endTag || startTag > endTag)
1209 break;
1210
1211 size_t sindex = startTag - temp;
1212 size_t eindex = endTag - temp + 1;
1213 if (!eina_strbuf_remove(buf, sindex, eindex))
1214 break;
1215 }
1216 ret = eina_strbuf_string_steal(buf);
1217 eina_strbuf_free(buf);
1218 return ret;
1219}
1220
1221void
1222_elm_entry_entry_paste(Evas_Object *obj, const char *entry)
1223{
1224 Widget_Data *wd = elm_widget_data_get(obj);
1225 char *str = NULL;
1226
1227 if (wd->cnp_mode == ELM_CNP_MODE_NO_IMAGE)
1228 {
1229 str = _remove_item_tags(entry);
1230 if (!str) str = strdup(entry);
1231 }
1232 else
1233 str = strdup(entry);
1234 if (!str) str = (char *)entry;
1235
1236 edje_object_part_text_user_insert(wd->ent, "elm.text", str);
1237 if (str != entry) free(str);
1238}
1239
1240static void
1241_paste(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1242{
1243 Widget_Data *wd = elm_widget_data_get(data);
1244 if (!wd) return;
1245 evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
1246 if (wd->sel_notify_handler)
1247 {
1248#ifdef HAVE_ELEMENTARY_X
1249 Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP;
1250 wd->selection_asked = EINA_TRUE;
1251 if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
1252 formats = ELM_SEL_FORMAT_TEXT;
1253 else if (wd->cnp_mode != ELM_CNP_MODE_NO_IMAGE)
1254 formats |= ELM_SEL_FORMAT_IMAGE;
1255 elm_cnp_selection_get(data, ELM_SEL_TYPE_CLIPBOARD, formats, NULL, NULL);
1256#endif
1257 }
1258}
1259
1260static void
1261_store_selection(Elm_Sel_Type seltype, Evas_Object *obj)
1262{
1263 Widget_Data *wd = elm_widget_data_get(obj);
1264 const char *sel;
1265
1266 if (!wd) return;
1267 sel = edje_object_part_text_selection_get(wd->ent, "elm.text");
1268 if ((!sel) || (!sel[0])) return; /* avoid deleting our own selection */
1269 elm_cnp_selection_set(obj, seltype, ELM_SEL_FORMAT_MARKUP, sel, strlen(sel));
1270 if (seltype == ELM_SEL_TYPE_CLIPBOARD)
1271 eina_stringshare_replace(&wd->cut_sel, sel);
1272}
1273
1274static void
1275_cut(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1276{
1277 Widget_Data *wd = elm_widget_data_get(data);
1278
1279 /* Store it */
1280 wd->selmode = EINA_FALSE;
1281 if (!_elm_config->desktop_entry)
1282 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1283 edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1284 if (!_elm_config->desktop_entry)
1285 elm_widget_scroll_hold_pop(data);
1286 _store_selection(ELM_SEL_TYPE_CLIPBOARD, data);
1287 edje_object_part_text_user_insert(wd->ent, "elm.text", "");
1288 _sizing_eval(data);
1289}
1290
1291static void
1292_copy(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1293{
1294 Widget_Data *wd = elm_widget_data_get(data);
1295 if (!wd) return;
1296 wd->selmode = EINA_FALSE;
1297 if (!_elm_config->desktop_entry)
1298 {
1299 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1300 edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1301 elm_widget_scroll_hold_pop(data);
1302 }
1303 _store_selection(ELM_SEL_TYPE_CLIPBOARD, data);
1304 // edje_object_part_text_select_none(wd->ent, "elm.text");
1305}
1306
1307static void
1308_cancel(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1309{
1310 Widget_Data *wd = elm_widget_data_get(data);
1311 if (!wd) return;
1312 wd->selmode = EINA_FALSE;
1313 if (!_elm_config->desktop_entry)
1314 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1315 edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
1316 if (!_elm_config->desktop_entry)
1317 elm_widget_scroll_hold_pop(data);
1318 edje_object_part_text_select_none(wd->ent, "elm.text");
1319}
1320
1321static void
1322_item_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1323{
1324 Elm_Entry_Context_Menu_Item *it = data;
1325 Evas_Object *obj2 = it->obj;
1326 if (it->func) it->func(it->data, obj2, NULL);
1327}
1328
1329static void
1330_menu_press(Evas_Object *obj)
1331{
1332 Widget_Data *wd = elm_widget_data_get(obj);
1333 Evas_Object *top;
1334 const Eina_List *l;
1335 const Elm_Entry_Context_Menu_Item *it;
1336 if (!wd) return;
1337 if ((wd->api) && (wd->api->obj_longpress))
1338 {
1339 wd->api->obj_longpress(obj);
1340 }
1341 else if (wd->context_menu)
1342 {
1343 const char *context_menu_orientation;
1344
1345 if (wd->hoversel) evas_object_del(wd->hoversel);
1346 else elm_widget_scroll_freeze_push(obj);
1347 wd->hoversel = elm_hoversel_add(obj);
1348 context_menu_orientation = edje_object_data_get
1349 (wd->ent, "context_menu_orientation");
1350 if ((context_menu_orientation) &&
1351 (!strcmp(context_menu_orientation, "horizontal")))
1352 elm_hoversel_horizontal_set(wd->hoversel, EINA_TRUE);
1353 elm_object_style_set(wd->hoversel, "entry");
1354 elm_widget_sub_object_add(obj, wd->hoversel);
1355 elm_object_text_set(wd->hoversel, "Text");
1356 top = elm_widget_top_get(obj);
1357 if (top) elm_hoversel_hover_parent_set(wd->hoversel, top);
1358 evas_object_smart_callback_add(wd->hoversel, "dismissed", _dismissed, obj);
1359 if (wd->have_selection)
1360 {
1361 if (!wd->password)
1362 {
1363 if (wd->have_selection)
1364 {
1365 elm_hoversel_item_add(wd->hoversel, E_("Copy"), NULL, ELM_ICON_NONE,
1366 _copy, obj);
1367 if (wd->editable)
1368 elm_hoversel_item_add(wd->hoversel, E_("Cut"), NULL, ELM_ICON_NONE,
1369 _cut, obj);
1370 }
1371 elm_hoversel_item_add(wd->hoversel, E_("Cancel"), NULL, ELM_ICON_NONE,
1372 _cancel, obj);
1373 }
1374 }
1375 else
1376 {
1377 if (!wd->selmode)
1378 {
1379 if (!_elm_config->desktop_entry)
1380 {
1381 if (!wd->password)
1382 elm_hoversel_item_add(wd->hoversel, E_("Select"), NULL, ELM_ICON_NONE,
1383 _select, obj);
1384 }
1385 if (elm_selection_selection_has_owner())
1386 {
1387 if (wd->editable)
1388 elm_hoversel_item_add(wd->hoversel, E_("Paste"), NULL, ELM_ICON_NONE,
1389 _paste, obj);
1390 }
1391 }
1392 }
1393 EINA_LIST_FOREACH(wd->items, l, it)
1394 {
1395 elm_hoversel_item_add(wd->hoversel, it->label, it->icon_file,
1396 it->icon_type, _item_clicked, it);
1397 }
1398 if (wd->hoversel)
1399 {
1400 _hoversel_position(obj);
1401 evas_object_show(wd->hoversel);
1402 elm_hoversel_hover_begin(wd->hoversel);
1403 }
1404 if (!_elm_config->desktop_entry)
1405 {
1406 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
1407 edje_object_part_text_select_abort(wd->ent, "elm.text");
1408 }
1409 }
1410}
1411
1412static Eina_Bool
1413_long_press(void *data)
1414{
1415 Widget_Data *wd = elm_widget_data_get(data);
1416 if (!wd) return ECORE_CALLBACK_CANCEL;
1417 if (!_elm_config->desktop_entry)
1418 _menu_press(data);
1419 wd->longpress_timer = NULL;
1420 evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
1421 return ECORE_CALLBACK_CANCEL;
1422}
1423
1424static void
1425_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1426{
1427 Widget_Data *wd = elm_widget_data_get(data);
1428 Evas_Event_Mouse_Down *ev = event_info;
1429 if (!wd) return;
1430 if (wd->disabled) return;
1431 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1432 wd->downx = ev->canvas.x;
1433 wd->downy = ev->canvas.y;
1434 if (ev->button == 1)
1435 {
1436 if (wd->longpress_timer) ecore_timer_del(wd->longpress_timer);
1437 wd->longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
1438 }
1439}
1440
1441static void
1442_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1443{
1444 Widget_Data *wd = elm_widget_data_get(data);
1445 Evas_Event_Mouse_Up *ev = event_info;
1446 if (!wd) return;
1447 if (wd->disabled) return;
1448 if (ev->button == 1)
1449 {
1450 if (wd->longpress_timer)
1451 {
1452 ecore_timer_del(wd->longpress_timer);
1453 wd->longpress_timer = NULL;
1454 }
1455 }
1456 else if ((ev->button == 3) && (!_elm_config->desktop_entry))
1457 {
1458 wd->usedown = 1;
1459 _menu_press(data);
1460 }
1461}
1462
1463static void
1464_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1465{
1466 Widget_Data *wd = elm_widget_data_get(data);
1467 Evas_Event_Mouse_Move *ev = event_info;
1468 if (!wd) return;
1469 if (wd->disabled) return;
1470 if (!wd->selmode)
1471 {
1472 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1473 {
1474 if (wd->longpress_timer)
1475 {
1476 ecore_timer_del(wd->longpress_timer);
1477 wd->longpress_timer = NULL;
1478 }
1479 }
1480 else if (wd->longpress_timer)
1481 {
1482 Evas_Coord dx, dy;
1483
1484 dx = wd->downx - ev->cur.canvas.x;
1485 dx *= dx;
1486 dy = wd->downy - ev->cur.canvas.y;
1487 dy *= dy;
1488 if ((dx + dy) >
1489 ((_elm_config->finger_size / 2) *
1490 (_elm_config->finger_size / 2)))
1491 {
1492 ecore_timer_del(wd->longpress_timer);
1493 wd->longpress_timer = NULL;
1494 }
1495 }
1496 }
1497 else if (wd->longpress_timer)
1498 {
1499 Evas_Coord dx, dy;
1500
1501 dx = wd->downx - ev->cur.canvas.x;
1502 dx *= dx;
1503 dy = wd->downy - ev->cur.canvas.y;
1504 dy *= dy;
1505 if ((dx + dy) >
1506 ((_elm_config->finger_size / 2) *
1507 (_elm_config->finger_size / 2)))
1508 {
1509 ecore_timer_del(wd->longpress_timer);
1510 wd->longpress_timer = NULL;
1511 }
1512 }
1513}
1514
1515static const char *
1516_getbase(Evas_Object *obj)
1517{
1518 Widget_Data *wd = elm_widget_data_get(obj);
1519 if (!wd) return "base";
1520 if (wd->editable)
1521 {
1522 if (wd->password) return "base-password";
1523 else
1524 {
1525 if (wd->single_line) return "base-single";
1526 else
1527 {
1528 switch (wd->linewrap)
1529 {
1530 case ELM_WRAP_CHAR:
1531 return "base-charwrap";
1532 case ELM_WRAP_WORD:
1533 return "base";
1534 case ELM_WRAP_MIXED:
1535 return "base-mixedwrap";
1536 case ELM_WRAP_NONE:
1537 default:
1538 return "base-nowrap";
1539 }
1540 }
1541 }
1542 }
1543 else
1544 {
1545 if (wd->password) return "base-password";
1546 else
1547 {
1548 if (wd->single_line) return "base-single-noedit";
1549 else
1550 {
1551 switch (wd->linewrap)
1552 {
1553 case ELM_WRAP_CHAR:
1554 return "base-noedit-charwrap";
1555 case ELM_WRAP_WORD:
1556 return "base-noedit";
1557 case ELM_WRAP_MIXED:
1558 return "base-noedit-mixedwrap";
1559 case ELM_WRAP_NONE:
1560 default:
1561 return "base-nowrap-noedit";
1562 }
1563 }
1564 }
1565 }
1566}
1567
1568static void
1569_entry_changed_common_handling(void *data, const char *event)
1570{
1571 Widget_Data *wd = elm_widget_data_get(data);
1572 Evas_Coord minh;
1573 const char *text;
1574 if (!wd) return;
1575 evas_event_freeze(evas_object_evas_get(data));
1576 wd->changed = EINA_TRUE;
1577 /* Reset the size hints which are no more relevant.
1578 * Keep the height, this is a hack, but doesn't really matter
1579 * cause we'll re-eval in a moment. */
1580 evas_object_size_hint_min_get(data, NULL, &minh);
1581 evas_object_size_hint_min_set(data, -1, minh);
1582 _sizing_eval(data);
1583 if (wd->text) eina_stringshare_del(wd->text);
1584 wd->text = NULL;
1585 if (wd->delay_write)
1586 {
1587 ecore_timer_del(wd->delay_write);
1588 wd->delay_write = NULL;
1589 }
1590 evas_event_thaw(evas_object_evas_get(data));
1591 evas_event_thaw_eval(evas_object_evas_get(data));
1592 if ((wd->autosave) && (wd->file))
1593 wd->delay_write = ecore_timer_add(2.0, _delay_write, data);
1594 /* callback - this could call callbacks that delete the entry... thus...
1595 * any access to wd after this could be invalid */
1596 evas_object_smart_callback_call(data, event, NULL);
1597 _check_enable_return_key(data);
1598 text = edje_object_part_text_get(wd->ent, "elm.text");
1599 if (text)
1600 {
1601 if (text[0])
1602 _elm_entry_update_guide(data, EINA_TRUE);
1603 else
1604 _elm_entry_update_guide(data, EINA_FALSE);
1605 }
1606}
1607
1608static void
1609_signal_entry_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1610{
1611 _entry_changed_common_handling(data, SIG_CHANGED);
1612}
1613
1614static void
1615_signal_entry_changed_user(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1616{
1617 Elm_Entry_Change_Info info;
1618 Edje_Entry_Change_Info *edje_info = (Edje_Entry_Change_Info *)
1619 edje_object_signal_callback_extra_data_get();
1620 if (edje_info)
1621 {
1622 memcpy(&info, edje_info, sizeof(info));
1623 evas_object_smart_callback_call(data, SIG_CHANGED_USER, &info);
1624 }
1625 else
1626 {
1627 evas_object_smart_callback_call(data, SIG_CHANGED_USER, NULL);
1628 }
1629}
1630
1631static void
1632_signal_preedit_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1633{
1634 _entry_changed_common_handling(data, SIG_PREEDIT_CHANGED);
1635}
1636
1637static void
1638_signal_undo_request(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1639{
1640 evas_object_smart_callback_call(data, SIG_UNDO_REQUEST, NULL);
1641}
1642
1643static void
1644_signal_redo_request(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1645{
1646 evas_object_smart_callback_call(data, SIG_REDO_REQUEST, NULL);
1647}
1648
1649static void
1650_signal_selection_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1651{
1652 Widget_Data *wd = elm_widget_data_get(data);
1653 const Eina_List *l;
1654 Evas_Object *entry;
1655 if (!wd) return;
1656 EINA_LIST_FOREACH(entries, l, entry)
1657 {
1658 if (entry != data) elm_entry_select_none(entry);
1659 }
1660 wd->have_selection = EINA_TRUE;
1661 evas_object_smart_callback_call(data, SIG_SELECTION_START, NULL);
1662#ifdef HAVE_ELEMENTARY_X
1663 if (wd->sel_notify_handler)
1664 {
1665 const char *txt = elm_entry_selection_get(data);
1666 Evas_Object *top;
1667
1668 top = elm_widget_top_get(data);
1669 if (txt && top && (elm_win_xwindow_get(top)))
1670 elm_cnp_selection_set(data, ELM_SEL_TYPE_PRIMARY,
1671 ELM_SEL_FORMAT_MARKUP, txt, strlen(txt));
1672 }
1673#endif
1674}
1675
1676static void
1677_signal_selection_all(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1678{
1679 Widget_Data *wd = elm_widget_data_get(data);
1680 if (!wd) return;
1681 elm_entry_select_all(data);
1682}
1683
1684static void
1685_signal_selection_none(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1686{
1687 Widget_Data *wd = elm_widget_data_get(data);
1688 if (!wd) return;
1689 elm_entry_select_none(data);
1690}
1691
1692static void
1693_signal_selection_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1694{
1695 Widget_Data *wd = elm_widget_data_get(data);
1696 if (!wd) return;
1697 wd->have_selection = EINA_TRUE;
1698 evas_object_smart_callback_call(data, SIG_SELECTION_CHANGED, NULL);
1699 _store_selection(ELM_SEL_TYPE_PRIMARY, data);
1700}
1701
1702static void
1703_signal_selection_cleared(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1704{
1705 Widget_Data *wd = elm_widget_data_get(data);
1706 if (!wd) return;
1707 if (!wd->have_selection) return;
1708 wd->have_selection = EINA_FALSE;
1709 evas_object_smart_callback_call(data, SIG_SELECTION_CLEARED, NULL);
1710 if (wd->sel_notify_handler)
1711 {
1712 if (wd->cut_sel)
1713 {
1714#ifdef HAVE_ELEMENTARY_X
1715 Evas_Object *top;
1716
1717 top = elm_widget_top_get(data);
1718 if ((top) && (elm_win_xwindow_get(top)))
1719 elm_cnp_selection_set(data, ELM_SEL_TYPE_PRIMARY,
1720 ELM_SEL_FORMAT_MARKUP, wd->cut_sel,
1721 strlen(wd->cut_sel));
1722#endif
1723 eina_stringshare_del(wd->cut_sel);
1724 wd->cut_sel = NULL;
1725 }
1726 else
1727 {
1728#ifdef HAVE_ELEMENTARY_X
1729 Evas_Object *top;
1730
1731 top = elm_widget_top_get(data);
1732 if ((top) && (elm_win_xwindow_get(top)))
1733 elm_object_cnp_selection_clear(data, ELM_SEL_TYPE_PRIMARY);
1734#endif
1735 }
1736 }
1737}
1738
1739static void
1740_signal_entry_paste_request(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
1741{
1742 Widget_Data *wd = elm_widget_data_get(data);
1743#ifdef HAVE_ELEMENTARY_X
1744 Elm_Sel_Type type = (emission[sizeof("ntry,paste,request,")] == '1') ?
1745 ELM_SEL_TYPE_PRIMARY : ELM_SEL_TYPE_CLIPBOARD;
1746#endif
1747
1748 if (!wd) return;
1749 if (!wd->editable) return;
1750 evas_object_smart_callback_call(data, SIG_SELECTION_PASTE, NULL);
1751 if (wd->sel_notify_handler)
1752 {
1753#ifdef HAVE_ELEMENTARY_X
1754 Evas_Object *top;
1755
1756 top = elm_widget_top_get(data);
1757 if ((top) && (elm_win_xwindow_get(top)))
1758 {
1759 wd->selection_asked = EINA_TRUE;
1760 Elm_Sel_Format formats = ELM_SEL_FORMAT_MARKUP;
1761 if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
1762 formats = ELM_SEL_FORMAT_TEXT;
1763 else if (wd->cnp_mode != ELM_CNP_MODE_NO_IMAGE)
1764 formats |= ELM_SEL_FORMAT_IMAGE;
1765 elm_cnp_selection_get(data, type, formats,
1766 NULL, NULL);
1767 }
1768#endif
1769 }
1770}
1771
1772static void
1773_signal_entry_copy_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1774{
1775 evas_object_smart_callback_call(data, SIG_SELECTION_COPY, NULL);
1776 _copy(data, NULL, NULL);
1777}
1778
1779static void
1780_signal_entry_cut_notify(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1781{
1782 evas_object_smart_callback_call(data, SIG_SELECTION_CUT, NULL);
1783 _cut(data, NULL, NULL);
1784}
1785
1786static void
1787_signal_cursor_changed(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1788{
1789 Widget_Data *wd = elm_widget_data_get(data);
1790 if (!wd) return;
1791 wd->cursor_pos = edje_object_part_text_cursor_pos_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
1792 wd->cur_changed = EINA_TRUE;
1793 _recalc_cursor_geometry(data);
1794}
1795
1796static void
1797_signal_cursor_changed_manual(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1798{
1799 evas_object_smart_callback_call(data, SIG_CURSOR_CHANGED_MANUAL, NULL);
1800}
1801
1802
1803static void
1804_signal_anchor_geoms_do_things_with(Widget_Data *wd, Elm_Entry_Anchor_Info *ei)
1805{
1806 const Eina_List *geoms, *l;
1807 Evas_Textblock_Rectangle *r;
1808 Evas_Coord px, py, x, y;
1809
1810 geoms = edje_object_part_text_anchor_geometry_get(wd->ent, "elm.text", ei->name);
1811 if (!geoms) return;
1812
1813
1814 evas_object_geometry_get(wd->ent, &x, &y, NULL, NULL);
1815 evas_pointer_canvas_xy_get(evas_object_evas_get(wd->ent), &px, &py);
1816 EINA_LIST_FOREACH(geoms, l, r)
1817 {
1818 if (((r->x + x) <= px) && ((r->y + y) <= py) &&
1819 ((r->x + x + r->w) > px) && ((r->y + y + r->h) > py))
1820 {
1821 ei->x = r->x + x;
1822 ei->y = r->y + y;
1823 ei->w = r->w;
1824 ei->h = r->h;
1825 break;
1826 }
1827 }
1828}
1829
1830static void
1831_signal_anchor_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1832{
1833 Widget_Data *wd = elm_widget_data_get(data);
1834 Elm_Entry_Anchor_Info ei;
1835 const char *p;
1836 char *p2;
1837 if (!wd) return;
1838 p = emission + sizeof("nchor,mouse,down,");
1839 ei.button = strtol(p, &p2, 10);
1840 ei.name = p2 + 1;
1841 ei.x = ei.y = ei.w = ei.h = 0;
1842
1843 _signal_anchor_geoms_do_things_with(wd, &ei);
1844
1845 if (!wd->disabled)
1846 evas_object_smart_callback_call(data, SIG_ANCHOR_DOWN, &ei);
1847}
1848
1849static void
1850_signal_anchor_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1851{
1852 Widget_Data *wd = elm_widget_data_get(data);
1853 Elm_Entry_Anchor_Info ei;
1854 const char *p;
1855 char *p2;
1856 if (!wd) return;
1857 p = emission + sizeof("nchor,mouse,up,");
1858 ei.button = strtol(p, &p2, 10);
1859 ei.name = p2 + 1;
1860 ei.x = ei.y = ei.w = ei.h = 0;
1861
1862 _signal_anchor_geoms_do_things_with(wd, &ei);
1863
1864 if (!wd->disabled)
1865 evas_object_smart_callback_call(data, SIG_ANCHOR_UP, &ei);
1866}
1867
1868static void
1869_signal_anchor_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
1870{
1871 Widget_Data *wd = elm_widget_data_get(data);
1872 Elm_Entry_Anchor_Info ei;
1873 const char *p;
1874 char *p2;
1875 if (!wd) return;
1876 p = emission + sizeof("nchor,mouse,clicked,");
1877 ei.button = strtol(p, &p2, 10);
1878 ei.name = p2 + 1;
1879 ei.x = ei.y = ei.w = ei.h = 0;
1880
1881 _signal_anchor_geoms_do_things_with(wd, &ei);
1882
1883 if (!wd->disabled)
1884 {
1885 evas_object_smart_callback_call(data, SIG_ANCHOR_CLICKED, &ei);
1886
1887 if (!_elm_config->desktop_entry)
1888 _entry_hover_anchor_clicked(data, data, &ei);
1889 }
1890}
1891
1892static void
1893_signal_anchor_move(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1894{
1895 Widget_Data *wd = elm_widget_data_get(data);
1896 if (!wd) return;
1897}
1898
1899static void
1900_signal_anchor_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1901{
1902 Widget_Data *wd = elm_widget_data_get(data);
1903 Elm_Entry_Anchor_Info ei;
1904 if (!wd) return;
1905 ei.name = emission + sizeof("nchor,mouse,in,");
1906 ei.button = 0;
1907 ei.x = ei.y = ei.w = ei.h = 0;
1908
1909 _signal_anchor_geoms_do_things_with(wd, &ei);
1910
1911 if (!wd->disabled)
1912 evas_object_smart_callback_call(data, SIG_ANCHOR_IN, &ei);
1913}
1914
1915static void
1916_signal_anchor_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1917{
1918 Widget_Data *wd = elm_widget_data_get(data);
1919 Elm_Entry_Anchor_Info ei;
1920 if (!wd) return;
1921 ei.name = emission + sizeof("nchor,mouse,out,");
1922 ei.button = 0;
1923 ei.x = ei.y = ei.w = ei.h = 0;
1924
1925 _signal_anchor_geoms_do_things_with(wd, &ei);
1926
1927 if (!wd->disabled)
1928 evas_object_smart_callback_call(data, SIG_ANCHOR_OUT, &ei);
1929}
1930
1931static void
1932_signal_key_enter(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1933{
1934 Widget_Data *wd = elm_widget_data_get(data);
1935 if (!wd) return;
1936 evas_object_smart_callback_call(data, SIG_ACTIVATED, NULL);
1937}
1938
1939static void
1940_signal_mouse_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1941{
1942 Widget_Data *wd = elm_widget_data_get(data);
1943 if (!wd) return;
1944 evas_object_smart_callback_call(data, SIG_PRESS, NULL);
1945}
1946
1947static void
1948_signal_mouse_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1949{
1950 Widget_Data *wd = elm_widget_data_get(data);
1951 if (!wd) return;
1952 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
1953}
1954
1955static void
1956_signal_mouse_double(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1957{
1958 Widget_Data *wd = elm_widget_data_get(data);
1959 if (!wd) return;
1960 evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
1961}
1962
1963static void
1964_signal_mouse_triple(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1965{
1966 Widget_Data *wd = elm_widget_data_get(data);
1967 if (!wd) return;
1968 evas_object_smart_callback_call(data, SIG_CLICKED_TRIPLE, NULL);
1969}
1970
1971#ifdef HAVE_ELEMENTARY_X
1972static Eina_Bool
1973_event_selection_notify(void *data, int type __UNUSED__, void *event)
1974{
1975 Widget_Data *wd = elm_widget_data_get(data);
1976 Ecore_X_Event_Selection_Notify *ev = event;
1977 if (!wd) return ECORE_CALLBACK_PASS_ON;
1978 if ((!wd->selection_asked) && (!wd->drag_selection_asked))
1979 return ECORE_CALLBACK_PASS_ON;
1980
1981 if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
1982 (ev->selection == ECORE_X_SELECTION_PRIMARY))
1983 {
1984 Ecore_X_Selection_Data_Text *text_data;
1985
1986 text_data = ev->data;
1987 if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
1988 {
1989 if (text_data->text)
1990 {
1991 char *txt = _elm_util_text_to_mkup(text_data->text);
1992
1993 if (txt)
1994 {
1995 elm_entry_entry_insert(data, txt);
1996 free(txt);
1997 }
1998 }
1999 }
2000 wd->selection_asked = EINA_FALSE;
2001 }
2002 else if (ev->selection == ECORE_X_SELECTION_XDND)
2003 {
2004 Ecore_X_Selection_Data_Text *text_data;
2005
2006 text_data = ev->data;
2007 if (text_data->data.content == ECORE_X_SELECTION_CONTENT_TEXT)
2008 {
2009 if (text_data->text)
2010 {
2011 char *txt = _elm_util_text_to_mkup(text_data->text);
2012
2013 if (txt)
2014 {
2015 /* Massive FIXME: this should be at the drag point */
2016 elm_entry_entry_insert(data, txt);
2017 free(txt);
2018 }
2019 }
2020 }
2021 wd->drag_selection_asked = EINA_FALSE;
2022
2023 ecore_x_dnd_send_finished();
2024
2025 }
2026 return ECORE_CALLBACK_PASS_ON;
2027}
2028
2029static Eina_Bool
2030_event_selection_clear(void *data __UNUSED__, int type __UNUSED__, void *event __UNUSED__)
2031{
2032 Widget_Data *wd = elm_widget_data_get(data);
2033 Ecore_X_Event_Selection_Clear *ev = event;
2034 if (!wd) return ECORE_CALLBACK_PASS_ON;
2035 if (!wd->have_selection) return ECORE_CALLBACK_PASS_ON;
2036 if ((ev->selection == ECORE_X_SELECTION_CLIPBOARD) ||
2037 (ev->selection == ECORE_X_SELECTION_PRIMARY))
2038 {
2039 elm_entry_select_none(data);
2040 }
2041 return ECORE_CALLBACK_PASS_ON;
2042}
2043
2044static Eina_Bool
2045_drag_drop_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Selection_Data *drop)
2046{
2047 Widget_Data *wd;
2048 Eina_Bool rv;
2049
2050 wd = elm_widget_data_get(obj);
2051 if (!wd) return EINA_FALSE;
2052 printf("Inserting at (%d,%d) %s\n",drop->x,drop->y,(char*)drop->data);
2053
2054 edje_object_part_text_cursor_copy(wd->ent, "elm.text",
2055 EDJE_CURSOR_MAIN,/*->*/EDJE_CURSOR_USER);
2056 rv = edje_object_part_text_cursor_coord_set(wd->ent,"elm.text",
2057 EDJE_CURSOR_MAIN,drop->x,drop->y);
2058 if (!rv) printf("Warning: Failed to position cursor: paste anyway\n");
2059 elm_entry_entry_insert(obj, drop->data);
2060 edje_object_part_text_cursor_copy(wd->ent, "elm.text",
2061 EDJE_CURSOR_USER,/*->*/EDJE_CURSOR_MAIN);
2062
2063 return EINA_TRUE;
2064}
2065#endif
2066
2067static Evas_Object *
2068_get_item(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, const char *item)
2069{
2070 Widget_Data *wd = elm_widget_data_get(data);
2071 Evas_Object *o;
2072 Eina_List *l;
2073 Elm_Entry_Item_Provider *ip;
2074
2075 EINA_LIST_FOREACH(wd->item_providers, l, ip)
2076 {
2077 o = ip->func(ip->data, data, item);
2078 if (o) return o;
2079 }
2080 if (!strncmp(item, "file://", 7))
2081 {
2082 const char *fname = item + 7;
2083
2084 o = evas_object_image_filled_add(evas_object_evas_get(data));
2085 evas_object_image_file_set(o, fname, NULL);
2086 if (evas_object_image_load_error_get(o) == EVAS_LOAD_ERROR_NONE)
2087 {
2088 evas_object_show(o);
2089 }
2090 else
2091 {
2092 evas_object_del(o);
2093 o = edje_object_add(evas_object_evas_get(data));
2094 _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
2095 }
2096 return o;
2097 }
2098 o = edje_object_add(evas_object_evas_get(data));
2099 if (!_elm_theme_object_set(data, o, "entry", item, elm_widget_style_get(data)))
2100 _elm_theme_object_set(data, o, "entry/emoticon", "wtf", elm_widget_style_get(data));
2101 return o;
2102}
2103
2104static void
2105_text_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, Edje_Text_Filter_Type type, char **text)
2106{
2107 Widget_Data *wd = elm_widget_data_get(data);
2108 Eina_List *l;
2109 Elm_Entry_Markup_Filter *tf;
2110
2111 if (type == EDJE_TEXT_FILTER_FORMAT)
2112 return;
2113
2114 EINA_LIST_FOREACH(wd->text_filters, l, tf)
2115 {
2116 tf->func(tf->data, data, text);
2117 if (!*text)
2118 break;
2119 }
2120}
2121
2122static void
2123_markup_filter(void *data, Evas_Object *edje __UNUSED__, const char *part __UNUSED__, char **text)
2124{
2125 Widget_Data *wd = elm_widget_data_get(data);
2126 Eina_List *l;
2127 Elm_Entry_Markup_Filter *tf;
2128
2129 EINA_LIST_FOREACH(wd->markup_filters, l, tf)
2130 {
2131 tf->func(tf->data, data, text);
2132 if (!*text)
2133 break;
2134 }
2135}
2136
2137/* This function is used to insert text by chunks in jobs */
2138static Eina_Bool
2139_text_append_idler(void *data)
2140{
2141 int start;
2142 char backup;
2143 Evas_Object *obj = (Evas_Object *) data;
2144 Widget_Data *wd = elm_widget_data_get(obj);
2145 evas_event_freeze(evas_object_evas_get(obj));
2146 if (wd->text) eina_stringshare_del(wd->text);
2147 wd->text = NULL;
2148 wd->changed = EINA_TRUE;
2149
2150 start = wd->append_text_position;
2151 if ((start + _CHUNK_SIZE) < wd->append_text_len)
2152 {
2153 int pos = start;
2154 int tag_start, esc_start;
2155
2156 tag_start = esc_start = -1;
2157 /* Find proper markup cut place */
2158 while (pos - start < _CHUNK_SIZE)
2159 {
2160 int prev_pos = pos;
2161 Eina_Unicode tmp =
2162 eina_unicode_utf8_get_next(wd->append_text_left, &pos);
2163 if (esc_start == -1)
2164 {
2165 if (tmp == '<')
2166 tag_start = prev_pos;
2167 else if (tmp == '>')
2168 tag_start = -1;
2169 }
2170 if (tag_start == -1)
2171 {
2172 if (tmp == '&')
2173 esc_start = prev_pos;
2174 else if (tmp == ';')
2175 esc_start = -1;
2176 }
2177 }
2178
2179 if (tag_start >= 0)
2180 {
2181 wd->append_text_position = tag_start;
2182 }
2183 else if (esc_start >= 0)
2184 {
2185 wd->append_text_position = esc_start;
2186 }
2187 else
2188 {
2189 wd->append_text_position = pos;
2190 }
2191 }
2192 else
2193 {
2194 wd->append_text_position = wd->append_text_len;
2195 }
2196
2197 backup = wd->append_text_left[wd->append_text_position];
2198 wd->append_text_left[wd->append_text_position] = '\0';
2199
2200 edje_object_part_text_append(wd->ent, "elm.text",
2201 wd->append_text_left + start);
2202
2203 wd->append_text_left[wd->append_text_position] = backup;
2204
2205 evas_event_thaw(evas_object_evas_get(obj));
2206 evas_event_thaw_eval(evas_object_evas_get(obj));
2207
2208 _elm_entry_update_guide(obj, EINA_TRUE);
2209
2210 /* If there's still more to go, renew the idler, else, cleanup */
2211 if (wd->append_text_position < wd->append_text_len)
2212 {
2213 return ECORE_CALLBACK_RENEW;
2214 }
2215 else
2216 {
2217 free(wd->append_text_left);
2218 wd->append_text_left = NULL;
2219 wd->append_text_idler = NULL;
2220 return ECORE_CALLBACK_CANCEL;
2221 }
2222}
2223
2224static void
2225_add_chars_till_limit(Evas_Object *obj, char **text, int can_add, Length_Unit unit)
2226{
2227 int i = 0, current_len = 0;
2228 char *new_text;
2229
2230 if (!*text) return;
2231 if (unit >= LENGTH_UNIT_LAST) return;
2232 new_text = *text;
2233 current_len = strlen(*text);
2234 while (*new_text)
2235 {
2236 int idx = 0, unit_size = 0;
2237 char *markup, *utfstr;
2238 if (*new_text == '<')
2239 {
2240 while (*(new_text + idx) != '>')
2241 {
2242 idx++;
2243 if (!*(new_text + idx)) break;
2244 }
2245 }
2246 else if (*new_text == '&')
2247 {
2248 while (*(new_text + idx) != ';')
2249 {
2250 idx++;
2251 if (!*(new_text + idx)) break;
2252 }
2253 }
2254 idx = evas_string_char_next_get(new_text, idx, NULL);
2255 markup = malloc(idx + 1);
2256 if (markup)
2257 {
2258 strncpy(markup, new_text, idx);
2259 markup[idx] = 0;
2260 utfstr = elm_entry_markup_to_utf8(markup);
2261 if (utfstr)
2262 {
2263 if (unit == LENGTH_UNIT_BYTE)
2264 unit_size = strlen(utfstr);
2265 else if (unit == LENGTH_UNIT_CHAR)
2266 unit_size = evas_string_char_len_get(utfstr);
2267 free(utfstr);
2268 utfstr = NULL;
2269 }
2270 free(markup);
2271 markup = NULL;
2272 }
2273 if (can_add < unit_size)
2274 {
2275 if (!i)
2276 {
2277 evas_object_smart_callback_call(obj, "maxlength,reached", NULL);
2278 free(*text);
2279 *text = NULL;
2280 return;
2281 }
2282 can_add = 0;
2283 strncpy(new_text, new_text + idx, current_len - ((new_text + idx) - *text));
2284 current_len -= idx;
2285 (*text)[current_len] = 0;
2286 }
2287 else
2288 {
2289 new_text += idx;
2290 can_add -= unit_size;
2291 }
2292 i++;
2293 }
2294 evas_object_smart_callback_call(obj, "maxlength,reached", NULL);
2295}
2296
2297static void
2298_elm_entry_text_set(Evas_Object *obj, const char *item, const char *entry)
2299{
2300 int len = 0;
2301 ELM_CHECK_WIDTYPE(obj, widtype);
2302 Widget_Data *wd = elm_widget_data_get(obj);
2303 if (!wd) return;
2304 evas_event_freeze(evas_object_evas_get(obj));
2305 if (!entry) entry = "";
2306 if (item)
2307 {
2308 if (!strcmp(item, "guide"))
2309 edje_object_part_text_set(wd->ent, "elm.guide", entry);
2310 else
2311 edje_object_part_text_set(wd->ent, item, entry);
2312 evas_event_thaw(evas_object_evas_get(obj));
2313 evas_event_thaw_eval(evas_object_evas_get(obj));
2314 return;
2315 }
2316
2317 if (wd->text) eina_stringshare_del(wd->text);
2318 wd->text = NULL;
2319 wd->changed = EINA_TRUE;
2320
2321 /* Clear currently pending job if there is one */
2322 if (wd->append_text_idler)
2323 {
2324 ecore_idler_del(wd->append_text_idler);
2325 free(wd->append_text_left);
2326 wd->append_text_left = NULL;
2327 wd->append_text_idler = NULL;
2328 }
2329
2330 len = strlen(entry);
2331 /* Split to ~_CHUNK_SIZE chunks */
2332 if (len > _CHUNK_SIZE)
2333 {
2334 wd->append_text_left = (char *) malloc(len + 1);
2335 }
2336
2337 /* If we decided to use the idler */
2338 if (wd->append_text_left)
2339 {
2340 /* Need to clear the entry first */
2341 edje_object_part_text_set(wd->ent, "elm.text", "");
2342 memcpy(wd->append_text_left, entry, len + 1);
2343 wd->append_text_position = 0;
2344 wd->append_text_len = len;
2345 wd->append_text_idler = ecore_idler_add(_text_append_idler, obj);
2346 }
2347 else
2348 {
2349 edje_object_part_text_set(wd->ent, "elm.text", entry);
2350 }
2351 if ((entry) && (entry[0]))
2352 _elm_entry_update_guide(obj, EINA_TRUE);
2353 else
2354 _elm_entry_update_guide(obj, EINA_FALSE);
2355 evas_event_thaw(evas_object_evas_get(obj));
2356 evas_event_thaw_eval(evas_object_evas_get(obj));
2357}
2358
2359static const char *
2360_elm_entry_text_get(const Evas_Object *obj, const char *item)
2361{
2362 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2363 Widget_Data *wd = elm_widget_data_get(obj);
2364 if (item && strcmp(item, "default")) return NULL;
2365 const char *text;
2366 if (!wd) return NULL;
2367 text = edje_object_part_text_get(wd->ent, "elm.text");
2368 if (!text)
2369 {
2370 ERR("text=NULL for edje %p, part 'elm.text'", wd->ent);
2371 return NULL;
2372 }
2373
2374 if (wd->append_text_len > 0)
2375 {
2376 char *tmpbuf;
2377 size_t tlen;
2378 tlen = wd->append_text_position;
2379 tmpbuf = malloc(wd->append_text_len + 1);
2380 if (!tmpbuf)
2381 {
2382 ERR("Failed to allocate memory for entry's text %p", obj);
2383 return NULL;
2384 }
2385 memcpy(tmpbuf, text, tlen);
2386 if (wd->append_text_left)
2387 memcpy(tmpbuf + tlen, wd->append_text_left + wd->append_text_position, wd->append_text_len - tlen);
2388 tmpbuf[wd->append_text_len + 1] = '\0';
2389 eina_stringshare_replace(&wd->text, tmpbuf);
2390 free(tmpbuf);
2391 }
2392 else
2393 {
2394 eina_stringshare_replace(&wd->text, text);
2395 }
2396 return wd->text;
2397}
2398
2399EAPI Evas_Object *
2400elm_entry_add(Evas_Object *parent)
2401{
2402#ifdef HAVE_ELEMENTARY_X
2403 Evas_Object *top;
2404#endif
2405 Evas_Object *obj;
2406 Evas *e;
2407 Widget_Data *wd;
2408
2409 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
2410
2411 ELM_SET_WIDTYPE(widtype, "entry");
2412 elm_widget_type_set(obj, "entry");
2413 elm_widget_sub_object_add(parent, obj);
2414 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
2415 elm_widget_data_set(obj, wd);
2416 elm_widget_del_hook_set(obj, _del_hook);
2417 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
2418 elm_widget_theme_hook_set(obj, _theme_hook);
2419 elm_widget_disable_hook_set(obj, _disable_hook);
2420 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
2421 elm_widget_focus_region_hook_set(obj, _focus_region_hook);
2422 elm_widget_on_focus_region_hook_set(obj, _on_focus_region_hook);
2423 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
2424 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
2425 elm_object_cursor_set(obj, ELM_CURSOR_XTERM);
2426 elm_widget_can_focus_set(obj, EINA_TRUE);
2427 elm_widget_text_set_hook_set(obj, _elm_entry_text_set);
2428 elm_widget_text_get_hook_set(obj, _elm_entry_text_get);
2429 elm_widget_content_set_hook_set(obj, _content_set_hook);
2430 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
2431 elm_widget_content_get_hook_set(obj, _content_get_hook);
2432 elm_widget_translate_hook_set(obj, _translate_hook);
2433
2434 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, wd);
2435
2436 wd->linewrap = ELM_WRAP_WORD;
2437 wd->editable = EINA_TRUE;
2438 wd->disabled = EINA_FALSE;
2439 wd->context_menu = EINA_TRUE;
2440 wd->autosave = EINA_TRUE;
2441 wd->cnp_mode = ELM_CNP_MODE_MARKUP;
2442 wd->scroll = EINA_FALSE;
2443 wd->input_panel_imdata = NULL;
2444
2445 wd->ent = edje_object_add(e);
2446 edje_object_item_provider_set(wd->ent, _get_item, obj);
2447 edje_object_text_insert_filter_callback_add(wd->ent,"elm.text", _text_filter, obj);
2448 edje_object_text_markup_filter_callback_add(wd->ent,"elm.text", _markup_filter, obj);
2449 evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOVE, _move, obj);
2450 evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_DOWN,
2451 _mouse_down, obj);
2452 evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_UP,
2453 _mouse_up, obj);
2454 evas_object_event_callback_add(wd->ent, EVAS_CALLBACK_MOUSE_MOVE,
2455 _mouse_move, obj);
2456 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
2457
2458 _elm_theme_object_set(obj, wd->ent, "entry", "base", "default");
2459 edje_object_signal_callback_add(wd->ent, "entry,changed", "elm.text",
2460 _signal_entry_changed, obj);
2461 edje_object_signal_callback_add(wd->ent, "entry,changed,user", "elm.text",
2462 _signal_entry_changed_user, obj);
2463 edje_object_signal_callback_add(wd->ent, "preedit,changed", "elm.text",
2464 _signal_preedit_changed, obj);
2465 edje_object_signal_callback_add(wd->ent, "selection,start", "elm.text",
2466 _signal_selection_start, obj);
2467 edje_object_signal_callback_add(wd->ent, "selection,changed", "elm.text",
2468 _signal_selection_changed, obj);
2469 edje_object_signal_callback_add(wd->ent, "entry,selection,all,request", "elm.text",
2470 _signal_selection_all, obj);
2471 edje_object_signal_callback_add(wd->ent, "entry,selection,none,request", "elm.text",
2472 _signal_selection_none, obj);
2473 edje_object_signal_callback_add(wd->ent, "selection,cleared", "elm.text",
2474 _signal_selection_cleared, obj);
2475 edje_object_signal_callback_add(wd->ent, "entry,paste,request,*", "elm.text",
2476 _signal_entry_paste_request, obj);
2477 edje_object_signal_callback_add(wd->ent, "entry,copy,notify", "elm.text",
2478 _signal_entry_copy_notify, obj);
2479 edje_object_signal_callback_add(wd->ent, "entry,cut,notify", "elm.text",
2480 _signal_entry_cut_notify, obj);
2481 edje_object_signal_callback_add(wd->ent, "cursor,changed", "elm.text",
2482 _signal_cursor_changed, obj);
2483 edje_object_signal_callback_add(wd->ent, "cursor,changed,manual", "elm.text",
2484 _signal_cursor_changed_manual, obj);
2485 edje_object_signal_callback_add(wd->ent, "anchor,mouse,down,*", "elm.text",
2486 _signal_anchor_down, obj);
2487 edje_object_signal_callback_add(wd->ent, "anchor,mouse,up,*", "elm.text",
2488 _signal_anchor_up, obj);
2489 edje_object_signal_callback_add(wd->ent, "anchor,mouse,clicked,*", "elm.text",
2490 _signal_anchor_clicked, obj);
2491 edje_object_signal_callback_add(wd->ent, "anchor,mouse,move,*", "elm.text",
2492 _signal_anchor_move, obj);
2493 edje_object_signal_callback_add(wd->ent, "anchor,mouse,in,*", "elm.text",
2494 _signal_anchor_in, obj);
2495 edje_object_signal_callback_add(wd->ent, "anchor,mouse,out,*", "elm.text",
2496 _signal_anchor_out, obj);
2497 edje_object_signal_callback_add(wd->ent, "entry,key,enter", "elm.text",
2498 _signal_key_enter, obj);
2499 edje_object_signal_callback_add(wd->ent, "mouse,down,1", "elm.text",
2500 _signal_mouse_down, obj);
2501 edje_object_signal_callback_add(wd->ent, "mouse,clicked,1", "elm.text",
2502 _signal_mouse_clicked, obj);
2503 edje_object_signal_callback_add(wd->ent, "mouse,down,1,double", "elm.text",
2504 _signal_mouse_double, obj);
2505 edje_object_signal_callback_add(wd->ent, "mouse,down,1,triple", "elm.text",
2506 _signal_mouse_triple, obj);
2507 edje_object_signal_callback_add(wd->ent, "entry,undo,request", "elm.text",
2508 _signal_undo_request, obj);
2509 edje_object_signal_callback_add(wd->ent, "entry,redo,request", "elm.text",
2510 _signal_redo_request, obj);
2511 edje_object_part_text_set(wd->ent, "elm.text", "");
2512 if (_elm_config->desktop_entry)
2513 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_TRUE);
2514 elm_widget_resize_object_set(obj, wd->ent);
2515 _sizing_eval(obj);
2516
2517 elm_entry_input_panel_layout_set(obj, ELM_INPUT_PANEL_LAYOUT_NORMAL);
2518 elm_entry_input_panel_enabled_set(obj, EINA_TRUE);
2519 elm_entry_prediction_allow_set(obj, EINA_TRUE);
2520
2521 wd->autocapital_type = edje_object_part_text_autocapital_type_get(wd->ent, "elm.text");
2522
2523#ifdef HAVE_ELEMENTARY_X
2524 top = elm_widget_top_get(obj);
2525 if ((top) && (elm_win_xwindow_get(top)))
2526 {
2527 wd->sel_notify_handler =
2528 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_NOTIFY,
2529 _event_selection_notify, obj);
2530 wd->sel_clear_handler =
2531 ecore_event_handler_add(ECORE_X_EVENT_SELECTION_CLEAR,
2532 _event_selection_clear, obj);
2533 }
2534
2535 elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP | ELM_SEL_FORMAT_IMAGE,
2536 _drag_drop_cb, NULL);
2537#endif
2538
2539 entries = eina_list_prepend(entries, obj);
2540
2541 // module - find module for entry
2542 wd->api = _module(obj);
2543 // if found - hook in
2544 if ((wd->api) && (wd->api->obj_hook)) wd->api->obj_hook(obj);
2545
2546 _mirrored_set(obj, elm_widget_mirrored_get(obj));
2547 // TODO: convert Elementary to subclassing of Evas_Smart_Class
2548 // TODO: and save some bytes, making descriptions per-class and not instance!
2549 evas_object_smart_callbacks_descriptions_set(obj, _signals);
2550 return obj;
2551}
2552
2553EAPI void
2554elm_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line)
2555{
2556 ELM_CHECK_WIDTYPE(obj, widtype);
2557 Widget_Data *wd = elm_widget_data_get(obj);
2558 if (!wd) return;
2559 if (wd->single_line == single_line) return;
2560 wd->single_line = single_line;
2561 wd->linewrap = ELM_WRAP_NONE;
2562 elm_entry_cnp_mode_set(obj, ELM_CNP_MODE_NO_IMAGE);
2563 _theme_hook(obj);
2564 if (wd->scroller)
2565 {
2566 if (wd->single_line)
2567 elm_smart_scroller_policy_set(wd->scroller,
2568 ELM_SMART_SCROLLER_POLICY_OFF,
2569 ELM_SMART_SCROLLER_POLICY_OFF);
2570 else
2571 {
2572 const Elm_Scroller_Policy map[3] =
2573 {
2574 ELM_SMART_SCROLLER_POLICY_AUTO,
2575 ELM_SMART_SCROLLER_POLICY_ON,
2576 ELM_SMART_SCROLLER_POLICY_OFF
2577 };
2578 elm_smart_scroller_policy_set(wd->scroller,
2579 map[wd->policy_h],
2580 map[wd->policy_v]);
2581 }
2582 _sizing_eval(obj);
2583 }
2584}
2585
2586EAPI Eina_Bool
2587elm_entry_single_line_get(const Evas_Object *obj)
2588{
2589 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2590 Widget_Data *wd = elm_widget_data_get(obj);
2591 if (!wd) return EINA_FALSE;
2592 return wd->single_line;
2593}
2594
2595EAPI void
2596elm_entry_password_set(Evas_Object *obj, Eina_Bool password)
2597{
2598 ELM_CHECK_WIDTYPE(obj, widtype);
2599 Widget_Data *wd = elm_widget_data_get(obj);
2600 if (!wd) return;
2601 if (wd->password == password) return;
2602 wd->password = password;
2603 if (password)
2604 {
2605 wd->single_line = EINA_TRUE;
2606 wd->linewrap = ELM_WRAP_NONE;
2607#ifdef HAVE_ELEMENTARY_X
2608 elm_drop_target_del(obj);
2609#endif
2610 edje_object_signal_callback_del_full(wd->ent, "selection,start", "elm.text",
2611 _signal_selection_start, obj);
2612 edje_object_signal_callback_del_full(wd->ent, "selection,changed", "elm.text",
2613 _signal_selection_changed, obj);
2614 edje_object_signal_callback_del_full(wd->ent, "entry,selection,all,request", "elm.text",
2615 _signal_selection_all, obj);
2616 edje_object_signal_callback_del_full(wd->ent, "entry,selection,none,request", "elm.text",
2617 _signal_selection_none, obj);
2618 edje_object_signal_callback_del_full(wd->ent, "selection,cleared", "elm.text",
2619 _signal_selection_cleared, obj);
2620 edje_object_signal_callback_del_full(wd->ent, "entry,paste,request,*", "elm.text",
2621 _signal_entry_paste_request, obj);
2622 edje_object_signal_callback_del_full(wd->ent, "entry,copy,notify", "elm.text",
2623 _signal_entry_copy_notify, obj);
2624 edje_object_signal_callback_del_full(wd->ent, "entry,cut,notify", "elm.text",
2625 _signal_entry_cut_notify, obj);
2626 }
2627 else
2628 {
2629#ifdef HAVE_ELEMENTARY_X
2630 elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP, _drag_drop_cb, NULL);
2631#endif
2632 edje_object_signal_callback_add(wd->ent, "selection,start", "elm.text",
2633 _signal_selection_start, obj);
2634 edje_object_signal_callback_add(wd->ent, "selection,changed", "elm.text",
2635 _signal_selection_changed, obj);
2636 edje_object_signal_callback_add(wd->ent, "entry,selection,all,request", "elm.text",
2637 _signal_selection_all, obj);
2638 edje_object_signal_callback_add(wd->ent, "entry,selection,none,request", "elm.text",
2639 _signal_selection_none, obj);
2640 edje_object_signal_callback_add(wd->ent, "selection,cleared", "elm.text",
2641 _signal_selection_cleared, obj);
2642 edje_object_signal_callback_add(wd->ent, "entry,paste,request,*", "elm.text",
2643 _signal_entry_paste_request, obj);
2644 edje_object_signal_callback_add(wd->ent, "entry,copy,notify", "elm.text",
2645 _signal_entry_copy_notify, obj);
2646 edje_object_signal_callback_add(wd->ent, "entry,cut,notify", "elm.text",
2647 _signal_entry_cut_notify, obj);
2648 }
2649 _theme_hook(obj);
2650}
2651
2652EAPI Eina_Bool
2653elm_entry_password_get(const Evas_Object *obj)
2654{
2655 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2656 Widget_Data *wd = elm_widget_data_get(obj);
2657 if (!wd) return EINA_FALSE;
2658 return wd->password;
2659}
2660
2661EAPI void
2662elm_entry_entry_set(Evas_Object *obj, const char *entry)
2663{
2664 _elm_entry_text_set(obj, NULL, entry);
2665}
2666
2667EAPI const char *
2668elm_entry_entry_get(const Evas_Object *obj)
2669{
2670 return _elm_entry_text_get(obj, NULL);
2671}
2672
2673EAPI void
2674elm_entry_entry_append(Evas_Object *obj, const char *entry)
2675{
2676 int len = 0;
2677 ELM_CHECK_WIDTYPE(obj, widtype);
2678 Widget_Data *wd = elm_widget_data_get(obj);
2679 if (!wd) return;
2680 if (!entry) entry = "";
2681 wd->changed = EINA_TRUE;
2682
2683 len = strlen(entry);
2684 if (wd->append_text_left)
2685 {
2686 char *tmpbuf;
2687 tmpbuf = realloc(wd->append_text_left, wd->append_text_len + len + 1);
2688 if (!tmpbuf)
2689 {
2690 /* Do something */
2691 return;
2692 }
2693 wd->append_text_left = tmpbuf;
2694 memcpy(wd->append_text_left + wd->append_text_len, entry, len + 1);
2695 wd->append_text_len += len;
2696 }
2697 else
2698 {
2699 /* FIXME: Add chunked appending here (like in entry_set) */
2700 edje_object_part_text_append(wd->ent, "elm.text", entry);
2701 }
2702}
2703
2704EAPI Eina_Bool
2705elm_entry_is_empty(const Evas_Object *obj)
2706{
2707 /* FIXME: until there's support for that in textblock, we just check
2708 * to see if the there is text or not. */
2709 ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
2710 Widget_Data *wd = elm_widget_data_get(obj);
2711 const Evas_Object *tb;
2712 Evas_Textblock_Cursor *cur;
2713 Eina_Bool ret;
2714 if (!wd) return EINA_TRUE;
2715 /* It's a hack until we get the support suggested above.
2716 * We just create a cursor, point it to the begining, and then
2717 * try to advance it, if it can advance, the tb is not empty,
2718 * otherwise it is. */
2719 tb = edje_object_part_object_get(wd->ent, "elm.text");
2720 cur = evas_object_textblock_cursor_new((Evas_Object *) tb); /* This is
2721 actually, ok for the time being, thsese hackish stuff will be removed
2722 once evas 1.0 is out*/
2723 evas_textblock_cursor_pos_set(cur, 0);
2724 ret = evas_textblock_cursor_char_next(cur);
2725 evas_textblock_cursor_free(cur);
2726
2727 return !ret;
2728}
2729
2730EAPI Evas_Object *
2731elm_entry_textblock_get(Evas_Object *obj)
2732{
2733 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2734 Widget_Data *wd = elm_widget_data_get(obj);
2735 if (!wd) return NULL;
2736
2737 return (Evas_Object *) edje_object_part_object_get(wd->ent, "elm.text");
2738}
2739
2740EAPI void
2741elm_entry_calc_force(Evas_Object *obj)
2742{
2743 ELM_CHECK_WIDTYPE(obj, widtype);
2744 Widget_Data *wd = elm_widget_data_get(obj);
2745 if (!wd) return;
2746
2747 edje_object_calc_force(wd->ent);
2748 wd->changed = EINA_TRUE;
2749 _sizing_eval(obj);
2750}
2751
2752
2753EAPI const char *
2754elm_entry_selection_get(const Evas_Object *obj)
2755{
2756 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2757 Widget_Data *wd = elm_widget_data_get(obj);
2758 if ((!wd) || (wd->password)) return NULL;
2759 return edje_object_part_text_selection_get(wd->ent, "elm.text");
2760}
2761
2762EAPI void
2763elm_entry_entry_insert(Evas_Object *obj, const char *entry)
2764{
2765 ELM_CHECK_WIDTYPE(obj, widtype);
2766 Widget_Data *wd = elm_widget_data_get(obj);
2767 if (!wd) return;
2768 edje_object_part_text_insert(wd->ent, "elm.text", entry);
2769 wd->changed = EINA_TRUE;
2770 _sizing_eval(obj);
2771}
2772
2773EAPI void
2774elm_entry_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
2775{
2776 ELM_CHECK_WIDTYPE(obj, widtype);
2777 Widget_Data *wd = elm_widget_data_get(obj);
2778 if (!wd) return;
2779 if (wd->linewrap == wrap) return;
2780 wd->lastw = -1;
2781 wd->linewrap = wrap;
2782 _theme_hook(obj);
2783}
2784
2785EAPI Elm_Wrap_Type
2786elm_entry_line_wrap_get(const Evas_Object *obj)
2787{
2788 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2789 Widget_Data *wd = elm_widget_data_get(obj);
2790 if (!wd) return EINA_FALSE;
2791 return wd->linewrap;
2792}
2793
2794EAPI void
2795elm_entry_editable_set(Evas_Object *obj, Eina_Bool editable)
2796{
2797 ELM_CHECK_WIDTYPE(obj, widtype);
2798 Widget_Data *wd = elm_widget_data_get(obj);
2799 if (!wd) return;
2800 if (wd->editable == editable) return;
2801 wd->editable = editable;
2802 _theme_hook(obj);
2803
2804#ifdef HAVE_ELEMENTARY_X
2805 if (editable)
2806 elm_drop_target_add(obj, ELM_SEL_FORMAT_MARKUP, _drag_drop_cb, NULL);
2807 else
2808 elm_drop_target_del(obj);
2809#endif
2810}
2811
2812EAPI Eina_Bool
2813elm_entry_editable_get(const Evas_Object *obj)
2814{
2815 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2816 Widget_Data *wd = elm_widget_data_get(obj);
2817 if (!wd) return EINA_FALSE;
2818 return wd->editable;
2819}
2820
2821EAPI void
2822elm_entry_select_none(Evas_Object *obj)
2823{
2824 ELM_CHECK_WIDTYPE(obj, widtype);
2825 Widget_Data *wd = elm_widget_data_get(obj);
2826 if ((!wd) || (wd->password)) return;
2827 if (wd->selmode)
2828 {
2829 wd->selmode = EINA_FALSE;
2830 if (!_elm_config->desktop_entry)
2831 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
2832 edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
2833 }
2834 wd->have_selection = EINA_FALSE;
2835 edje_object_part_text_select_none(wd->ent, "elm.text");
2836}
2837
2838EAPI void
2839elm_entry_select_all(Evas_Object *obj)
2840{
2841 ELM_CHECK_WIDTYPE(obj, widtype);
2842 Widget_Data *wd = elm_widget_data_get(obj);
2843 if ((!wd) || (wd->password)) return;
2844 if (wd->selmode)
2845 {
2846 wd->selmode = EINA_FALSE;
2847 if (!_elm_config->desktop_entry)
2848 edje_object_part_text_select_allow_set(wd->ent, "elm.text", EINA_FALSE);
2849 edje_object_signal_emit(wd->ent, "elm,state,select,off", "elm");
2850 }
2851 wd->have_selection = EINA_TRUE;
2852 edje_object_part_text_select_all(wd->ent, "elm.text");
2853}
2854
2855EAPI Eina_Bool
2856elm_entry_cursor_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
2857{
2858 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2859 Widget_Data *wd = elm_widget_data_get(obj);
2860 if (!wd) return EINA_FALSE;
2861 edje_object_part_text_cursor_geometry_get(wd->ent, "elm.text", x, y, w, h);
2862 return EINA_TRUE;
2863}
2864
2865EAPI Eina_Bool
2866elm_entry_cursor_next(Evas_Object *obj)
2867{
2868 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2869 Widget_Data *wd = elm_widget_data_get(obj);
2870 if (!wd) return EINA_FALSE;
2871 return edje_object_part_text_cursor_next(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2872}
2873
2874EAPI Eina_Bool
2875elm_entry_cursor_prev(Evas_Object *obj)
2876{
2877 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2878 Widget_Data *wd = elm_widget_data_get(obj);
2879 if (!wd) return EINA_FALSE;
2880 return edje_object_part_text_cursor_prev(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2881}
2882
2883EAPI Eina_Bool
2884elm_entry_cursor_up(Evas_Object *obj)
2885{
2886 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2887 Widget_Data *wd = elm_widget_data_get(obj);
2888 if (!wd) return EINA_FALSE;
2889 return edje_object_part_text_cursor_up(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2890}
2891
2892EAPI Eina_Bool
2893elm_entry_cursor_down(Evas_Object *obj)
2894{
2895 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2896 Widget_Data *wd = elm_widget_data_get(obj);
2897 if (!wd) return EINA_FALSE;
2898 return edje_object_part_text_cursor_down(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2899}
2900
2901EAPI void
2902elm_entry_cursor_begin_set(Evas_Object *obj)
2903{
2904 ELM_CHECK_WIDTYPE(obj, widtype);
2905 Widget_Data *wd = elm_widget_data_get(obj);
2906 if (!wd) return;
2907 edje_object_part_text_cursor_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2908}
2909
2910EAPI void
2911elm_entry_cursor_end_set(Evas_Object *obj)
2912{
2913 ELM_CHECK_WIDTYPE(obj, widtype);
2914 Widget_Data *wd = elm_widget_data_get(obj);
2915 if (!wd) return;
2916 edje_object_part_text_cursor_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2917}
2918
2919EAPI void
2920elm_entry_cursor_line_begin_set(Evas_Object *obj)
2921{
2922 ELM_CHECK_WIDTYPE(obj, widtype);
2923 Widget_Data *wd = elm_widget_data_get(obj);
2924 if (!wd) return;
2925 edje_object_part_text_cursor_line_begin_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2926}
2927
2928EAPI void
2929elm_entry_cursor_line_end_set(Evas_Object *obj)
2930{
2931 ELM_CHECK_WIDTYPE(obj, widtype);
2932 Widget_Data *wd = elm_widget_data_get(obj);
2933 if (!wd) return;
2934 edje_object_part_text_cursor_line_end_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2935}
2936
2937EAPI void
2938elm_entry_cursor_selection_begin(Evas_Object *obj)
2939{
2940 ELM_CHECK_WIDTYPE(obj, widtype);
2941 Widget_Data *wd = elm_widget_data_get(obj);
2942 if (!wd) return;
2943 edje_object_part_text_select_begin(wd->ent, "elm.text");
2944}
2945
2946EAPI void
2947elm_entry_cursor_selection_end(Evas_Object *obj)
2948{
2949 ELM_CHECK_WIDTYPE(obj, widtype);
2950 Widget_Data *wd = elm_widget_data_get(obj);
2951 if (!wd) return;
2952 edje_object_part_text_select_extend(wd->ent, "elm.text");
2953}
2954
2955EAPI Eina_Bool
2956elm_entry_cursor_is_format_get(const Evas_Object *obj)
2957{
2958 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2959 Widget_Data *wd = elm_widget_data_get(obj);
2960 if (!wd) return EINA_FALSE;
2961 return edje_object_part_text_cursor_is_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2962}
2963
2964EAPI Eina_Bool
2965elm_entry_cursor_is_visible_format_get(const Evas_Object *obj)
2966{
2967 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2968 Widget_Data *wd = elm_widget_data_get(obj);
2969 if (!wd) return EINA_FALSE;
2970 return edje_object_part_text_cursor_is_visible_format_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2971}
2972
2973EAPI char *
2974elm_entry_cursor_content_get(const Evas_Object *obj)
2975{
2976 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2977 Widget_Data *wd = elm_widget_data_get(obj);
2978 if (!wd) return NULL;
2979 return edje_object_part_text_cursor_content_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2980}
2981
2982EAPI void
2983elm_entry_cursor_pos_set(Evas_Object *obj, int pos)
2984{
2985 ELM_CHECK_WIDTYPE(obj, widtype);
2986 Widget_Data *wd = elm_widget_data_get(obj);
2987 if (!wd) return;
2988 edje_object_part_text_cursor_pos_set(wd->ent, "elm.text", EDJE_CURSOR_MAIN, pos);
2989 edje_object_message_signal_process(wd->ent);
2990}
2991
2992EAPI int
2993elm_entry_cursor_pos_get(const Evas_Object *obj)
2994{
2995 ELM_CHECK_WIDTYPE(obj, widtype) 0;
2996 Widget_Data *wd = elm_widget_data_get(obj);
2997 if (!wd) return 0;
2998 return edje_object_part_text_cursor_pos_get(wd->ent, "elm.text", EDJE_CURSOR_MAIN);
2999}
3000
3001EAPI void
3002elm_entry_selection_cut(Evas_Object *obj)
3003{
3004 ELM_CHECK_WIDTYPE(obj, widtype);
3005 Widget_Data *wd = elm_widget_data_get(obj);
3006 if ((!wd) || (wd->password)) return;
3007 _cut(obj, NULL, NULL);
3008}
3009
3010EAPI void
3011elm_entry_selection_copy(Evas_Object *obj)
3012{
3013 ELM_CHECK_WIDTYPE(obj, widtype);
3014 Widget_Data *wd = elm_widget_data_get(obj);
3015 if ((!wd) || (wd->password)) return;
3016 _copy(obj, NULL, NULL);
3017}
3018
3019EAPI void
3020elm_entry_selection_paste(Evas_Object *obj)
3021{
3022 ELM_CHECK_WIDTYPE(obj, widtype);
3023 Widget_Data *wd = elm_widget_data_get(obj);
3024 if ((!wd) || (wd->password)) return;
3025 _paste(obj, NULL, NULL);
3026}
3027
3028EAPI void
3029elm_entry_context_menu_clear(Evas_Object *obj)
3030{
3031 ELM_CHECK_WIDTYPE(obj, widtype);
3032 Widget_Data *wd = elm_widget_data_get(obj);
3033 Elm_Entry_Context_Menu_Item *it;
3034 if (!wd) return;
3035 EINA_LIST_FREE(wd->items, it)
3036 {
3037 eina_stringshare_del(it->label);
3038 eina_stringshare_del(it->icon_file);
3039 eina_stringshare_del(it->icon_group);
3040 free(it);
3041 }
3042}
3043
3044EAPI void
3045elm_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)
3046{
3047 ELM_CHECK_WIDTYPE(obj, widtype);
3048 Widget_Data *wd = elm_widget_data_get(obj);
3049 Elm_Entry_Context_Menu_Item *it;
3050 if (!wd) return;
3051 it = calloc(1, sizeof(Elm_Entry_Context_Menu_Item));
3052 if (!it) return;
3053 wd->items = eina_list_append(wd->items, it);
3054 it->obj = obj;
3055 it->label = eina_stringshare_add(label);
3056 it->icon_file = eina_stringshare_add(icon_file);
3057 it->icon_type = icon_type;
3058 it->func = func;
3059 it->data = (void *)data;
3060}
3061
3062EAPI void
3063elm_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3064{
3065 ELM_CHECK_WIDTYPE(obj, widtype);
3066 Widget_Data *wd = elm_widget_data_get(obj);
3067 if (!wd) return;
3068 if (wd->context_menu == !disabled) return;
3069 wd->context_menu = !disabled;
3070}
3071
3072EAPI Eina_Bool
3073elm_entry_context_menu_disabled_get(const Evas_Object *obj)
3074{
3075 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3076 Widget_Data *wd = elm_widget_data_get(obj);
3077 if (!wd) return EINA_FALSE;
3078 return !wd->context_menu;
3079}
3080
3081EAPI void
3082elm_entry_item_provider_append(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data)
3083{
3084 ELM_CHECK_WIDTYPE(obj, widtype);
3085 Widget_Data *wd = elm_widget_data_get(obj);
3086 if (!wd) return;
3087 EINA_SAFETY_ON_NULL_RETURN(func);
3088 Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
3089 if (!ip) return;
3090 ip->func = func;
3091 ip->data = data;
3092 wd->item_providers = eina_list_append(wd->item_providers, ip);
3093}
3094
3095EAPI void
3096elm_entry_item_provider_prepend(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data)
3097{
3098 ELM_CHECK_WIDTYPE(obj, widtype);
3099 Widget_Data *wd = elm_widget_data_get(obj);
3100 if (!wd) return;
3101 EINA_SAFETY_ON_NULL_RETURN(func);
3102 Elm_Entry_Item_Provider *ip = calloc(1, sizeof(Elm_Entry_Item_Provider));
3103 if (!ip) return;
3104 ip->func = func;
3105 ip->data = data;
3106 wd->item_providers = eina_list_prepend(wd->item_providers, ip);
3107}
3108
3109EAPI void
3110elm_entry_item_provider_remove(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data)
3111{
3112 ELM_CHECK_WIDTYPE(obj, widtype);
3113 Widget_Data *wd = elm_widget_data_get(obj);
3114 Eina_List *l;
3115 Elm_Entry_Item_Provider *ip;
3116 if (!wd) return;
3117 EINA_SAFETY_ON_NULL_RETURN(func);
3118 EINA_LIST_FOREACH(wd->item_providers, l, ip)
3119 {
3120 if ((ip->func == func) && ((!data) || (ip->data == data)))
3121 {
3122 wd->item_providers = eina_list_remove_list(wd->item_providers, l);
3123 free(ip);
3124 return;
3125 }
3126 }
3127}
3128
3129EAPI void
3130elm_entry_markup_filter_append(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data)
3131{
3132 Widget_Data *wd;
3133 Elm_Entry_Markup_Filter *tf;
3134 ELM_CHECK_WIDTYPE(obj, widtype);
3135
3136 wd = elm_widget_data_get(obj);
3137
3138 EINA_SAFETY_ON_NULL_RETURN(func);
3139
3140 tf = _filter_new(func, data);
3141 if (!tf) return;
3142
3143 wd->markup_filters = eina_list_append(wd->markup_filters, tf);
3144}
3145
3146EAPI void
3147elm_entry_markup_filter_prepend(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data)
3148{
3149 Widget_Data *wd;
3150 Elm_Entry_Markup_Filter *tf;
3151 ELM_CHECK_WIDTYPE(obj, widtype);
3152
3153 wd = elm_widget_data_get(obj);
3154
3155 EINA_SAFETY_ON_NULL_RETURN(func);
3156
3157 tf = _filter_new(func, data);
3158 if (!tf) return;
3159
3160 wd->markup_filters = eina_list_prepend(wd->markup_filters, tf);
3161}
3162
3163EAPI void
3164elm_entry_markup_filter_remove(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data)
3165{
3166 Widget_Data *wd;
3167 Eina_List *l;
3168 Elm_Entry_Markup_Filter *tf;
3169 ELM_CHECK_WIDTYPE(obj, widtype);
3170
3171 wd = elm_widget_data_get(obj);
3172
3173 EINA_SAFETY_ON_NULL_RETURN(func);
3174
3175 EINA_LIST_FOREACH(wd->markup_filters, l, tf)
3176 {
3177 if ((tf->func == func) && ((!data) || (tf->data == data)))
3178 {
3179 wd->markup_filters = eina_list_remove_list(wd->markup_filters, l);
3180 _filter_free(tf);
3181 return;
3182 }
3183 }
3184}
3185
3186EAPI char *
3187elm_entry_markup_to_utf8(const char *s)
3188{
3189 char *ss = _elm_util_mkup_to_text(s);
3190 if (!ss) ss = strdup("");
3191 return ss;
3192}
3193
3194EAPI char *
3195elm_entry_utf8_to_markup(const char *s)
3196{
3197 char *ss = _elm_util_text_to_mkup(s);
3198 if (!ss) ss = strdup("");
3199 return ss;
3200}
3201
3202static const char *
3203_text_get(const Evas_Object *obj)
3204{
3205 return elm_object_text_get(obj);
3206}
3207
3208EAPI void
3209elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text)
3210{
3211 Elm_Entry_Filter_Limit_Size *lim = data;
3212 char *current, *utfstr;
3213 int len, newlen;
3214 const char *(*text_get)(const Evas_Object *);
3215
3216 EINA_SAFETY_ON_NULL_RETURN(data);
3217 EINA_SAFETY_ON_NULL_RETURN(entry);
3218 EINA_SAFETY_ON_NULL_RETURN(text);
3219
3220 /* hack. I don't want to copy the entire function to work with
3221 * scrolled_entry */
3222 text_get = _text_get;
3223
3224 current = elm_entry_markup_to_utf8(text_get(entry));
3225 utfstr = elm_entry_markup_to_utf8(*text);
3226
3227 if (lim->max_char_count > 0)
3228 {
3229 len = evas_string_char_len_get(current);
3230 newlen = evas_string_char_len_get(utfstr);
3231 if ((len >= lim->max_char_count) && (newlen > 0))
3232 {
3233 evas_object_smart_callback_call(entry, "maxlength,reached", NULL);
3234 free(*text);
3235 *text = NULL;
3236 free(current);
3237 free(utfstr);
3238 return;
3239 }
3240 if ((len + newlen) > lim->max_char_count)
3241 _add_chars_till_limit(entry, text, (lim->max_char_count - len), LENGTH_UNIT_CHAR);
3242 }
3243 else if (lim->max_byte_count > 0)
3244 {
3245 len = strlen(current);
3246 newlen = strlen(utfstr);
3247 if ((len >= lim->max_byte_count) && (newlen > 0))
3248 {
3249 evas_object_smart_callback_call(entry, "maxlength,reached", NULL);
3250 free(*text);
3251 *text = NULL;
3252 free(current);
3253 free(utfstr);
3254 return;
3255 }
3256 if ((len + newlen) > lim->max_byte_count)
3257 _add_chars_till_limit(entry, text, (lim->max_byte_count - len), LENGTH_UNIT_BYTE);
3258 }
3259 free(current);
3260 free(utfstr);
3261}
3262
3263EAPI void
3264elm_entry_filter_accept_set(void *data, Evas_Object *entry __UNUSED__, char **text)
3265{
3266 Elm_Entry_Filter_Accept_Set *as = data;
3267 const char *set;
3268 char *insert;
3269 Eina_Bool goes_in;
3270 int read_idx, last_read_idx = 0, read_char;
3271
3272 EINA_SAFETY_ON_NULL_RETURN(data);
3273 EINA_SAFETY_ON_NULL_RETURN(text);
3274
3275 if ((!as->accepted) && (!as->rejected))
3276 return;
3277
3278 if (as->accepted)
3279 {
3280 set = as->accepted;
3281 goes_in = EINA_TRUE;
3282 }
3283 else
3284 {
3285 set = as->rejected;
3286 goes_in = EINA_FALSE;
3287 }
3288
3289 insert = *text;
3290 read_idx = evas_string_char_next_get(*text, 0, &read_char);
3291 while (read_char)
3292 {
3293 int cmp_idx, cmp_char;
3294 Eina_Bool in_set = EINA_FALSE;
3295
3296 cmp_idx = evas_string_char_next_get(set, 0, &cmp_char);
3297 while (cmp_char)
3298 {
3299 if (read_char == cmp_char)
3300 {
3301 in_set = EINA_TRUE;
3302 break;
3303 }
3304 cmp_idx = evas_string_char_next_get(set, cmp_idx, &cmp_char);
3305 }
3306 if (in_set == goes_in)
3307 {
3308 int size = read_idx - last_read_idx;
3309 const char *src = (*text) + last_read_idx;
3310 if (src != insert)
3311 memcpy(insert, *text + last_read_idx, size);
3312 insert += size;
3313 }
3314 last_read_idx = read_idx;
3315 read_idx = evas_string_char_next_get(*text, read_idx, &read_char);
3316 }
3317 *insert = 0;
3318}
3319
3320EAPI Eina_Bool
3321elm_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format)
3322{
3323 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3324 Widget_Data *wd = elm_widget_data_get(obj);
3325 if (!wd) return EINA_FALSE;
3326 if (wd->delay_write)
3327 {
3328 ecore_timer_del(wd->delay_write);
3329 wd->delay_write = NULL;
3330 }
3331 if (wd->autosave) _save(obj);
3332 eina_stringshare_replace(&wd->file, file);
3333 wd->format = format;
3334 return _load(obj);
3335}
3336
3337EAPI void
3338elm_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format)
3339{
3340 ELM_CHECK_WIDTYPE(obj, widtype);
3341 Widget_Data *wd = elm_widget_data_get(obj);
3342 if (!wd) return;
3343 if (file) *file = wd->file;
3344 if (format) *format = wd->format;
3345}
3346
3347EAPI void
3348elm_entry_file_save(Evas_Object *obj)
3349{
3350 ELM_CHECK_WIDTYPE(obj, widtype);
3351 Widget_Data *wd = elm_widget_data_get(obj);
3352 if (!wd) return;
3353 if (wd->delay_write)
3354 {
3355 ecore_timer_del(wd->delay_write);
3356 wd->delay_write = NULL;
3357 }
3358 _save(obj);
3359 wd->delay_write = ecore_timer_add(2.0, _delay_write, obj);
3360}
3361
3362EAPI void
3363elm_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave)
3364{
3365 ELM_CHECK_WIDTYPE(obj, widtype);
3366 Widget_Data *wd = elm_widget_data_get(obj);
3367 if (!wd) return;
3368 wd->autosave = !!autosave;
3369}
3370
3371EAPI Eina_Bool
3372elm_entry_autosave_get(const Evas_Object *obj)
3373{
3374 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3375 Widget_Data *wd = elm_widget_data_get(obj);
3376 if (!wd) return EINA_FALSE;
3377 return wd->autosave;
3378}
3379
3380EINA_DEPRECATED EAPI void
3381elm_entry_cnp_textonly_set(Evas_Object *obj, Eina_Bool textonly)
3382{
3383 ELM_CHECK_WIDTYPE(obj, widtype);
3384 Elm_Cnp_Mode cnp_mode = ELM_CNP_MODE_MARKUP;
3385 if (textonly)
3386 cnp_mode = ELM_CNP_MODE_NO_IMAGE;
3387 elm_entry_cnp_mode_set(obj, cnp_mode);
3388}
3389
3390EINA_DEPRECATED EAPI Eina_Bool
3391elm_entry_cnp_textonly_get(const Evas_Object *obj)
3392{
3393 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3394 return elm_entry_cnp_mode_get(obj) != ELM_CNP_MODE_MARKUP;
3395}
3396
3397EAPI void
3398elm_entry_cnp_mode_set(Evas_Object *obj, Elm_Cnp_Mode cnp_mode)
3399{
3400 Elm_Sel_Format format = ELM_SEL_FORMAT_MARKUP;
3401 ELM_CHECK_WIDTYPE(obj, widtype);
3402 Widget_Data *wd = elm_widget_data_get(obj);
3403 if (!wd) return;
3404 if (wd->cnp_mode == cnp_mode) return;
3405 wd->cnp_mode = cnp_mode;
3406 if (wd->cnp_mode == ELM_CNP_MODE_PLAINTEXT)
3407 format = ELM_SEL_FORMAT_TEXT;
3408 else if (cnp_mode == ELM_CNP_MODE_MARKUP) format |= ELM_SEL_FORMAT_IMAGE;
3409#ifdef HAVE_ELEMENTARY_X
3410 elm_drop_target_add(obj, format, _drag_drop_cb, NULL);
3411#endif
3412}
3413
3414EAPI Elm_Cnp_Mode
3415elm_entry_cnp_mode_get(const Evas_Object *obj)
3416{
3417 ELM_CHECK_WIDTYPE(obj, widtype) ELM_CNP_MODE_MARKUP;
3418 Widget_Data *wd = elm_widget_data_get(obj);
3419 if (!wd) return ELM_CNP_MODE_MARKUP;
3420 return wd->cnp_mode;
3421}
3422
3423EAPI void
3424elm_entry_scrollable_set(Evas_Object *obj, Eina_Bool scroll)
3425{
3426 ELM_CHECK_WIDTYPE(obj, widtype);
3427 Widget_Data *wd = elm_widget_data_get(obj);
3428 const Elm_Scroller_Policy map[3] =
3429 {
3430 ELM_SMART_SCROLLER_POLICY_AUTO,
3431 ELM_SMART_SCROLLER_POLICY_ON,
3432 ELM_SMART_SCROLLER_POLICY_OFF
3433 };
3434 if (!wd) return;
3435 scroll = !!scroll;
3436 if (wd->scroll == scroll) return;
3437 wd->scroll = scroll;
3438 if (wd->scroll)
3439 {
3440 if (!wd->scroller)
3441 {
3442 wd->scroller = elm_smart_scroller_add(evas_object_evas_get(obj));
3443 elm_widget_resize_object_set(obj, wd->scroller);
3444 elm_smart_scroller_widget_set(wd->scroller, obj);
3445 elm_smart_scroller_object_theme_set(obj, wd->scroller, "scroller", "entry",
3446 elm_widget_style_get(obj));
3447 evas_object_size_hint_weight_set(wd->scroller, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3448 evas_object_size_hint_align_set(wd->scroller, EVAS_HINT_FILL, EVAS_HINT_FILL);
3449 evas_object_propagate_events_set(wd->scroller, EINA_TRUE);
3450 evas_object_propagate_events_set(elm_smart_scroller_edje_object_get(wd->scroller),
3451 EINA_TRUE);
3452 }
3453 elm_smart_scroller_bounce_allow_set(wd->scroller, wd->h_bounce, wd->v_bounce);
3454 if (wd->single_line)
3455 elm_smart_scroller_policy_set(wd->scroller, ELM_SMART_SCROLLER_POLICY_OFF,
3456 ELM_SMART_SCROLLER_POLICY_OFF);
3457 else
3458 elm_smart_scroller_policy_set(wd->scroller, map[wd->policy_h], map[wd->policy_v]);
3459 elm_widget_sub_object_add(obj, wd->ent);
3460 elm_smart_scroller_child_set(wd->scroller, wd->ent);
3461 evas_object_show(wd->scroller);
3462 elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3463 }
3464 else
3465 {
3466 if (wd->scroller)
3467 {
3468 elm_smart_scroller_child_set(wd->scroller, NULL);
3469 evas_object_smart_member_add(wd->scroller, obj);
3470 elm_widget_sub_object_add(obj, wd->scroller);
3471 evas_object_hide(wd->scroller);
3472 }
3473 elm_widget_sub_object_del(obj, wd->ent);
3474 elm_widget_resize_object_set(obj, wd->ent);
3475 elm_widget_on_show_region_hook_set(obj, NULL, NULL);
3476 }
3477 wd->lastw = -1;
3478 _theme_hook(obj);
3479}
3480
3481EAPI Eina_Bool
3482elm_entry_scrollable_get(const Evas_Object *obj)
3483{
3484 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3485 Widget_Data *wd = elm_widget_data_get(obj);
3486 if (!wd) return EINA_FALSE;
3487 return wd->scroll;
3488}
3489
3490EAPI void
3491elm_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting)
3492{
3493 ELM_CHECK_WIDTYPE(obj, widtype);
3494 Widget_Data *wd = elm_widget_data_get(obj);
3495 Evas_Object *edje;
3496 if (!wd) return;
3497 if (wd->scroll)
3498 edje = elm_smart_scroller_edje_object_get(wd->scroller);
3499 else
3500 edje = wd->ent;
3501
3502 if ((!edje) || (!edje_object_part_swallow_get(edje, "elm.swallow.icon"))) return;
3503 if (setting)
3504 edje_object_signal_emit(edje, "elm,action,show,icon", "elm");
3505 else
3506 edje_object_signal_emit(edje, "elm,action,hide,icon", "elm");
3507 _sizing_eval(obj);
3508}
3509
3510EAPI void
3511elm_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting)
3512{
3513 ELM_CHECK_WIDTYPE(obj, widtype);
3514 Widget_Data *wd = elm_widget_data_get(obj);
3515 Evas_Object *edje;
3516 if (!wd) return;
3517 if (wd->scroll)
3518 edje = elm_smart_scroller_edje_object_get(wd->scroller);
3519 else
3520 edje = wd->ent;
3521
3522 if ((!edje) || (!edje_object_part_swallow_get(edje, "elm.swallow.icon"))) return;
3523 if (setting)
3524 edje_object_signal_emit(edje, "elm,action,show,end", "elm");
3525 else
3526 edje_object_signal_emit(edje, "elm,action,hide,end", "elm");
3527 _sizing_eval(obj);
3528}
3529
3530EAPI void
3531elm_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v)
3532{
3533 ELM_CHECK_WIDTYPE(obj, widtype);
3534 Widget_Data *wd = elm_widget_data_get(obj);
3535 const Elm_Scroller_Policy map[3] =
3536 {
3537 ELM_SMART_SCROLLER_POLICY_AUTO,
3538 ELM_SMART_SCROLLER_POLICY_ON,
3539 ELM_SMART_SCROLLER_POLICY_OFF
3540 };
3541 if (!wd) return;
3542 wd->policy_h = h;
3543 wd->policy_v = v;
3544 elm_smart_scroller_policy_set(wd->scroller,
3545 map[wd->policy_h],
3546 map[wd->policy_v]);
3547}
3548
3549EAPI void
3550elm_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
3551{
3552 ELM_CHECK_WIDTYPE(obj, widtype);
3553 Widget_Data *wd = elm_widget_data_get(obj);
3554 if (!wd) return;
3555 wd->h_bounce = h_bounce;
3556 wd->v_bounce = v_bounce;
3557 elm_smart_scroller_bounce_allow_set(wd->scroller, h_bounce, v_bounce);
3558}
3559
3560EAPI void
3561elm_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
3562{
3563 ELM_CHECK_WIDTYPE(obj, widtype);
3564 Widget_Data *wd = elm_widget_data_get(obj);
3565 if (!wd) return;
3566 elm_smart_scroller_bounce_allow_get(wd->scroller, h_bounce, v_bounce);
3567}
3568
3569EAPI void
3570elm_entry_input_panel_layout_set(Evas_Object *obj, Elm_Input_Panel_Layout layout)
3571{
3572 ELM_CHECK_WIDTYPE(obj, widtype);
3573 Widget_Data *wd = elm_widget_data_get(obj);
3574 if (!wd) return;
3575
3576 wd->input_panel_layout = layout;
3577
3578 edje_object_part_text_input_panel_layout_set(wd->ent, "elm.text", layout);
3579}
3580
3581EAPI Elm_Input_Panel_Layout
3582elm_entry_input_panel_layout_get(const Evas_Object *obj)
3583{
3584 ELM_CHECK_WIDTYPE(obj, widtype) ELM_INPUT_PANEL_LAYOUT_INVALID;
3585 Widget_Data *wd = elm_widget_data_get(obj);
3586 if (!wd) return ELM_INPUT_PANEL_LAYOUT_INVALID;
3587
3588 return wd->input_panel_layout;
3589}
3590
3591EAPI void
3592elm_entry_autocapital_type_set(Evas_Object *obj, Elm_Autocapital_Type autocapital_type)
3593{
3594 ELM_CHECK_WIDTYPE(obj, widtype);
3595 Widget_Data *wd = elm_widget_data_get(obj);
3596 if (!wd) return;
3597
3598 wd->autocapital_type = autocapital_type;
3599 edje_object_part_text_autocapital_type_set(wd->ent, "elm.text", autocapital_type);
3600}
3601
3602EAPI Elm_Autocapital_Type
3603elm_entry_autocapital_type_get(const Evas_Object *obj)
3604{
3605 ELM_CHECK_WIDTYPE(obj, widtype) ELM_AUTOCAPITAL_TYPE_NONE;
3606 Widget_Data *wd = elm_widget_data_get(obj);
3607 if (!wd) return ELM_AUTOCAPITAL_TYPE_NONE;
3608
3609 return wd->autocapital_type;
3610}
3611
3612EAPI void
3613elm_entry_prediction_allow_set(Evas_Object *obj, Eina_Bool prediction)
3614{
3615 ELM_CHECK_WIDTYPE(obj, widtype);
3616 Widget_Data *wd = elm_widget_data_get(obj);
3617 if (!wd) return;
3618
3619 wd->prediction_allow = prediction;
3620 edje_object_part_text_prediction_allow_set(wd->ent, "elm.text", prediction);
3621}
3622
3623EAPI Eina_Bool
3624elm_entry_prediction_allow_get(const Evas_Object *obj)
3625{
3626 ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
3627 Widget_Data *wd = elm_widget_data_get(obj);
3628 if (!wd) return EINA_TRUE;
3629
3630 return wd->prediction_allow;
3631}
3632
3633EAPI void
3634elm_entry_imf_context_reset(Evas_Object *obj)
3635{
3636 ELM_CHECK_WIDTYPE(obj, widtype);
3637 Widget_Data *wd = elm_widget_data_get(obj);
3638 if (!wd) return;
3639
3640 edje_object_part_text_imf_context_reset(wd->ent, "elm.text");
3641}
3642
3643EAPI void
3644elm_entry_input_panel_enabled_set(Evas_Object *obj, Eina_Bool enabled)
3645{
3646 ELM_CHECK_WIDTYPE(obj, widtype);
3647 Widget_Data *wd = elm_widget_data_get(obj);
3648 if (!wd) return;
3649
3650 wd->input_panel_enable = enabled;
3651 edje_object_part_text_input_panel_enabled_set(wd->ent, "elm.text", enabled);
3652}
3653
3654EAPI Eina_Bool
3655elm_entry_input_panel_enabled_get(const Evas_Object *obj)
3656{
3657 ELM_CHECK_WIDTYPE(obj, widtype) EINA_TRUE;
3658 Widget_Data *wd = elm_widget_data_get(obj);
3659 if (!wd) return EINA_TRUE;
3660
3661 return wd->input_panel_enable;
3662}
3663
3664EAPI void
3665elm_entry_input_panel_show(Evas_Object *obj)
3666{
3667 ELM_CHECK_WIDTYPE(obj, widtype);
3668 Widget_Data *wd = elm_widget_data_get(obj);
3669 if (!wd) return;
3670
3671 edje_object_part_text_input_panel_show(wd->ent, "elm.text");
3672}
3673
3674EAPI void
3675elm_entry_input_panel_hide(Evas_Object *obj)
3676{
3677 ELM_CHECK_WIDTYPE(obj, widtype);
3678 Widget_Data *wd = elm_widget_data_get(obj);
3679 if (!wd) return;
3680
3681 edje_object_part_text_input_panel_hide(wd->ent, "elm.text");
3682}
3683
3684EAPI void
3685elm_entry_input_panel_language_set(Evas_Object *obj, Elm_Input_Panel_Lang lang)
3686{
3687 ELM_CHECK_WIDTYPE(obj, widtype);
3688 Widget_Data *wd = elm_widget_data_get(obj);
3689 if (!wd) return;
3690
3691 wd->input_panel_lang = lang;
3692 edje_object_part_text_input_panel_language_set(wd->ent, "elm.text", lang);
3693}
3694
3695EAPI Elm_Input_Panel_Lang
3696elm_entry_input_panel_language_get(const Evas_Object *obj)
3697{
3698 ELM_CHECK_WIDTYPE(obj, widtype) ELM_INPUT_PANEL_LANG_AUTOMATIC;
3699 Widget_Data *wd = elm_widget_data_get(obj);
3700 if (!wd) return ELM_INPUT_PANEL_LANG_AUTOMATIC;
3701
3702 return wd->input_panel_lang;
3703}
3704
3705EAPI void
3706elm_entry_input_panel_imdata_set(Evas_Object *obj, const void *data, int len)
3707{
3708 ELM_CHECK_WIDTYPE(obj, widtype);
3709 Widget_Data *wd = elm_widget_data_get(obj);
3710 if (!wd) return;
3711
3712 if (wd->input_panel_imdata)
3713 free(wd->input_panel_imdata);
3714
3715 wd->input_panel_imdata = calloc(1, len);
3716 wd->input_panel_imdata_len = len;
3717 memcpy(wd->input_panel_imdata, data, len);
3718
3719 edje_object_part_text_input_panel_imdata_set(wd->ent, "elm.text", wd->input_panel_imdata, wd->input_panel_imdata_len);
3720}
3721
3722EAPI void
3723elm_entry_input_panel_imdata_get(const Evas_Object *obj, void *data, int *len)
3724{
3725 ELM_CHECK_WIDTYPE(obj, widtype);
3726 Widget_Data *wd = elm_widget_data_get(obj);
3727 if (!wd) return;
3728
3729 edje_object_part_text_input_panel_imdata_get(wd->ent, "elm.text", data, len);
3730}
3731
3732EAPI void
3733elm_entry_input_panel_return_key_type_set(Evas_Object *obj, Elm_Input_Panel_Return_Key_Type return_key_type)
3734{
3735 ELM_CHECK_WIDTYPE(obj, widtype);
3736 Widget_Data *wd = elm_widget_data_get(obj);
3737 if (!wd) return;
3738
3739 wd->input_panel_return_key_type = return_key_type;
3740
3741 edje_object_part_text_input_panel_return_key_type_set(wd->ent, "elm.text", return_key_type);
3742}
3743
3744EAPI Elm_Input_Panel_Return_Key_Type
3745elm_entry_input_panel_return_key_type_get(const Evas_Object *obj)
3746{
3747 ELM_CHECK_WIDTYPE(obj, widtype) ELM_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3748 Widget_Data *wd = elm_widget_data_get(obj);
3749 if (!wd) return ELM_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT;
3750
3751 return wd->input_panel_return_key_type;
3752}
3753
3754EAPI void
3755elm_entry_input_panel_return_key_disabled_set(Evas_Object *obj, Eina_Bool disabled)
3756{
3757 ELM_CHECK_WIDTYPE(obj, widtype);
3758 Widget_Data *wd = elm_widget_data_get(obj);
3759 if (!wd) return;
3760
3761 wd->input_panel_return_key_disabled = disabled;
3762
3763 edje_object_part_text_input_panel_return_key_disabled_set(wd->ent, "elm.text", disabled);
3764}
3765
3766EAPI Eina_Bool
3767elm_entry_input_panel_return_key_disabled_get(const Evas_Object *obj)
3768{
3769 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3770 Widget_Data *wd = elm_widget_data_get(obj);
3771 if (!wd) return EINA_FALSE;
3772
3773 return wd->input_panel_return_key_disabled;
3774}
3775
3776EAPI void
3777elm_entry_input_panel_return_key_autoenabled_set(Evas_Object *obj, Eina_Bool enabled)
3778{
3779 ELM_CHECK_WIDTYPE(obj, widtype);
3780 Widget_Data *wd = elm_widget_data_get(obj);
3781 if (!wd) return;
3782
3783 wd->autoreturnkey = enabled;
3784 _check_enable_return_key(obj);
3785}
3786
3787EAPI void*
3788elm_entry_imf_context_get(Evas_Object *obj)
3789{
3790 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3791 Widget_Data *wd = elm_widget_data_get(obj);
3792 if (!wd) return NULL;
3793
3794 return edje_object_part_text_imf_context_get(wd->ent, "elm.text");
3795}
3796
3797/* START - ANCHOR HOVER */
3798static void
3799_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3800{
3801 Widget_Data *wd = elm_widget_data_get(data);
3802 if (!wd) return;
3803 wd->anchor_hover.hover_parent = NULL;
3804}
3805
3806EAPI void
3807elm_entry_anchor_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
3808{
3809 ELM_CHECK_WIDTYPE(obj, widtype);
3810 Widget_Data *wd = elm_widget_data_get(obj);
3811 if (!wd) return;
3812 if (wd->anchor_hover.hover_parent)
3813 evas_object_event_callback_del_full(wd->anchor_hover.hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
3814 wd->anchor_hover.hover_parent = parent;
3815 if (wd->anchor_hover.hover_parent)
3816 evas_object_event_callback_add(wd->anchor_hover.hover_parent, EVAS_CALLBACK_DEL, _parent_del, obj);
3817}
3818
3819EAPI Evas_Object *
3820elm_entry_anchor_hover_parent_get(const Evas_Object *obj)
3821{
3822 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3823 Widget_Data *wd = elm_widget_data_get(obj);
3824 if (!wd) return NULL;
3825 return wd->anchor_hover.hover_parent;
3826}
3827
3828EAPI void
3829elm_entry_anchor_hover_style_set(Evas_Object *obj, const char *style)
3830{
3831 ELM_CHECK_WIDTYPE(obj, widtype);
3832 Widget_Data *wd = elm_widget_data_get(obj);
3833 if (!wd) return;
3834 eina_stringshare_replace(&wd->anchor_hover.hover_style, style);
3835}
3836
3837EAPI const char *
3838elm_entry_anchor_hover_style_get(const Evas_Object *obj)
3839{
3840 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3841 Widget_Data *wd = elm_widget_data_get(obj);
3842 if (!wd) return NULL;
3843 return wd->anchor_hover.hover_style;
3844}
3845
3846EAPI void
3847elm_entry_anchor_hover_end(Evas_Object *obj)
3848{
3849 ELM_CHECK_WIDTYPE(obj, widtype);
3850 Widget_Data *wd = elm_widget_data_get(obj);
3851 if (!wd) return;
3852 if (wd->anchor_hover.hover) evas_object_del(wd->anchor_hover.hover);
3853 if (wd->anchor_hover.pop) evas_object_del(wd->anchor_hover.pop);
3854 wd->anchor_hover.hover = NULL;
3855 wd->anchor_hover.pop = NULL;
3856}
3857
3858
3859static void
3860_anchor_hover_clicked(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3861{
3862 elm_entry_anchor_hover_end(data);
3863}
3864
3865static void
3866_entry_hover_anchor_clicked(void *data, Evas_Object *obj, void *event_info)
3867{
3868 Widget_Data *wd = elm_widget_data_get(obj);
3869 Elm_Entry_Anchor_Info *info = event_info;
3870 Evas_Object *hover_parent;
3871 Elm_Entry_Anchor_Hover_Info ei;
3872 Evas_Coord x, w, y, h, px, py;
3873 if (!wd) return;
3874
3875 ei.anchor_info = event_info;
3876
3877 wd->anchor_hover.pop = elm_icon_add(obj);
3878 evas_object_move(wd->anchor_hover.pop, info->x, info->y);
3879 evas_object_resize(wd->anchor_hover.pop, info->w, info->h);
3880
3881 wd->anchor_hover.hover = elm_hover_add(obj);
3882 elm_widget_mirrored_set(wd->anchor_hover.hover, elm_widget_mirrored_get(obj));
3883 if (wd->anchor_hover.hover_style)
3884 elm_object_style_set(wd->anchor_hover.hover, wd->anchor_hover.hover_style);
3885
3886 hover_parent = wd->anchor_hover.hover_parent;
3887 if (!hover_parent) hover_parent = obj;
3888 elm_hover_parent_set(wd->anchor_hover.hover, hover_parent);
3889 elm_hover_target_set(wd->anchor_hover.hover, wd->anchor_hover.pop);
3890 ei.hover = wd->anchor_hover.hover;
3891
3892 evas_object_geometry_get(hover_parent, &x, &y, &w, &h);
3893 ei.hover_parent.x = x;
3894 ei.hover_parent.y = y;
3895 ei.hover_parent.w = w;
3896 ei.hover_parent.h = h;
3897 px = info->x + (info->w / 2);
3898 py = info->y + (info->h / 2);
3899 ei.hover_left = 1;
3900 if (px < (x + (w / 3))) ei.hover_left = 0;
3901 ei.hover_right = 1;
3902 if (px > (x + ((w * 2) / 3))) ei.hover_right = 0;
3903 ei.hover_top = 1;
3904 if (py < (y + (h / 3))) ei.hover_top = 0;
3905 ei.hover_bottom = 1;
3906 if (py > (y + ((h * 2) / 3))) ei.hover_bottom = 0;
3907
3908 if (elm_widget_mirrored_get(wd->anchor_hover.hover))
3909 { /* Swap right and left because they switch sides in RTL */
3910 Eina_Bool tmp = ei.hover_left;
3911 ei.hover_left = ei.hover_right;
3912 ei.hover_right = tmp;
3913 }
3914
3915 evas_object_smart_callback_call(data, SIG_ANCHOR_HOVER_OPENED, &ei);
3916 evas_object_smart_callback_add(wd->anchor_hover.hover, "clicked", _anchor_hover_clicked, data);
3917
3918 /* FIXME: Should just check if there's any callback registered to the smart
3919 * events instead.
3920 * This is used to determine if anyone cares about the hover or not. */
3921 if (!elm_object_part_content_get(wd->anchor_hover.hover, "middle") &&
3922 !elm_object_part_content_get(wd->anchor_hover.hover, "left") &&
3923 !elm_object_part_content_get(wd->anchor_hover.hover, "right") &&
3924 !elm_object_part_content_get(wd->anchor_hover.hover, "top") &&
3925 !elm_object_part_content_get(wd->anchor_hover.hover, "bottom"))
3926 {
3927 evas_object_del(wd->anchor_hover.hover);
3928 }
3929 else
3930 {
3931 evas_object_show(wd->anchor_hover.hover);
3932 }
3933}
3934/* END - ANCHOR HOVER */
diff --git a/libraries/elementary/src/lib/elm_entry.h b/libraries/elementary/src/lib/elm_entry.h
new file mode 100644
index 0000000..0621caa
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_entry.h
@@ -0,0 +1,1730 @@
1/**
2 * @defgroup Entry Entry
3 * @ingroup Elementary
4 *
5 * @image html img/widget/entry/preview-00.png
6 * @image latex img/widget/entry/preview-00.eps width=\textwidth
7 * @image html img/widget/entry/preview-01.png
8 * @image latex img/widget/entry/preview-01.eps width=\textwidth
9 * @image html img/widget/entry/preview-02.png
10 * @image latex img/widget/entry/preview-02.eps width=\textwidth
11 * @image html img/widget/entry/preview-03.png
12 * @image latex img/widget/entry/preview-03.eps width=\textwidth
13 *
14 * An entry is a convenience widget which shows a box that the user can
15 * enter text into. Entries by default don't scroll, so they grow to
16 * accommodate the entire text, resizing the parent window as needed. This
17 * can be changed with the elm_entry_scrollable_set() function.
18 *
19 * They can also be single line or multi line (the default) and when set
20 * to multi line mode they support text wrapping in any of the modes
21 * indicated by #Elm_Wrap_Type.
22 *
23 * Other features include password mode, filtering of inserted text with
24 * elm_entry_markup_filter_append() and related functions, inline "items" and
25 * formatted markup text.
26 *
27 * @section entry-markup Formatted text
28 *
29 * The markup tags supported by the Entry are defined by the theme, but
30 * even when writing new themes or extensions it's a good idea to stick to
31 * a sane default, to maintain coherency and avoid application breakages.
32 * Currently defined by the default theme are the following tags:
33 * @li \<br\>: Inserts a line break.
34 * @li \<ps\>: Inserts a paragraph separator. This is preferred over line
35 * breaks.
36 * @li \<tab\>: Inserts a tab.
37 * @li \<em\>...\</em\>: Emphasis. Sets the @em oblique style for the
38 * enclosed text.
39 * @li \<b\>...\</b\>: Sets the @b bold style for the enclosed text.
40 * @li \<link\>...\</link\>: Underlines the enclosed text.
41 * @li \<hilight\>...\</hilight\>: Highlights the enclosed text.
42 *
43 * @section entry-special Special markups
44 *
45 * Besides those used to format text, entries support two special markup
46 * tags used to insert click-able portions of text or items inlined within
47 * the text.
48 *
49 * @subsection entry-anchors Anchors
50 *
51 * Anchors are similar to HTML anchors. Text can be surrounded by \<a\> and
52 * \</a\> tags and an event will be generated when this text is clicked,
53 * like this:
54 *
55 * @code
56 * This text is outside <a href=anc-01>but this one is an anchor</a>
57 * @endcode
58 *
59 * The @c href attribute in the opening tag gives the name that will be
60 * used to identify the anchor and it can be any valid utf8 string.
61 *
62 * When an anchor is clicked, an @c "anchor,clicked" signal is emitted with
63 * an #Elm_Entry_Anchor_Info in the @c event_info parameter for the
64 * callback function. The same applies for "anchor,in" (mouse in), "anchor,out"
65 * (mouse out), "anchor,down" (mouse down), and "anchor,up" (mouse up) events on
66 * an anchor.
67 *
68 * @subsection entry-items Items
69 *
70 * Inlined in the text, any other @c Evas_Object can be inserted by using
71 * \<item\> tags this way:
72 *
73 * @code
74 * <item size=16x16 vsize=full href=emoticon/haha></item>
75 * @endcode
76 *
77 * Just like with anchors, the @c href identifies each item, but these need,
78 * in addition, to indicate their size, which is done using any one of
79 * @c size, @c absize or @c relsize attributes. These attributes take their
80 * value in the WxH format, where W is the width and H the height of the
81 * item.
82 *
83 * @li absize: Absolute pixel size for the item. Whatever value is set will
84 * be the item's size regardless of any scale value the object may have
85 * been set to. The final line height will be adjusted to fit larger items.
86 * @li size: Similar to @c absize, but it's adjusted to the scale value set
87 * for the object.
88 * @li relsize: Size is adjusted for the item to fit within the current
89 * line height.
90 *
91 * Besides their size, items are specified a @c vsize value that affects
92 * how their final size and position are calculated. The possible values
93 * are:
94 * @li ascent: Item will be placed within the line's baseline and its
95 * ascent. That is, the height between the line where all characters are
96 * positioned and the highest point in the line. For @c size and @c absize
97 * items, the descent value will be added to the total line height to make
98 * them fit. @c relsize items will be adjusted to fit within this space.
99 * @li full: Items will be placed between the descent and ascent, or the
100 * lowest point in the line and its highest.
101 *
102 * The next image shows different configurations of items and how
103 * the previously mentioned options affect their sizes. In all cases,
104 * the green line indicates the ascent, blue for the baseline and red for
105 * the descent.
106 *
107 * @image html entry_item.png
108 * @image latex entry_item.eps width=\textwidth
109 *
110 * And another one to show how size differs from absize. In the first one,
111 * the scale value is set to 1.0, while the second one is using one of 2.0.
112 *
113 * @image html entry_item_scale.png
114 * @image latex entry_item_scale.eps width=\textwidth
115 *
116 * After the size for an item is calculated, the entry will request an
117 * object to place in its space. For this, the functions set with
118 * elm_entry_item_provider_append() and related functions will be called
119 * in order until one of them returns a @c non-NULL value. If no providers
120 * are available, or all of them return @c NULL, then the entry falls back
121 * to one of the internal defaults, provided the name matches with one of
122 * them.
123 *
124 * All of the following are currently supported:
125 *
126 * - emoticon/angry
127 * - emoticon/angry-shout
128 * - emoticon/crazy-laugh
129 * - emoticon/evil-laugh
130 * - emoticon/evil
131 * - emoticon/goggle-smile
132 * - emoticon/grumpy
133 * - emoticon/grumpy-smile
134 * - emoticon/guilty
135 * - emoticon/guilty-smile
136 * - emoticon/haha
137 * - emoticon/half-smile
138 * - emoticon/happy-panting
139 * - emoticon/happy
140 * - emoticon/indifferent
141 * - emoticon/kiss
142 * - emoticon/knowing-grin
143 * - emoticon/laugh
144 * - emoticon/little-bit-sorry
145 * - emoticon/love-lots
146 * - emoticon/love
147 * - emoticon/minimal-smile
148 * - emoticon/not-happy
149 * - emoticon/not-impressed
150 * - emoticon/omg
151 * - emoticon/opensmile
152 * - emoticon/smile
153 * - emoticon/sorry
154 * - emoticon/squint-laugh
155 * - emoticon/surprised
156 * - emoticon/suspicious
157 * - emoticon/tongue-dangling
158 * - emoticon/tongue-poke
159 * - emoticon/uh
160 * - emoticon/unhappy
161 * - emoticon/very-sorry
162 * - emoticon/what
163 * - emoticon/wink
164 * - emoticon/worried
165 * - emoticon/wtf
166 *
167 * Alternatively, an item may reference an image by its path, using
168 * the URI form @c file:///path/to/an/image.png and the entry will then
169 * use that image for the item.
170 *
171 * @section entry-files Loading and saving files
172 *
173 * Entries have convenience functions to load text from a file and save
174 * changes back to it after a short delay. The automatic saving is enabled
175 * by default, but can be disabled with elm_entry_autosave_set() and files
176 * can be loaded directly as plain text or have any markup in them
177 * recognized. See elm_entry_file_set() for more details.
178 *
179 * @section entry-signals Emitted signals
180 *
181 * This widget emits the following signals:
182 *
183 * @li "changed": The text within the entry was changed.
184 * @li "changed,user": The text within the entry was changed because of user interaction.
185 * @li "activated": The enter key was pressed on a single line entry.
186 * @li "press": A mouse button has been pressed on the entry.
187 * @li "longpressed": A mouse button has been pressed and held for a couple
188 * seconds.
189 * @li "clicked": The entry has been clicked (mouse press and release).
190 * @li "clicked,double": The entry has been double clicked.
191 * @li "clicked,triple": The entry has been triple clicked.
192 * @li "focused": The entry has received focus.
193 * @li "unfocused": The entry has lost focus.
194 * @li "selection,paste": A paste of the clipboard contents was requested.
195 * @li "selection,copy": A copy of the selected text into the clipboard was
196 * requested.
197 * @li "selection,cut": A cut of the selected text into the clipboard was
198 * requested.
199 * @li "selection,start": A selection has begun and no previous selection
200 * existed.
201 * @li "selection,changed": The current selection has changed.
202 * @li "selection,cleared": The current selection has been cleared.
203 * @li "cursor,changed": The cursor has changed position.
204 * @li "anchor,clicked": An anchor has been clicked. The event_info
205 * parameter for the callback will be an #Elm_Entry_Anchor_Info.
206 * @li "anchor,in": Mouse cursor has moved into an anchor. The event_info
207 * parameter for the callback will be an #Elm_Entry_Anchor_Info.
208 * @li "anchor,out": Mouse cursor has moved out of an anchor. The event_info
209 * parameter for the callback will be an #Elm_Entry_Anchor_Info.
210 * @li "anchor,up": Mouse button has been unpressed on an anchor. The event_info
211 * parameter for the callback will be an #Elm_Entry_Anchor_Info.
212 * @li "anchor,down": Mouse button has been pressed on an anchor. The event_info
213 * parameter for the callback will be an #Elm_Entry_Anchor_Info.
214 * @li "preedit,changed": The preedit string has changed.
215 * @li "language,changed": Program language changed.
216 *
217 * Default content parts of the entry items that you can use for are:
218 * @li "icon" - An icon in the entry
219 * @li "end" - A content in the end of the entry
220 *
221 * Default text parts of the entry that you can use for are:
222 * @li "default" - text of the entry
223 *
224 * Supported elm_object common APIs.
225 * @li @ref elm_object_signal_emit
226 * @li @ref elm_object_part_text_set
227 * @li @ref elm_object_part_text_get
228 * @li @ref elm_object_part_content_set
229 * @li @ref elm_object_part_content_get
230 * @li @ref elm_object_part_content_unset
231 * @li @ref elm_object_signal_callback_add
232 * @li @ref elm_object_signal_callback_del
233 * @li @ref elm_object_disabled_set
234 * @li @ref elm_object_disabled_get
235 *
236 * @section entry-examples
237 *
238 * An overview of the Entry API can be seen in @ref entry_example
239 *
240 * @{
241 */
242
243/**
244 * @typedef Elm_Text_Format
245 *
246 * Text Format types.
247 *
248 * @see elm_entry_file_set()
249 */
250typedef enum
251{
252 ELM_TEXT_FORMAT_PLAIN_UTF8, /**< Plain UTF8 type */
253 ELM_TEXT_FORMAT_MARKUP_UTF8 /**< Markup UTF8 type */
254} Elm_Text_Format;
255
256/**
257 * @typedef Elm_Wrap_Type
258 *
259 * Line wrapping types.
260 *
261 * @see elm_entry_line_wrap_set()
262 */
263typedef enum
264{
265 ELM_WRAP_NONE = 0, /**< No wrap - value is zero */
266 ELM_WRAP_CHAR, /**< Char wrap - wrap between characters */
267 ELM_WRAP_WORD, /**< Word wrap - wrap in allowed wrapping points (as defined in the unicode standard) */
268 ELM_WRAP_MIXED, /**< Mixed wrap - Word wrap, and if that fails, char wrap. */
269 ELM_WRAP_LAST
270} Elm_Wrap_Type; /**< Type of word or character wrapping to use */
271
272/**
273 * @typedef Elm_Input_Panel_Layout
274 *
275 * Input panel (virtual keyboard) layout types.
276 *
277 * @see elm_entry_input_panel_layout_set()
278 */
279typedef enum
280{
281 ELM_INPUT_PANEL_LAYOUT_NORMAL, /**< Default layout */
282 ELM_INPUT_PANEL_LAYOUT_NUMBER, /**< Number layout */
283 ELM_INPUT_PANEL_LAYOUT_EMAIL, /**< Email layout */
284 ELM_INPUT_PANEL_LAYOUT_URL, /**< URL layout */
285 ELM_INPUT_PANEL_LAYOUT_PHONENUMBER, /**< Phone Number layout */
286 ELM_INPUT_PANEL_LAYOUT_IP, /**< IP layout */
287 ELM_INPUT_PANEL_LAYOUT_MONTH, /**< Month layout */
288 ELM_INPUT_PANEL_LAYOUT_NUMBERONLY, /**< Number Only layout */
289 ELM_INPUT_PANEL_LAYOUT_INVALID, /**< Never use this */
290 ELM_INPUT_PANEL_LAYOUT_HEX, /**< Hexadecimal layout */
291 ELM_INPUT_PANEL_LAYOUT_TERMINAL, /**< Command-line terminal layout */
292 ELM_INPUT_PANEL_LAYOUT_PASSWORD /**< Like normal, but no auto-correct, no auto-capitalization etc. */
293} Elm_Input_Panel_Layout; /**< Type of input panel (virtual keyboard) to use - this is a hint and may not provide exactly what is desired. */
294
295/**
296 * @typedef Elm_Input_Panel_Lang
297 *
298 * Input panel (virtual keyboard) language modes.
299 *
300 * @see elm_entry_input_panel_language_set()
301 */
302typedef enum
303{
304 ELM_INPUT_PANEL_LANG_AUTOMATIC, /**< Automatic */
305 ELM_INPUT_PANEL_LANG_ALPHABET /**< Alphabet */
306} Elm_Input_Panel_Lang;
307
308/**
309 * @typedef Elm_Autocapital_Type
310 *
311 * Autocapitalization Types.
312 *
313 * @see elm_entry_autocapital_type_set()
314 */
315typedef enum
316{
317 ELM_AUTOCAPITAL_TYPE_NONE, /**< No auto-capitalization when typing */
318 ELM_AUTOCAPITAL_TYPE_WORD, /**< Autocapitalize each word typed */
319 ELM_AUTOCAPITAL_TYPE_SENTENCE, /**< Autocapitalize the start of each sentence */
320 ELM_AUTOCAPITAL_TYPE_ALLCHARACTER, /**< Autocapitalize all letters */
321} Elm_Autocapital_Type; /**< Choose method of auto-capitalization */
322
323/**
324 * @typedef Elm_Input_Panel_Return_Key_Type
325 *
326 * "Return" Key types on the input panel (virtual keyboard).
327 *
328 * @see elm_entry_input_panel_return_key_type_set()
329 */
330typedef enum
331{
332 ELM_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT, /**< Default */
333 ELM_INPUT_PANEL_RETURN_KEY_TYPE_DONE, /**< Done */
334 ELM_INPUT_PANEL_RETURN_KEY_TYPE_GO, /**< Go */
335 ELM_INPUT_PANEL_RETURN_KEY_TYPE_JOIN, /**< Join */
336 ELM_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN, /**< Login */
337 ELM_INPUT_PANEL_RETURN_KEY_TYPE_NEXT, /**< Next */
338 ELM_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH, /**< Search string or magnifier icon */
339 ELM_INPUT_PANEL_RETURN_KEY_TYPE_SEND /**< Send */
340} Elm_Input_Panel_Return_Key_Type;
341
342/**
343 * @typedef Elm_Entry_Anchor_Info
344 *
345 * The info sent in the callback for the "anchor,clicked" signals emitted
346 * by entries.
347 */
348typedef struct _Elm_Entry_Anchor_Info Elm_Entry_Anchor_Info;
349
350/**
351 * @struct _Elm_Entry_Anchor_Info
352 *
353 * The info sent in the callback for the "anchor,clicked" signals emitted
354 * by entries.
355 */
356struct _Elm_Entry_Anchor_Info
357{
358 const char *name; /**< The name of the anchor, as stated in its href */
359 int button; /**< The mouse button used to click on it */
360 Evas_Coord x, /**< Anchor geometry, relative to canvas */
361 y, /**< Anchor geometry, relative to canvas */
362 w, /**< Anchor geometry, relative to canvas */
363 h; /**< Anchor geometry, relative to canvas */
364};
365
366/**
367 * @typedef Elm_Entry_Anchor_Hover_Info
368 *
369 * The info sent in the callback for "anchor,clicked" signals emitted by
370 * the Anchor_Hover widget.
371 */
372typedef struct _Elm_Entry_Anchor_Hover_Info Elm_Entry_Anchor_Hover_Info;
373
374/**
375 * @struct _Elm_Entry_Anchor_Hover_Info
376 *
377 * The info sent in the callback for "anchor,clicked" signals emitted by
378 * the Anchor_Hover widget.
379 */
380struct _Elm_Entry_Anchor_Hover_Info
381{
382 const Elm_Entry_Anchor_Info *anchor_info; /**< The actual anchor info. */
383 Evas_Object *hover; /**< The hover object to use for the popup */
384 struct
385 {
386 Evas_Coord x, y, w, h;
387 } hover_parent; /**< Geometry of the object used as parent by the
388 hover */
389 Eina_Bool hover_left : 1; /**< Hint indicating if there's space
390 for content on the left side of
391 the hover. Before calling the
392 callback, the widget will make the
393 necessary calculations to check
394 which sides are fit to be set with
395 content, based on the position the
396 hover is activated and its distance
397 to the edges of its parent object
398 */
399 Eina_Bool hover_right : 1; /**< Hint indicating content fits on
400 the right side of the hover.
401 See @ref hover_left */
402 Eina_Bool hover_top : 1; /**< Hint indicating content fits on top
403 of the hover. See @ref hover_left */
404 Eina_Bool hover_bottom : 1; /**< Hint indicating content fits
405 below the hover. See @ref
406 hover_left */
407};
408
409/**
410 * @typedef Elm_Entry_Item_Provider_Cb
411 * This callback type is used to provide items.
412 * If it returns an object handle other than NULL (it should create an
413 * object to do this), then this object is used to replace the current item.
414 * If not the next provider is called until one provides an item object, or the
415 * default provider in entry does.
416 * @param data The data specified as the last param when adding the provider
417 * @param entry The entry object
418 * @param text A pointer to the item href string in the text
419 * @return The object to be placed in the entry like an icon, or other element
420 * @see elm_entry_item_provider_append
421 * @see elm_entry_item_provider_prepend
422 * @see elm_entry_item_provider_remove
423 */
424typedef Evas_Object * (*Elm_Entry_Item_Provider_Cb)(void *data, Evas_Object * entry, const char *item);
425
426/**
427 * @typedef Elm_Entry_Filter_Cb
428 * This callback type is used by entry filters to modify text.
429 * @param data The data specified as the last param when adding the filter
430 * @param entry The entry object
431 * @param text A pointer to the location of the text being filtered. The type of text is always markup. This data can be modified, but any additional allocations must be managed by the user.
432 * @see elm_entry_markup_filter_append
433 * @see elm_entry_markup_filter_prepend
434 * @see elm_entry_markup_filter_remove
435 */
436typedef void (*Elm_Entry_Filter_Cb)(void *data, Evas_Object *entry, char **text);
437
438/**
439 * @typedef Elm_Entry_Change_Info
440 * This corresponds to Edje_Entry_Change_Info. Includes information about
441 * a change in the entry.
442 */
443typedef Edje_Entry_Change_Info Elm_Entry_Change_Info;
444
445/**
446 * This adds an entry to @p parent object.
447 *
448 * By default, entries are:
449 * @li not scrolled
450 * @li multi-line
451 * @li word wrapped
452 * @li autosave is enabled
453 *
454 * @param parent The parent object
455 * @return The new object or NULL if it cannot be created
456 *
457 * @ingroup Entry
458 */
459EAPI Evas_Object *elm_entry_add(Evas_Object *parent);
460
461/**
462 * Sets the entry to single line mode.
463 *
464 * In single line mode, entries don't ever wrap when the text reaches the
465 * edge, and instead they keep growing horizontally. Pressing the @c Enter
466 * key will generate an @c "activate" event instead of adding a new line.
467 *
468 * When @p single_line is @c EINA_FALSE, line wrapping takes effect again
469 * and pressing enter will break the text into a different line
470 * without generating any events.
471 *
472 * @param obj The entry object
473 * @param single_line If true, the text in the entry
474 * will be on a single line.
475 *
476 * @ingroup Entry
477 */
478EAPI void elm_entry_single_line_set(Evas_Object *obj, Eina_Bool single_line);
479
480/**
481 * Gets whether the entry is set to be single line.
482 *
483 * @param obj The entry object
484 * @return single_line If true, the text in the entry is set to display
485 * on a single line.
486 *
487 * @see elm_entry_single_line_set()
488 *
489 * @ingroup Entry
490 */
491EAPI Eina_Bool elm_entry_single_line_get(const Evas_Object *obj);
492
493/**
494 * Sets the entry to password mode.
495 *
496 * In password mode, entries are implicitly single line and the display of
497 * any text in them is replaced with asterisks (*).
498 *
499 * @param obj The entry object
500 * @param password If true, password mode is enabled.
501 *
502 * @ingroup Entry
503 */
504EAPI void elm_entry_password_set(Evas_Object *obj, Eina_Bool password);
505
506/**
507 * Gets whether the entry is set to password mode.
508 *
509 * @param obj The entry object
510 * @return If true, the entry is set to display all characters
511 * as asterisks (*).
512 *
513 * @see elm_entry_password_set()
514 *
515 * @ingroup Entry
516 */
517EAPI Eina_Bool elm_entry_password_get(const Evas_Object *obj);
518
519/**
520 * This sets the text displayed within the entry to @p entry.
521 *
522 * @param obj The entry object
523 * @param entry The text to be displayed
524 *
525 * @note Using this function bypasses text filters
526 *
527 * @ingroup Entry
528 */
529EAPI void elm_entry_entry_set(Evas_Object *obj, const char *entry);
530
531/**
532 * This returns the text currently shown in object @p entry.
533 * See also elm_entry_entry_set().
534 *
535 * @param obj The entry object
536 * @return The currently displayed text or NULL on failure
537 *
538 * @ingroup Entry
539 */
540EAPI const char *elm_entry_entry_get(const Evas_Object *obj);
541
542/**
543 * Appends @p entry to the text of the entry.
544 *
545 * Adds the text in @p entry to the end of any text already present in the
546 * widget.
547 *
548 * The appended text is subject to any filters set for the widget.
549 *
550 * @param obj The entry object
551 * @param entry The text to be displayed
552 *
553 * @see elm_entry_markup_filter_append()
554 *
555 * @ingroup Entry
556 */
557EAPI void elm_entry_entry_append(Evas_Object *obj, const char *entry);
558
559/**
560 * Gets whether the entry is empty.
561 *
562 * Empty means no text at all. If there are any markup tags, like an item
563 * tag for which no provider finds anything, and no text is displayed, this
564 * function still returns EINA_FALSE.
565 *
566 * @param obj The entry object
567 * @return EINA_TRUE if the entry is empty, EINA_FALSE otherwise.
568 *
569 * @ingroup Entry
570 */
571EAPI Eina_Bool elm_entry_is_empty(const Evas_Object *obj);
572
573/**
574 * Gets any selected text within the entry.
575 *
576 * If there's any selected text in the entry, this function returns it as
577 * a string in markup format. NULL is returned if no selection exists or
578 * if an error occurred.
579 *
580 * The returned value points to an internal string and should not be freed
581 * or modified in any way. If the @p entry object is deleted or its
582 * contents are changed, the returned pointer should be considered invalid.
583 *
584 * @param obj The entry object
585 * @return The selected text within the entry or NULL on failure
586 *
587 * @ingroup Entry
588 */
589EAPI const char *elm_entry_selection_get(const Evas_Object *obj);
590
591/**
592 * Returns the actual textblock object of the entry.
593 *
594 * This function exposes the internal textblock object that actually
595 * contains and draws the text. This should be used for low-level
596 * manipulations that are otherwise not possible.
597 *
598 * Changing the textblock directly from here will not notify edje/elm to
599 * recalculate the textblock size automatically, so any modifications
600 * done to the textblock returned by this function should be followed by
601 * a call to elm_entry_calc_force().
602 *
603 * The return value is marked as const as an additional warning.
604 * One should not use the returned object with any of the generic evas
605 * functions (geometry_get/resize/move and etc), but only with the textblock
606 * functions; The former will either not work at all, or break the correct
607 * functionality.
608 *
609 * IMPORTANT: Many functions may change (i.e delete and create a new one)
610 * the internal textblock object. Do NOT cache the returned object, and try
611 * not to mix calls on this object with regular elm_entry calls (which may
612 * change the internal textblock object). This applies to all cursors
613 * returned from textblock calls, and all the other derivative values.
614 *
615 * @param obj The entry object
616 * @return The textblock object.
617 *
618 * @ingroup Entry
619 */
620EAPI Evas_Object * elm_entry_textblock_get(Evas_Object *obj);
621
622/**
623 * Forces calculation of the entry size and text layouting.
624 *
625 * This should be used after modifying the textblock object directly. See
626 * elm_entry_textblock_get() for more information.
627 *
628 * @param obj The entry object
629 *
630 * @see elm_entry_textblock_get()
631 *
632 * @ingroup Entry
633 */
634EAPI void elm_entry_calc_force(Evas_Object *obj);
635
636/**
637 * Inserts the given text into the entry at the current cursor position.
638 *
639 * This inserts text at the cursor position as if it was typed
640 * by the user (note that this also allows markup which a user
641 * can't just "type" as it would be converted to escaped text, so this
642 * call can be used to insert things like emoticon items or bold push/pop
643 * tags, other font and color change tags etc.)
644 *
645 * If any selection exists, it will be replaced by the inserted text.
646 *
647 * The inserted text is subject to any filters set for the widget.
648 *
649 * @param obj The entry object
650 * @param entry The text to insert
651 *
652 * @see elm_entry_markup_filter_append()
653 *
654 * @ingroup Entry
655 */
656EAPI void elm_entry_entry_insert(Evas_Object *obj, const char *entry);
657
658/**
659 * Set the line wrap type to use on multi-line entries.
660 *
661 * Sets the wrap type used by the entry to any of the specified in
662 * Elm_Wrap_Type. This tells how the text will be implicitly cut into a new
663 * line (without inserting a line break or paragraph separator) when it
664 * reaches the far edge of the widget.
665 *
666 * Note that this only makes sense for multi-line entries. A widget set
667 * to be single line will never wrap.
668 *
669 * @param obj The entry object
670 * @param wrap The wrap mode to use. See Elm_Wrap_Type for details on them
671 */
672EAPI void elm_entry_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap);
673
674/**
675 * Gets the wrap mode the entry was set to use.
676 *
677 * @param obj The entry object
678 * @return Wrap type
679 *
680 * @see also elm_entry_line_wrap_set()
681 *
682 * @ingroup Entry
683 */
684EAPI Elm_Wrap_Type elm_entry_line_wrap_get(const Evas_Object *obj);
685
686/**
687 * Sets if the entry is to be editable or not.
688 *
689 * By default, entries are editable and when focused, any text input by the
690 * user will be inserted at the current cursor position. But calling this
691 * function with @p editable as EINA_FALSE will prevent the user from
692 * inputting text into the entry.
693 *
694 * The only way to change the text of a non-editable entry is to use
695 * elm_object_text_set(), elm_entry_entry_insert() and other related
696 * functions.
697 *
698 * @param obj The entry object
699 * @param editable If EINA_TRUE, user input will be inserted in the entry,
700 * if not, the entry is read-only and no user input is allowed.
701 *
702 * @ingroup Entry
703 */
704EAPI void elm_entry_editable_set(Evas_Object *obj, Eina_Bool editable);
705
706/**
707 * Gets whether the entry is editable or not.
708 *
709 * @param obj The entry object
710 * @return If true, the entry is editable by the user.
711 * If false, it is not editable by the user
712 *
713 * @see elm_entry_editable_set()
714 *
715 * @ingroup Entry
716 */
717EAPI Eina_Bool elm_entry_editable_get(const Evas_Object *obj);
718
719/**
720 * This drops any existing text selection within the entry.
721 *
722 * @param obj The entry object
723 *
724 * @ingroup Entry
725 */
726EAPI void elm_entry_select_none(Evas_Object *obj);
727
728/**
729 * This selects all text within the entry.
730 *
731 * @param obj The entry object
732 *
733 * @ingroup Entry
734 */
735EAPI void elm_entry_select_all(Evas_Object *obj);
736
737/**
738 * This moves the cursor one place to the right within the entry.
739 *
740 * @param obj The entry object
741 * @return EINA_TRUE upon success, EINA_FALSE upon failure
742 *
743 * @ingroup Entry
744 */
745EAPI Eina_Bool elm_entry_cursor_next(Evas_Object *obj);
746
747/**
748 * This moves the cursor one place to the left within the entry.
749 *
750 * @param obj The entry object
751 * @return EINA_TRUE upon success, EINA_FALSE upon failure
752 *
753 * @ingroup Entry
754 */
755EAPI Eina_Bool elm_entry_cursor_prev(Evas_Object *obj);
756
757/**
758 * This moves the cursor one line up within the entry.
759 *
760 * @param obj The entry object
761 * @return EINA_TRUE upon success, EINA_FALSE upon failure
762 *
763 * @ingroup Entry
764 */
765EAPI Eina_Bool elm_entry_cursor_up(Evas_Object *obj);
766
767/**
768 * This moves the cursor one line down within the entry.
769 *
770 * @param obj The entry object
771 * @return EINA_TRUE upon success, EINA_FALSE upon failure
772 *
773 * @ingroup Entry
774 */
775EAPI Eina_Bool elm_entry_cursor_down(Evas_Object *obj);
776
777/**
778 * This moves the cursor to the beginning of the entry.
779 *
780 * @param obj The entry object
781 *
782 * @ingroup Entry
783 */
784EAPI void elm_entry_cursor_begin_set(Evas_Object *obj);
785
786/**
787 * This moves the cursor to the end of the entry.
788 *
789 * @param obj The entry object
790 *
791 * @ingroup Entry
792 */
793EAPI void elm_entry_cursor_end_set(Evas_Object *obj);
794
795/**
796 * This moves the cursor to the beginning of the current line.
797 *
798 * @param obj The entry object
799 *
800 * @ingroup Entry
801 */
802EAPI void elm_entry_cursor_line_begin_set(Evas_Object *obj);
803
804/**
805 * This moves the cursor to the end of the current line.
806 *
807 * @param obj The entry object
808 *
809 * @ingroup Entry
810 */
811EAPI void elm_entry_cursor_line_end_set(Evas_Object *obj);
812
813/**
814 * This begins a selection within the entry as though
815 * the user were holding down the mouse button to make a selection.
816 *
817 * @param obj The entry object
818 *
819 * @ingroup Entry
820 */
821EAPI void elm_entry_cursor_selection_begin(Evas_Object *obj);
822
823/**
824 * This ends a selection within the entry as though
825 * the user had just released the mouse button while making a selection.
826 *
827 * @param obj The entry object
828 *
829 * @ingroup Entry
830 */
831EAPI void elm_entry_cursor_selection_end(Evas_Object *obj);
832
833/**
834 * Gets whether a format node exists at the current cursor position.
835 *
836 * A format node is anything that defines how the text is rendered. It can
837 * be a visible format node, such as a line break or a paragraph separator,
838 * or an invisible one, such as bold begin or end tag.
839 * This function returns whether any format node exists at the current
840 * cursor position.
841 *
842 * @param obj The entry object
843 * @return EINA_TRUE if the current cursor position contains a format node,
844 * EINA_FALSE otherwise.
845 *
846 * @see elm_entry_cursor_is_visible_format_get()
847 *
848 * @ingroup Entry
849 */
850EAPI Eina_Bool elm_entry_cursor_is_format_get(const Evas_Object *obj);
851
852/**
853 * Gets if the current cursor position holds a visible format node.
854 *
855 * @param obj The entry object
856 * @return EINA_TRUE if the current cursor is a visible format, EINA_FALSE
857 * if it's an invisible one or no format exists.
858 *
859 * @see elm_entry_cursor_is_format_get()
860 *
861 * @ingroup Entry
862 */
863EAPI Eina_Bool elm_entry_cursor_is_visible_format_get(const Evas_Object *obj);
864
865/**
866 * Gets the character pointed by the cursor at its current position.
867 *
868 * This function returns a string with the utf8 character stored at the
869 * current cursor position.
870 * Only the text is returned, any format that may exist will not be part
871 * of the return value. You must free the string when done with free().
872 *
873 * @param obj The entry object
874 * @return The text pointed by the cursors.
875 *
876 * @ingroup Entry
877 */
878EAPI char *elm_entry_cursor_content_get(const Evas_Object *obj);
879
880/**
881 * This function returns the geometry of the cursor.
882 *
883 * It's useful if you want to draw something on the cursor (or where it is),
884 * or for example in the case of scrolled entry where you want to show the
885 * cursor.
886 *
887 * @param obj The entry object
888 * @param x returned geometry
889 * @param y returned geometry
890 * @param w returned geometry
891 * @param h returned geometry
892 * @return EINA_TRUE upon success, EINA_FALSE upon failure
893 *
894 * @ingroup Entry
895 */
896EAPI Eina_Bool elm_entry_cursor_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
897
898/**
899 * Sets the cursor position in the entry to the given value
900 *
901 * The value in @p pos is the index of the character position within the
902 * contents of the string as returned by elm_entry_cursor_pos_get().
903 *
904 * @param obj The entry object
905 * @param pos The position of the cursor
906 *
907 * @ingroup Entry
908 */
909EAPI void elm_entry_cursor_pos_set(Evas_Object *obj, int pos);
910
911/**
912 * Retrieves the current position of the cursor in the entry
913 *
914 * @param obj The entry object
915 * @return The cursor position
916 *
917 * @ingroup Entry
918 */
919EAPI int elm_entry_cursor_pos_get(const Evas_Object *obj);
920
921/**
922 * This executes a "cut" action on the selected text in the entry.
923 *
924 * @param obj The entry object
925 *
926 * @ingroup Entry
927 */
928EAPI void elm_entry_selection_cut(Evas_Object *obj);
929
930/**
931 * This executes a "copy" action on the selected text in the entry.
932 *
933 * @param obj The entry object
934 *
935 * @ingroup Entry
936 */
937EAPI void elm_entry_selection_copy(Evas_Object *obj);
938
939/**
940 * This executes a "paste" action in the entry.
941 *
942 * @param obj The entry object
943 *
944 * @ingroup Entry
945 */
946EAPI void elm_entry_selection_paste(Evas_Object *obj);
947
948/**
949 * This clears and frees the items in a entry's contextual (longpress)
950 * menu.
951 *
952 * @param obj The entry object
953 *
954 * @see elm_entry_context_menu_item_add()
955 *
956 * @ingroup Entry
957 */
958EAPI void elm_entry_context_menu_clear(Evas_Object *obj);
959
960/**
961 * This adds an item to the entry's contextual menu.
962 *
963 * A longpress on an entry will make the contextual menu show up, if this
964 * hasn't been disabled with elm_entry_context_menu_disabled_set().
965 * By default, this menu provides a few options like enabling selection mode,
966 * which is useful on embedded devices that need to be explicit about it,
967 * and when a selection exists it also shows the copy and cut actions.
968 *
969 * With this function, developers can add other options to this menu to
970 * perform any action they deem necessary.
971 *
972 * @param obj The entry object
973 * @param label The item's text label
974 * @param icon_file The item's icon file
975 * @param icon_type The item's icon type
976 * @param func The callback to execute when the item is clicked
977 * @param data The data to associate with the item for related functions
978 *
979 * @ingroup Entry
980 */
981EAPI 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);
982
983/**
984 * This disables the entry's contextual (longpress) menu.
985 *
986 * @param obj The entry object
987 * @param disabled If true, the menu is disabled
988 *
989 * @ingroup Entry
990 */
991EAPI void elm_entry_context_menu_disabled_set(Evas_Object *obj, Eina_Bool disabled);
992
993/**
994 * This returns whether the entry's contextual (longpress) menu is
995 * disabled.
996 *
997 * @param obj The entry object
998 * @return If true, the menu is disabled
999 *
1000 * @ingroup Entry
1001 */
1002EAPI Eina_Bool elm_entry_context_menu_disabled_get(const Evas_Object *obj);
1003
1004/**
1005 * This appends a custom item provider to the list for that entry
1006 *
1007 * This appends the given callback. The list is walked from beginning to end
1008 * with each function called given the item href string in the text. If the
1009 * function returns an object handle other than NULL (it should create an
1010 * object to do this), then this object is used to replace that item. If
1011 * not the next provider is called until one provides an item object, or the
1012 * default provider in entry does.
1013 *
1014 * @param obj The entry object
1015 * @param func The function called to provide the item object
1016 * @param data The data passed to @p func
1017 *
1018 * @see @ref entry-items
1019 *
1020 * @ingroup Entry
1021 */
1022EAPI void elm_entry_item_provider_append(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data);
1023
1024/**
1025 * This prepends a custom item provider to the list for that entry
1026 *
1027 * This prepends the given callback. See elm_entry_item_provider_append() for
1028 * more information
1029 *
1030 * @param obj The entry object
1031 * @param func The function called to provide the item object
1032 * @param data The data passed to @p func
1033 *
1034 * @ingroup Entry
1035 */
1036EAPI void elm_entry_item_provider_prepend(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data);
1037
1038/**
1039 * This removes a custom item provider to the list for that entry
1040 *
1041 * This removes the given callback. See elm_entry_item_provider_append() for
1042 * more information
1043 *
1044 * @param obj The entry object
1045 * @param func The function called to provide the item object
1046 * @param data The data passed to @p func
1047 *
1048 * @ingroup Entry
1049 */
1050EAPI void elm_entry_item_provider_remove(Evas_Object *obj, Elm_Entry_Item_Provider_Cb func, void *data);
1051
1052/**
1053 * Append a markup filter function for text inserted in the entry
1054 *
1055 * Append the given callback to the list. This functions will be called
1056 * whenever any text is inserted into the entry, with the text to be inserted
1057 * as a parameter. The type of given text is always markup.
1058 * The callback function is free to alter the text in any way it wants, but
1059 * it must remember to free the given pointer and update it.
1060 * If the new text is to be discarded, the function can free it and set its
1061 * text parameter to NULL. This will also prevent any following filters from
1062 * being called.
1063 *
1064 * @param obj The entry object
1065 * @param func The function to use as text filter
1066 * @param data User data to pass to @p func
1067 *
1068 * @ingroup Entry
1069 */
1070EAPI void elm_entry_markup_filter_append(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data);
1071
1072/**
1073 * Prepend a markup filter function for text inserted in the entry
1074 *
1075 * Prepend the given callback to the list. See elm_entry_markup_filter_append()
1076 * for more information
1077 *
1078 * @param obj The entry object
1079 * @param func The function to use as text filter
1080 * @param data User data to pass to @p func
1081 *
1082 * @ingroup Entry
1083 */
1084EAPI void elm_entry_markup_filter_prepend(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data);
1085
1086/**
1087 * Remove a markup filter from the list
1088 *
1089 * Removes the given callback from the filter list. See
1090 * elm_entry_markup_filter_append() for more information.
1091 *
1092 * @param obj The entry object
1093 * @param func The filter function to remove
1094 * @param data The user data passed when adding the function
1095 *
1096 * @ingroup Entry
1097 */
1098EAPI void elm_entry_markup_filter_remove(Evas_Object *obj, Elm_Entry_Filter_Cb func, void *data);
1099
1100/**
1101 * This converts a markup (HTML-like) string into UTF-8.
1102 *
1103 * The returned string is a malloc'ed buffer and it should be freed when
1104 * not needed anymore.
1105 *
1106 * @param s The string (in markup) to be converted
1107 * @return The converted string (in UTF-8). It should be freed.
1108 *
1109 * @ingroup Entry
1110 */
1111EAPI char *elm_entry_markup_to_utf8(const char *s);
1112
1113/**
1114 * This converts a UTF-8 string into markup (HTML-like).
1115 *
1116 * The returned string is a malloc'ed buffer and it should be freed when
1117 * not needed anymore.
1118 *
1119 * @param s The string (in UTF-8) to be converted
1120 * @return The converted string (in markup). It should be freed.
1121 *
1122 * @ingroup Entry
1123 */
1124EAPI char *elm_entry_utf8_to_markup(const char *s);
1125
1126/**
1127 * This sets the file (and implicitly loads it) for the text to display and
1128 * then edit. All changes are written back to the file after a short delay if
1129 * the entry object is set to autosave (which is the default).
1130 *
1131 * If the entry had any other file set previously, any changes made to it
1132 * will be saved if the autosave feature is enabled, otherwise, the file
1133 * will be silently discarded and any non-saved changes will be lost.
1134 *
1135 * @param obj The entry object
1136 * @param file The path to the file to load and save
1137 * @param format The file format
1138 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
1139 *
1140 * @ingroup Entry
1141 */
1142EAPI Eina_Bool elm_entry_file_set(Evas_Object *obj, const char *file, Elm_Text_Format format);
1143
1144/**
1145 * Gets the file being edited by the entry.
1146 *
1147 * This function can be used to retrieve any file set on the entry for
1148 * edition, along with the format used to load and save it.
1149 *
1150 * @param obj The entry object
1151 * @param file The path to the file to load and save
1152 * @param format The file format
1153 *
1154 * @ingroup Entry
1155 */
1156EAPI void elm_entry_file_get(const Evas_Object *obj, const char **file, Elm_Text_Format *format);
1157
1158/**
1159 * This function writes any changes made to the file set with
1160 * elm_entry_file_set()
1161 *
1162 * @param obj The entry object
1163 *
1164 * @ingroup Entry
1165 */
1166EAPI void elm_entry_file_save(Evas_Object *obj);
1167
1168/**
1169 * This sets the entry object to 'autosave' the loaded text file or not.
1170 *
1171 * @param obj The entry object
1172 * @param autosave Autosave the loaded file or not
1173 *
1174 * @see elm_entry_file_set()
1175 *
1176 * @ingroup Entry
1177 */
1178EAPI void elm_entry_autosave_set(Evas_Object *obj, Eina_Bool autosave);
1179
1180/**
1181 * This gets the entry object's 'autosave' status.
1182 *
1183 * @param obj The entry object
1184 * @return Autosave the loaded file or not
1185 *
1186 * @see elm_entry_file_set()
1187 *
1188 * @ingroup Entry
1189 */
1190EAPI Eina_Bool elm_entry_autosave_get(const Evas_Object *obj);
1191
1192/**
1193 * Enable or disable scrolling in entry
1194 *
1195 * Normally the entry is not scrollable unless you enable it with this call.
1196 *
1197 * @param obj The entry object
1198 * @param scroll EINA_TRUE if it is to be scrollable, EINA_FALSE otherwise
1199 *
1200 * @ingroup Entry
1201 */
1202EAPI void elm_entry_scrollable_set(Evas_Object *obj, Eina_Bool scroll);
1203
1204/**
1205 * Get the scrollable state of the entry
1206 *
1207 * Normally the entry is not scrollable. This gets the scrollable state
1208 * of the entry. See elm_entry_scrollable_set() for more information.
1209 *
1210 * @param obj The entry object
1211 * @return The scrollable state
1212 *
1213 * @ingroup Entry
1214 */
1215EAPI Eina_Bool elm_entry_scrollable_get(const Evas_Object *obj);
1216
1217/**
1218 * Sets the visibility of the left-side widget of the entry,
1219 * set by elm_object_part_content_set().
1220 *
1221 * @param obj The entry object
1222 * @param setting EINA_TRUE if the object should be displayed,
1223 * EINA_FALSE if not.
1224 *
1225 * @ingroup Entry
1226 */
1227EAPI void elm_entry_icon_visible_set(Evas_Object *obj, Eina_Bool setting);
1228
1229/**
1230 * Sets the visibility of the end widget of the entry, set by
1231 * elm_object_part_content_set(ent, "end", content).
1232 *
1233 * @param obj The entry object
1234 * @param setting EINA_TRUE if the object should be displayed,
1235 * EINA_FALSE if not.
1236 *
1237 * @ingroup Entry
1238 */
1239EAPI void elm_entry_end_visible_set(Evas_Object *obj, Eina_Bool setting);
1240
1241/**
1242 * This sets the entry's scrollbar policy (i.e. enabling/disabling
1243 * them).
1244 *
1245 * Setting an entry to single-line mode with elm_entry_single_line_set()
1246 * will automatically disable the display of scrollbars when the entry
1247 * moves inside its scroller.
1248 *
1249 * @param obj The entry object
1250 * @param h The horizontal scrollbar policy to apply
1251 * @param v The vertical scrollbar policy to apply
1252 *
1253 * @ingroup Entry
1254 */
1255EAPI void elm_entry_scrollbar_policy_set(Evas_Object *obj, Elm_Scroller_Policy h, Elm_Scroller_Policy v);
1256
1257/**
1258 * This enables/disables bouncing within the entry.
1259 *
1260 * This function sets whether the entry will bounce when scrolling reaches
1261 * the end of the contained entry.
1262 *
1263 * @param obj The entry object
1264 * @param h_bounce The horizontal bounce state
1265 * @param v_bounce The vertical bounce state
1266 *
1267 * @ingroup Entry
1268 */
1269EAPI void elm_entry_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
1270
1271/**
1272 * Get the bounce mode
1273 *
1274 * @param obj The Entry object
1275 * @param h_bounce Allow bounce horizontally
1276 * @param v_bounce Allow bounce vertically
1277 *
1278 * @ingroup Entry
1279 */
1280EAPI void elm_entry_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
1281
1282/**
1283 * Set the input panel layout of the entry
1284 *
1285 * @param obj The entry object
1286 * @param layout layout type
1287 *
1288 * @ingroup Entry
1289 */
1290EAPI void elm_entry_input_panel_layout_set(Evas_Object *obj, Elm_Input_Panel_Layout layout);
1291
1292/**
1293 * Get the input panel layout of the entry
1294 *
1295 * @param obj The entry object
1296 * @return layout type
1297 *
1298 * @see elm_entry_input_panel_layout_set
1299 *
1300 * @ingroup Entry
1301 */
1302EAPI Elm_Input_Panel_Layout elm_entry_input_panel_layout_get(const Evas_Object *obj);
1303
1304/**
1305 * Set the autocapitalization type on the immodule.
1306 *
1307 * @param obj The entry object
1308 * @param autocapital_type The type of autocapitalization
1309 *
1310 * @ingroup Entry
1311 */
1312EAPI void elm_entry_autocapital_type_set(Evas_Object *obj, Elm_Autocapital_Type autocapital_type);
1313
1314/**
1315 * Retrieve the autocapitalization type on the immodule.
1316 *
1317 * @param obj The entry object
1318 * @return autocapitalization type
1319 *
1320 * @ingroup Entry
1321 */
1322EAPI Elm_Autocapital_Type elm_entry_autocapital_type_get(const Evas_Object *obj);
1323
1324/**
1325 * Sets the attribute to show the input panel automatically.
1326 *
1327 * @param obj The entry object
1328 * @param enabled If true, the input panel is appeared when entry is clicked or has a focus
1329 *
1330 * @ingroup Entry
1331 */
1332EAPI void elm_entry_input_panel_enabled_set(Evas_Object *obj, Eina_Bool enabled);
1333
1334/**
1335 * Retrieve the attribute to show the input panel automatically.
1336 *
1337 * @param obj The entry object
1338 * @return EINA_TRUE if input panel will be appeared when the entry is clicked or has a focus, EINA_FALSE otherwise
1339 *
1340 * @ingroup Entry
1341 */
1342EAPI Eina_Bool elm_entry_input_panel_enabled_get(const Evas_Object *obj);
1343
1344/**
1345 * Show the input panel (virtual keyboard) based on the input panel property of entry such as layout, autocapital types, and so on.
1346 *
1347 * Note that input panel is shown or hidden automatically according to the focus state of entry widget.
1348 * This API can be used in the case of manually controlling by using elm_entry_input_panel_enabled_set(en, EINA_FALSE).
1349 *
1350 * @param obj The entry object
1351 *
1352 * @ingroup Entry
1353 */
1354EAPI void elm_entry_input_panel_show(Evas_Object *obj);
1355
1356/**
1357 * Hide the input panel (virtual keyboard).
1358 *
1359 * Note that input panel is shown or hidden automatically according to the focus state of entry widget.
1360 * This API can be used in the case of manually controlling by using elm_entry_input_panel_enabled_set(en, EINA_FALSE)
1361 *
1362 * @param obj The entry object
1363 *
1364 * @ingroup Entry
1365 */
1366EAPI void elm_entry_input_panel_hide(Evas_Object *obj);
1367
1368/**
1369 * Set the language mode of the input panel.
1370 *
1371 * This API can be used if you want to show the alphabet keyboard mode.
1372 *
1373 * @param obj The entry object
1374 * @param lang language to be set to the input panel.
1375 *
1376 * @ingroup Entry
1377 */
1378EAPI void elm_entry_input_panel_language_set(Evas_Object *obj, Elm_Input_Panel_Lang lang);
1379
1380/**
1381 * Get the language mode of the input panel.
1382 *
1383 * See @ref elm_entry_input_panel_language_set for more details.
1384 *
1385 * @param obj The entry object
1386 * @return input panel language type
1387 *
1388 * @ingroup Entry
1389 */
1390EAPI Elm_Input_Panel_Lang elm_entry_input_panel_language_get(const Evas_Object *obj);
1391
1392/**
1393 * Set the input panel-specific data to deliver to the input panel.
1394 *
1395 * This API is used by applications to deliver specific data to the input panel.
1396 * The data format MUST be negotiated by both application and the input panel.
1397 * The size and format of data are defined by the input panel.
1398 *
1399 * @param obj The entry object
1400 * @param data The specific data to be set to the input panel.
1401 * @param len the length of data, in bytes, to send to the input panel
1402 *
1403 * @ingroup Entry
1404 */
1405EAPI void elm_entry_input_panel_imdata_set(Evas_Object *obj, const void *data, int len);
1406
1407/**
1408 * Get the specific data of the current input panel.
1409 *
1410 * See @ref elm_entry_input_panel_imdata_set for more details.
1411 *
1412 * @param obj The entry object
1413 * @param data The specific data to be got from the input panel
1414 * @param len The length of data
1415 *
1416 * @ingroup Entry
1417 */
1418EAPI void elm_entry_input_panel_imdata_get(const Evas_Object *obj, void *data, int *len);
1419
1420/**
1421 * Set the "return" key type. This type is used to set string or icon on the "return" key of the input panel.
1422 *
1423 * An input panel displays the string or icon associated with this type
1424 *
1425 * @param obj The entry object
1426 * @param return_key_type The type of "return" key on the input panel
1427 *
1428 * @ingroup Entry
1429 */
1430EAPI void elm_entry_input_panel_return_key_type_set(Evas_Object *obj, Elm_Input_Panel_Return_Key_Type return_key_type);
1431
1432/**
1433 * Get the "return" key type.
1434 *
1435 * @see elm_entry_input_panel_return_key_type_set() for more details
1436 *
1437 * @param obj The entry object
1438 * @return The type of "return" key on the input panel
1439 *
1440 * @ingroup Entry
1441 */
1442EAPI Elm_Input_Panel_Return_Key_Type elm_entry_input_panel_return_key_type_get(const Evas_Object *obj);
1443
1444/**
1445 * Set the return key on the input panel to be disabled.
1446 *
1447 * @param obj The entry object
1448 * @param disabled The state to put in in: @c EINA_TRUE for
1449 * disabled, @c EINA_FALSE for enabled
1450 *
1451 * @ingroup Entry
1452 */
1453EAPI void elm_entry_input_panel_return_key_disabled_set(Evas_Object *obj, Eina_Bool disabled);
1454
1455/**
1456 * Get whether the return key on the input panel should be disabled or not.
1457 *
1458 * @param obj The entry object
1459 * @return EINA_TRUE if it should be disabled
1460 *
1461 * @ingroup Entry
1462 */
1463EAPI Eina_Bool elm_entry_input_panel_return_key_disabled_get(const Evas_Object *obj);
1464
1465/**
1466 * Set whether the return key on the input panel is disabled automatically when entry has no text.
1467 *
1468 * If @p enabled is EINA_TRUE, The return key on input panel is disabled when the entry has no text.
1469 * The return key on the input panel is automatically enabled when the entry has text.
1470 * The default value is EINA_FALSE.
1471 *
1472 * @param obj The entry object
1473 * @param enabled If @p enabled is EINA_TRUE, the return key is automatically disabled when the entry has no text.
1474 *
1475 * @ingroup Entry
1476 */
1477EAPI void elm_entry_input_panel_return_key_autoenabled_set(Evas_Object *obj, Eina_Bool enabled);
1478
1479/**
1480 * Reset the input method context of the entry if needed.
1481 *
1482 * This can be necessary in the case where modifying the buffer would confuse on-going input method behavior
1483 * @param obj The entry object
1484 *
1485 * @ingroup Entry
1486 */
1487EAPI void elm_entry_imf_context_reset(Evas_Object *obj);
1488
1489/**
1490 * Set whether the entry should allow to use the text prediction.
1491 *
1492 * @param obj The entry object
1493 * @param prediction Whether the entry should allow to use the text prediction.
1494 *
1495 * @ingroup Entry
1496 */
1497EAPI void elm_entry_prediction_allow_set(Evas_Object *obj, Eina_Bool prediction);
1498
1499/**
1500 * Get whether the entry should allow to use the text prediction.
1501 *
1502 * @param obj The entry object
1503 * @return EINA_TRUE if it allows to use the text prediction, otherwise EINA_FALSE.
1504 *
1505 * @ingroup Entry
1506 */
1507EAPI Eina_Bool elm_entry_prediction_allow_get(const Evas_Object *obj);
1508
1509/* pre-made filters for entries */
1510
1511/**
1512 * @typedef Elm_Entry_Filter_Limit_Size
1513 *
1514 * Data for the elm_entry_filter_limit_size() entry filter.
1515 */
1516typedef struct _Elm_Entry_Filter_Limit_Size Elm_Entry_Filter_Limit_Size;
1517
1518/**
1519 * @struct _Elm_Entry_Filter_Limit_Size
1520 *
1521 * Data for the elm_entry_filter_limit_size() entry filter.
1522 */
1523struct _Elm_Entry_Filter_Limit_Size
1524{
1525 int max_char_count; /**< The maximum number of characters allowed. */
1526 int max_byte_count; /**< The maximum number of bytes allowed*/
1527};
1528
1529/**
1530 * Filter inserted text based on user defined character and byte limits
1531 *
1532 * Add this filter to an entry to limit the characters that it will accept
1533 * based the contents of the provided #Elm_Entry_Filter_Limit_Size.
1534 * The function works on the UTF-8 representation of the string, converting
1535 * it from the set markup, thus not accounting for any format in it.
1536 *
1537 * The user must create an #Elm_Entry_Filter_Limit_Size structure and pass
1538 * it as data when setting the filter. In it, it's possible to set limits
1539 * by character count or bytes (any of them is disabled if 0), and both can
1540 * be set at the same time. In that case, it first checks for characters,
1541 * then bytes. The #Elm_Entry_Filter_Limit_Size structure must be alive and
1542 * valid for as long as the entry is alive AND the elm_entry_filter_limit_size
1543 * filter is set.
1544 *
1545 * The function will cut the inserted text in order to allow only the first
1546 * number of characters that are still allowed. The cut is made in
1547 * characters, even when limiting by bytes, in order to always contain
1548 * valid ones and avoid half unicode characters making it in.
1549 *
1550 * This filter, like any others, does not apply when setting the entry text
1551 * directly with elm_object_text_set().
1552 *
1553 * @ingroup Entry
1554 */
1555EAPI void elm_entry_filter_limit_size(void *data, Evas_Object *entry, char **text);
1556
1557/**
1558 * @typedef Elm_Entry_Filter_Accept_Set
1559 *
1560 * Data for the elm_entry_filter_accept_set() entry filter.
1561 */
1562typedef struct _Elm_Entry_Filter_Accept_Set Elm_Entry_Filter_Accept_Set;
1563
1564/**
1565 * @struct _Elm_Entry_Filter_Accept_Set
1566 *
1567 * Data for the elm_entry_filter_accept_set() entry filter.
1568 */
1569struct _Elm_Entry_Filter_Accept_Set
1570{
1571 const char *accepted; /**< Set of characters accepted in the entry. */
1572 const char *rejected; /**< Set of characters rejected from the entry. */
1573};
1574
1575/**
1576 * Filter inserted text based on accepted or rejected sets of characters
1577 *
1578 * Add this filter to an entry to restrict the set of accepted characters
1579 * based on the sets in the provided #Elm_Entry_Filter_Accept_Set.
1580 * This structure contains both accepted and rejected sets, but they are
1581 * mutually exclusive. This structure must be available for as long as
1582 * the entry is alive AND the elm_entry_filter_accept_set is being used.
1583 *
1584 * The @c accepted set takes preference, so if it is set, the filter will
1585 * only work based on the accepted characters, ignoring anything in the
1586 * @c rejected value. If @c accepted is @c NULL, then @c rejected is used.
1587 *
1588 * In both cases, the function filters by matching utf8 characters to the
1589 * raw markup text, so it can be used to remove formatting tags.
1590 *
1591 * This filter, like any others, does not apply when setting the entry text
1592 * directly with elm_object_text_set()
1593 *
1594 * @ingroup Entry
1595 */
1596EAPI void elm_entry_filter_accept_set(void *data, Evas_Object *entry, char **text);
1597
1598/**
1599 * Returns the input method context of the entry.
1600 *
1601 * This function exposes the internal input method context.
1602 *
1603 * IMPORTANT: Many functions may change (i.e delete and create a new one)
1604 * the internal input method context. Do NOT cache the returned object.
1605 *
1606 * @param obj The entry object
1607 * @return The input method context (Ecore_IMF_Context *) in entry.
1608 *
1609 * @ingroup Entry
1610 */
1611EAPI void *elm_entry_imf_context_get(Evas_Object *obj);
1612
1613/**
1614 * @typedef Elm_Cnp_Mode
1615 * Enum of entry's copy & paste policy.
1616 *
1617 * @see elm_entry_cnp_mode_set()
1618 * @see elm_entry_cnp_mode_get()
1619 */
1620typedef enum {
1621 ELM_CNP_MODE_MARKUP, /**< copy & paste text with markup tag */
1622 ELM_CNP_MODE_NO_IMAGE, /**< copy & paste text without item(image) tag */
1623 ELM_CNP_MODE_PLAINTEXT /**< copy & paste text without markup tag */
1624} Elm_Cnp_Mode;
1625
1626/**
1627 * Control pasting of text and images for the widget.
1628 *
1629 * Normally the entry allows both text and images to be pasted.
1630 * By setting cnp_mode to be ELM_CNP_MODE_NO_IMAGE, this prevents images from being copy or past.
1631 * By setting cnp_mode to be ELM_CNP_MODE_PLAINTEXT, this remove all tags in text .
1632 *
1633 * @note this only changes the behaviour of text.
1634 *
1635 * @param obj The entry object
1636 * @param cnp_mode One of #Elm_Cnp_Mode: #ELM_CNP_MODE_MARKUP,
1637 * #ELM_CNP_MODE_NO_IMAGE, #ELM_CNP_MODE_PLAINTEXT.
1638 *
1639 * @ingroup Entry
1640 */
1641EAPI void elm_entry_cnp_mode_set(Evas_Object *obj, Elm_Cnp_Mode cnp_mode);
1642
1643/**
1644 * Getting elm_entry text paste/drop mode.
1645 *
1646 * Normally the entry allows both text and images to be pasted.
1647 * This gets the copy & paste mode of the entry.
1648 *
1649 * @param obj The entry object
1650 * @return mode One of #Elm_Cnp_Mode: #ELM_CNP_MODE_MARKUP,
1651 * #ELM_CNP_MODE_NO_IMAGE, #ELM_CNP_MODE_PLAINTEXT.
1652 *
1653 * @ingroup Entry
1654 */
1655EAPI Elm_Cnp_Mode elm_entry_cnp_mode_get(const Evas_Object *obj);
1656
1657/**
1658 * Set the parent of the hover popup
1659 *
1660 * Sets the parent object to use by the hover created by the entry
1661 * when an anchor is clicked. See @ref Hover for more details on this.
1662 *
1663 * @param obj The entry object
1664 * @param parent The object to use as parent for the hover
1665 *
1666 * @ingroup Entry
1667 */
1668EAPI void elm_entry_anchor_hover_parent_set(Evas_Object *obj, Evas_Object *parent);
1669
1670/**
1671 * Get the parent of the hover popup
1672 *
1673 * Get the object used as parent for the hover created by the entry
1674 * widget. See @ref Hover for more details on this.
1675 * If no parent is set, the same entry object will be used.
1676 *
1677 * @param obj The entry object
1678 * @return The object used as parent for the hover, NULL if none is set.
1679 *
1680 * @ingroup Entry
1681 */
1682EAPI Evas_Object *elm_entry_anchor_hover_parent_get(const Evas_Object *obj);
1683
1684/**
1685 * Set the style that the hover should use
1686 *
1687 * When creating the popup hover, entry will request that it's
1688 * themed according to @p style.
1689 *
1690 * Setting style no NULL means disabling automatic hover.
1691 *
1692 * @param obj The entry object
1693 * @param style The style to use for the underlying hover
1694 *
1695 * @see elm_object_style_set()
1696 *
1697 * @ingroup Entry
1698 */
1699EAPI void elm_entry_anchor_hover_style_set(Evas_Object *obj, const char *style);
1700
1701/**
1702 * Get the style that the hover should use
1703 *
1704 * Get the style, the hover created by entry will use.
1705 *
1706 * @param obj The entry object
1707 * @return The style to use by the hover. NULL means the default is used.
1708 *
1709 * @see elm_object_style_set()
1710 *
1711 * @ingroup Entry
1712 */
1713EAPI const char *elm_entry_anchor_hover_style_get(const Evas_Object *obj);
1714
1715/**
1716 * Ends the hover popup in the entry
1717 *
1718 * When an anchor is clicked, the entry widget will create a hover
1719 * object to use as a popup with user provided content. This function
1720 * terminates this popup, returning the entry to its normal state.
1721 *
1722 * @param obj The entry object
1723 *
1724 * @ingroup Entry
1725 */
1726EAPI void elm_entry_anchor_hover_end(Evas_Object *obj);
1727
1728/**
1729 * @}
1730 */
diff --git a/libraries/elementary/src/lib/elm_factory.c b/libraries/elementary/src/lib/elm_factory.c
new file mode 100644
index 0000000..25a3d37
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_factory.c
@@ -0,0 +1,338 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4// FIXME: handle if canvas resizes
5
6typedef struct _Widget_Data Widget_Data;
7
8struct _Widget_Data
9{
10 Evas_Object *obj;
11 Evas_Object *content;
12 int last_calc_count;
13 Evas_Coord maxminw, maxminh;
14 Eina_Bool eval : 1;
15 Eina_Bool szeval : 1;
16 Eina_Bool maxmin : 1;
17};
18
19static const char *widtype = NULL;
20static void _del_hook(Evas_Object *obj);
21static Eina_Bool _focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next);
22static void _sizing_eval(Evas_Object *obj);
23static void _eval(Evas_Object *obj);
24static void _changed(Evas_Object *obj);
25static void _move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
26static void _resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
27static void _child_change(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
28static void _child_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
29static void _content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content);
30static Evas_Object *_content_get_hook(const Evas_Object *obj, const char *part);
31static Evas_Object *_content_unset_hook(Evas_Object *obj, const char *part);
32
33static const char SIG_REALIZE[] = "realize";
34static const char SIG_UNREALIZE[] = "unrealize";
35
36static const Evas_Smart_Cb_Description _signals[] = {
37 {SIG_REALIZE, ""},
38 {SIG_UNREALIZE, ""},
39 {NULL, NULL}
40};
41
42static int fac = 0;
43
44static void
45_del_hook(Evas_Object *obj)
46{
47 Widget_Data *wd = elm_widget_data_get(obj);
48 if (!wd) return;
49 if (wd->content)
50 {
51 Evas_Object *o = wd->content;
52
53 evas_object_event_callback_del_full(o,
54 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
55 _child_change, obj);
56 evas_object_event_callback_del_full(o,
57 EVAS_CALLBACK_DEL,
58 _child_del, obj);
59 wd->content = NULL;
60 evas_object_del(o);
61 fac--;
62// printf("FAC-- = %i\n", fac);
63 }
64 free(wd);
65}
66
67static Eina_Bool
68_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
69{
70 Widget_Data *wd = elm_widget_data_get(obj);
71 Evas_Object *cur;
72
73 if ((!wd) || (!wd->content)) return EINA_FALSE;
74 cur = wd->content;
75 return elm_widget_focus_next_get(cur, dir, next);
76}
77
78static void
79_sizing_eval(Evas_Object *obj)
80{
81 Widget_Data *wd = elm_widget_data_get(obj);
82 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
83
84 if (!wd) return;
85 if (!wd->content) return;
86 evas_object_size_hint_min_get(wd->content, &minw, &minh);
87 evas_object_size_hint_max_get(wd->content, &maxw, &maxh);
88 if (wd->maxmin)
89 {
90 if (minw > wd->maxminw) wd->maxminw = minw;
91 if (minh > wd->maxminh) wd->maxminh = minh;
92 evas_object_size_hint_min_set(obj, wd->maxminw, wd->maxminh);
93 }
94 else
95 {
96 evas_object_size_hint_min_set(obj, minw, minh);
97 }
98 evas_object_size_hint_max_set(obj, maxw, maxh);
99// printf("FAC SZ: %i %i | %i %i\n", minw, minh, maxw, maxh);
100}
101
102static void
103_eval(Evas_Object *obj)
104{
105 Evas_Coord x, y, w, h, cvx, cvy, cvw, cvh;
106 Widget_Data *wd = elm_widget_data_get(obj);
107 if (!wd) return;
108
109 evas_event_freeze(evas_object_evas_get(obj));
110 evas_object_geometry_get(obj, &x, &y, &w, &h);
111 if (w < 1) w = 1;
112 if (h < 1) h = 1;
113 evas_output_viewport_get(evas_object_evas_get(obj),
114 &cvx, &cvy, &cvw, &cvh);
115 if ((cvw < 1) || (cvh < 1)) return;
116 // need some fuzz value thats beyond the current viewport
117 // for now just make it the viewport * 3 in size (so 1 vp in each direction)
118 /*
119 cvx -= cvw;
120 cvy -= cvh;
121 cvw *= 3;
122 cvh *= 3;
123 */
124 if (ELM_RECTS_INTERSECT(x, y, w, h, cvx, cvy, cvw, cvh))
125 {
126 if (!wd->content)
127 {
128// printf(" + %i %i %ix%i <> %i %i %ix%i\n", x, y, w, h, cvx, cvy, cvw, cvh);
129 evas_object_smart_callback_call(obj, SIG_REALIZE, NULL);
130 if (wd->content)
131 {
132 if (evas_object_smart_data_get(wd->content))
133 evas_object_smart_calculate(wd->content);
134 }
135 wd->last_calc_count =
136 evas_smart_objects_calculate_count_get(evas_object_evas_get(obj));
137 }
138 }
139 else
140 {
141 if (wd->content)
142 {
143 if (wd->last_calc_count !=
144 evas_smart_objects_calculate_count_get(evas_object_evas_get(obj)))
145 evas_object_smart_callback_call(obj, SIG_UNREALIZE, NULL);
146 }
147 }
148 evas_event_thaw(evas_object_evas_get(obj));
149 evas_event_thaw_eval(evas_object_evas_get(obj));
150}
151
152static void
153_changed(Evas_Object *obj)
154{
155 Widget_Data *wd = elm_widget_data_get(obj);
156 if (!wd) return;
157 if (wd->eval)
158 {
159 _eval(obj);
160 wd->eval = EINA_FALSE;
161 }
162 if (wd->szeval)
163 {
164 _sizing_eval(obj);
165 wd->szeval = EINA_FALSE;
166 }
167}
168
169static void
170_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
171{
172 Widget_Data *wd = elm_widget_data_get(obj);
173 if (!wd) return;
174 wd->eval = EINA_TRUE;
175 evas_object_smart_changed(obj);
176}
177
178static void
179_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
180{
181 Widget_Data *wd = elm_widget_data_get(obj);
182 if (!wd) return;
183 wd->eval = EINA_TRUE;
184 evas_object_smart_changed(obj);
185}
186
187static void
188_child_change(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
189{
190 Widget_Data *wd = elm_widget_data_get(data);
191 if (!wd) return;
192 wd->eval = EINA_TRUE;
193 wd->szeval = EINA_TRUE;
194 evas_object_smart_changed(data);
195}
196
197static void
198_child_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
199{
200 Evas_Object *fobj = data;
201 Widget_Data *wd = elm_widget_data_get(fobj);
202 if (!wd) return;
203 if (wd->content != obj) return;
204 evas_object_event_callback_del_full(wd->content,
205 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
206 _child_change, obj);
207 evas_object_event_callback_del_full(wd->content,
208 EVAS_CALLBACK_DEL,
209 _child_del, obj);
210 wd->content = NULL;
211 fac--;
212// printf("FAC-- = %i\n", fac);
213}
214
215static Evas_Object *
216_content_unset_hook(Evas_Object *obj, const char *part)
217{
218 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
219 Widget_Data *wd;
220 Evas_Object *content;
221
222 if (part && strcmp(part, "default")) return NULL;
223 wd = elm_widget_data_get(obj);
224 if (!wd || !wd->content) return NULL;
225
226 content = wd->content;
227 evas_object_event_callback_del_full(content,
228 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
229 _child_change, obj);
230 evas_object_event_callback_del_full(content,
231 EVAS_CALLBACK_DEL,
232 _child_del, obj);
233 wd->content = NULL;
234 fac--;
235// printf("FAC-- = %i\n", fac);
236 return content;
237}
238
239static void
240_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
241{
242 ELM_CHECK_WIDTYPE(obj, widtype);
243 Widget_Data *wd;
244 Evas_Object *prev_content;
245
246 if (part && strcmp(part, "default")) return;
247 wd = elm_widget_data_get(obj);
248 if (!wd) return;
249 if (wd->content == content) return;
250
251 prev_content = _content_unset_hook(obj, part);
252 if (prev_content) evas_object_del(prev_content);
253
254 wd->content = content;
255 if (!content) return;
256
257 elm_widget_resize_object_set(obj, content);
258 evas_object_event_callback_add(content, EVAS_CALLBACK_DEL, _child_del, obj);
259 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
260 _child_change, obj);
261 wd->eval = EINA_TRUE;
262 wd->szeval = EINA_TRUE;
263 evas_object_smart_changed(obj);
264 fac++;
265}
266
267static Evas_Object *
268_content_get_hook(const Evas_Object *obj, const char *part)
269{
270 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
271 Widget_Data *wd;
272 if (part && strcmp(part, "default")) return NULL;
273 wd = elm_widget_data_get(obj);
274 if (!wd) return NULL;
275 return wd->content;
276}
277
278EAPI Evas_Object *
279elm_factory_add(Evas_Object *parent)
280{
281 Evas_Object *obj;
282 Evas *e;
283 Widget_Data *wd;
284
285 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
286
287 ELM_SET_WIDTYPE(widtype, "factory");
288 elm_widget_type_set(obj, "factory");
289 elm_widget_sub_object_add(parent, obj);
290 elm_widget_data_set(obj, wd);
291 elm_widget_del_hook_set(obj, _del_hook);
292 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
293 elm_widget_content_set_hook_set(obj, _content_set_hook);
294 elm_widget_content_get_hook_set(obj, _content_get_hook);
295 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
296 elm_widget_can_focus_set(obj, EINA_FALSE);
297 elm_widget_changed_hook_set(obj, _changed);
298
299 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL);
300 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
301
302 evas_object_smart_callbacks_descriptions_set(obj, _signals);
303
304 wd->obj = obj;
305 wd->last_calc_count = -1;
306 return obj;
307}
308
309EAPI void
310elm_factory_maxmin_mode_set(Evas_Object *obj, Eina_Bool enabled)
311{
312 ELM_CHECK_WIDTYPE(obj, widtype);
313 Widget_Data *wd = elm_widget_data_get(obj);
314 if (!wd) return;
315 wd->maxmin = !!enabled;
316}
317
318EAPI Eina_Bool
319elm_factory_maxmin_mode_get(const Evas_Object *obj)
320{
321 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
322 Widget_Data *wd = elm_widget_data_get(obj);
323 if (!wd) return EINA_FALSE;
324 return wd->maxmin;
325}
326
327EAPI void
328elm_factory_maxmin_reset_set(Evas_Object *obj)
329{
330 ELM_CHECK_WIDTYPE(obj, widtype);
331 Widget_Data *wd = elm_widget_data_get(obj);
332 if (!wd) return;
333 wd->maxminw = 0;
334 wd->maxminh = 0;
335 wd->eval = EINA_TRUE;
336 wd->szeval = EINA_TRUE;
337 evas_object_smart_changed(obj);
338}
diff --git a/libraries/elementary/src/lib/elm_factory.h b/libraries/elementary/src/lib/elm_factory.h
new file mode 100644
index 0000000..a81ba5e
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_factory.h
@@ -0,0 +1,6 @@
1/* this api is currently disabled due to being incomplete. you cannot
2 * use it as it is not compiled in */
3EAPI Evas_Object *elm_factory_add(Evas_Object *parent);
4EAPI void elm_factory_maxmin_mode_set(Evas_Object *obj, Eina_Bool enabled);
5EAPI Eina_Bool elm_factory_maxmin_mode_get(const Evas_Object *obj);
6EAPI void elm_factory_maxmin_reset_set(Evas_Object *obj);
diff --git a/libraries/elementary/src/lib/elm_finger.h b/libraries/elementary/src/lib/elm_finger.h
new file mode 100644
index 0000000..cfe5d2e
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_finger.h
@@ -0,0 +1,45 @@
1/**
2 * @defgroup Fingers Fingers
3 * @ingroup Elementary
4 *
5 * Elementary is designed to be finger-friendly for touchscreens,
6 * and so in addition to scaling for display resolution, it can
7 * also scale based on finger "resolution" (or size). You can then
8 * customize the granularity of the areas meant to receive clicks
9 * on touchscreens.
10 *
11 * Different profiles may have pre-set values for finger sizes.
12 *
13 * @ref general_functions_example_page "This" example contemplates
14 * some of these functions.
15 *
16 * @{
17 */
18
19/**
20 * Adjust size of an element for finger usage.
21 *
22 * @param times_w How many fingers should fit horizontally
23 * @param w Pointer to the width size to adjust
24 * @param times_h How many fingers should fit vertically
25 * @param h Pointer to the height size to adjust
26 *
27 * This takes width and height sizes (in pixels) as input and a
28 * size multiple (which is how many fingers you want to place
29 * within the area, being "finger" the size set by
30 * elm_finger_size_set()), and adjusts the size to be large enough
31 * to accommodate the resulting size -- if it doesn't already
32 * accommodate it. On return the @p w and @p h sizes pointed to by
33 * these parameters will be modified, on those conditions.
34 *
35 * @note This is kind of low level Elementary call, most useful
36 * on size evaluation times for widgets. An external user wouldn't
37 * be calling, most of the time.
38 *
39 * @ingroup Fingers
40 */
41EAPI void elm_coords_finger_size_adjust(int times_w, Evas_Coord *w, int times_h, Evas_Coord *h);
42
43/**
44 * @}
45 */
diff --git a/libraries/elementary/src/lib/elm_flip.c b/libraries/elementary/src/lib/elm_flip.c
new file mode 100644
index 0000000..d02acdd
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_flip.c
@@ -0,0 +1,1941 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Slice Slice;
6typedef struct _Vertex2 Vertex2;
7typedef struct _Vertex3 Vertex3;
8
9struct _Slice
10{
11 Evas_Object *obj;
12 double u[4], v[4], x[4], y[4], z[4];
13};
14
15struct _Vertex2
16{
17 double x, y;
18};
19
20struct _Vertex3
21{
22 double x, y, z;
23};
24
25struct _Widget_Data
26{
27 Evas_Object *obj;
28 Ecore_Animator *animator;
29 double start, len;
30 Elm_Flip_Mode mode;
31 Evas_Object *clip;
32 Evas_Object *event[4];
33 struct
34 {
35 Evas_Object *content, *clip;
36 } front, back;
37 Ecore_Job *job;
38 Evas_Coord down_x, down_y, x, y, ox, oy, w, h;
39 Elm_Flip_Interaction intmode;
40 int dir;
41 double dir_hitsize[4];
42 Eina_Bool dir_enabled[4];
43 int slices_w, slices_h;
44 Slice **slices, **slices2;
45
46 Eina_Bool state : 1;
47 Eina_Bool down : 1;
48 Eina_Bool finish : 1;
49 Eina_Bool started : 1;
50 Eina_Bool backflip : 1;
51 Eina_Bool pageflip : 1;
52};
53
54static const char *widtype = NULL;
55static void _del_hook(Evas_Object *obj);
56static void _theme_hook(Evas_Object *obj);
57static void _sizing_eval(Evas_Object *obj);
58static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
59static void _sub_del(void *data, Evas_Object *obj, void *event_info);
60
61static void _state_slices_clear(Widget_Data *wd);
62static void _configure(Evas_Object *obj);
63
64static const char SIG_ANIMATE_BEGIN[] = "animate,begin";
65static const char SIG_ANIMATE_DONE[] = "animate,done";
66
67static const Evas_Smart_Cb_Description _signals[] = {
68 {SIG_ANIMATE_BEGIN, ""},
69 {SIG_ANIMATE_DONE, ""},
70 {NULL, NULL}
71};
72
73static void
74_del_hook(Evas_Object *obj)
75{
76 Widget_Data *wd = elm_widget_data_get(obj);
77 if (!wd) return;
78 if (wd->animator) ecore_animator_del(wd->animator);
79 _state_slices_clear(wd);
80 free(wd);
81}
82
83static void
84_theme_hook(Evas_Object *obj)
85{
86 Widget_Data *wd = elm_widget_data_get(obj);
87 if (!wd) return;
88 _sizing_eval(obj);
89}
90
91static Eina_Bool
92_elm_flip_focus_next_hook(const Evas_Object *obj,
93 Elm_Focus_Direction dir, Evas_Object **next)
94{
95 Widget_Data *wd = elm_widget_data_get(obj);
96 if (!wd) return EINA_FALSE;
97
98 /* Try Focus cycle in subitem */
99 if (wd->state)
100 return elm_widget_focus_next_get(wd->front.content, dir, next);
101 else
102 return elm_widget_focus_next_get(wd->back.content, dir, next);
103}
104
105static void
106_sizing_eval(Evas_Object *obj)
107{
108 Widget_Data *wd = elm_widget_data_get(obj);
109 Evas_Coord minw = -1, minh = -1, minw2 = -1, minh2 = -1;
110 Evas_Coord maxw = -1, maxh = -1, maxw2 = -1, maxh2 = -1;
111 int fingx = 0, fingy = 0;
112 if (!wd) return;
113 if (wd->front.content)
114 evas_object_size_hint_min_get(wd->front.content, &minw, &minh);
115 if (wd->back.content)
116 evas_object_size_hint_min_get(wd->back.content, &minw2, &minh2);
117 if (wd->front.content)
118 evas_object_size_hint_max_get(wd->front.content, &maxw, &maxh);
119 if (wd->back.content)
120 evas_object_size_hint_max_get(wd->back.content, &maxw2, &maxh2);
121
122 if (minw2 > minw) minw = minw2;
123 if (minh2 > minh) minh = minh2;
124 if ((maxw2 >= 0) && (maxw2 < maxw)) maxw = maxw2;
125 if ((maxh2 >= 0) && (maxh2 < maxh)) maxh = maxh2;
126
127 if (wd->dir_enabled[0]) fingy++;
128 if (wd->dir_enabled[1]) fingy++;
129 if (wd->dir_enabled[2]) fingx++;
130 if (wd->dir_enabled[3]) fingx++;
131
132 elm_coords_finger_size_adjust(fingx, &minw, fingy, &minh);
133
134 evas_object_size_hint_min_set(obj, minw, minh);
135 evas_object_size_hint_max_set(obj, maxw, maxh);
136}
137
138static void
139_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
140{
141 Widget_Data *wd = elm_widget_data_get(data);
142 if (!wd) return;
143 _sizing_eval(data);
144}
145
146static void
147_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
148{
149 Widget_Data *wd = elm_widget_data_get(obj);
150 Evas_Object *sub = event_info;
151 if (!wd) return;
152 if (sub == wd->front.content)
153 {
154 evas_object_event_callback_del_full(sub,
155 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
156 _changed_size_hints, obj);
157 wd->front.content = NULL;
158 evas_object_hide(wd->front.clip);
159 _sizing_eval(obj);
160 }
161 else if (sub == wd->back.content)
162 {
163 evas_object_event_callback_del_full(sub,
164 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
165 _changed_size_hints, obj);
166 wd->back.content = NULL;
167 evas_object_hide(wd->back.clip);
168 _sizing_eval(obj);
169 }
170}
171
172static Slice *
173_slice_new(Widget_Data *wd, Evas_Object *obj)
174{
175 Slice *sl;
176
177 sl = calloc(1, sizeof(Slice));
178 if (!sl) return NULL;
179 sl->obj = evas_object_image_add(evas_object_evas_get(obj));
180 elm_widget_sub_object_add(wd->obj, sl->obj);
181 evas_object_smart_member_add(sl->obj, wd->obj);
182 evas_object_image_smooth_scale_set(sl->obj, EINA_FALSE);
183 evas_object_pass_events_set(sl->obj, EINA_TRUE);
184 evas_object_image_source_set(sl->obj, obj);
185 return sl;
186}
187
188static void
189_slice_free(Slice *sl)
190{
191 evas_object_del(sl->obj);
192 free(sl);
193}
194
195static void
196_slice_apply(Widget_Data *wd, Slice *sl, Evas_Coord x __UNUSED__,
197 Evas_Coord y __UNUSED__, Evas_Coord w, Evas_Coord h __UNUSED__,
198 Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
199{
200 Evas_Map *m;
201 int i;
202
203 m = evas_map_new(4);
204 if (!m) return;
205 evas_map_smooth_set(m, EINA_FALSE);
206 for (i = 0; i < 4; i++)
207 {
208 evas_map_point_color_set(m, i, 255, 255, 255, 255);
209 if (wd->dir == 0)
210 {
211 int p[4] = { 0, 1, 2, 3 };
212 evas_map_point_coord_set(m, i, ox + sl->x[p[i]], oy + sl->y[p[i]],
213 sl->z[p[i]]);
214 evas_map_point_image_uv_set(m, i, sl->u[p[i]] , sl->v[p[i]]);
215 }
216 else if (wd->dir == 1)
217 {
218 int p[4] = { 1, 0, 3, 2 };
219 evas_map_point_coord_set(m, i, ox + (w - sl->x[p[i]]),
220 oy + sl->y[p[i]], sl->z[p[i]]);
221 evas_map_point_image_uv_set(m, i, ow - sl->u[p[i]], sl->v[p[i]]);
222 }
223 else if (wd->dir == 2)
224 {
225 int p[4] = { 1, 0, 3, 2 };
226 evas_map_point_coord_set(m, i, ox + sl->y[p[i]], oy + sl->x[p[i]],
227 sl->z[p[i]]);
228 evas_map_point_image_uv_set(m, i, sl->v[p[i]] , sl->u[p[i]]);
229 }
230 else/* if (wd->dir == 3) will be this anyway */
231 {
232 int p[4] = { 0, 1, 2, 3 };
233 evas_map_point_coord_set(m, i, ox + sl->y[p[i]],
234 oy + (w - sl->x[p[i]]), sl->z[p[i]]);
235 evas_map_point_image_uv_set(m, i, sl->v[p[i]] , oh - sl->u[p[i]]);
236 }
237 }
238 evas_object_map_enable_set(sl->obj, EINA_TRUE);
239 evas_object_image_fill_set(sl->obj, 0, 0, ow, oh);
240 evas_object_map_set(sl->obj, m);
241 evas_map_free(m);
242}
243
244static void
245_slice_3d(Widget_Data *wd __UNUSED__, Slice *sl, Evas_Coord x, Evas_Coord y,
246 Evas_Coord w, Evas_Coord h)
247{
248 Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
249 int i;
250
251 if (!m) return;
252 // vanishing point is center of page, and focal dist is 1024
253 evas_map_util_3d_perspective(m, x + (w / 2), y + (h / 2), 0, 1024);
254 for (i = 0; i < 4; i++)
255 {
256 Evas_Coord xx, yy, zz;
257 evas_map_point_coord_get(m, i, &xx, &yy, &zz);
258 evas_map_point_coord_set(m, i, xx, yy, 0);
259 }
260 if (evas_map_util_clockwise_get(m)) evas_object_show(sl->obj);
261 else evas_object_hide(sl->obj);
262 evas_object_map_set(sl->obj, m);
263}
264
265static void
266_slice_light(Widget_Data *wd __UNUSED__, Slice *sl, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
267{
268 Evas_Map *m = (Evas_Map *)evas_object_map_get(sl->obj);
269 int i;
270
271 if (!m) return;
272 evas_map_util_3d_lighting(m,
273 // light position
274 // (centered over page 10 * h toward camera)
275 x + (w / 2) , y + (h / 2) , -10000,
276 255, 255, 255, // light color
277 0 , 0 , 0); // ambient minimum
278 // multiply brightness by 1.2 to make lightish bits all white so we dont
279 // add shading where we could otherwise be pure white
280 for (i = 0; i < 4; i++)
281 {
282 int r, g, b, a;
283
284 evas_map_point_color_get(m, i, &r, &g, &b, &a);
285 r = (double)r * 1.2; if (r > 255) r = 255;
286 g = (double)g * 1.2; if (g > 255) g = 255;
287 b = (double)b * 1.2; if (b > 255) b = 255;
288 evas_map_point_color_set(m, i, r, g, b, a);
289 }
290 evas_object_map_set(sl->obj, m);
291}
292
293static void
294_slice_xyz(Widget_Data *wd __UNUSED__, Slice *sl,
295 double xx1, double yy1, double zz1,
296 double xx2, double yy2, double zz2,
297 double xx3, double yy3, double zz3,
298 double xx4, double yy4, double zz4)
299{
300 sl->x[0] = xx1; sl->y[0] = yy1; sl->z[0] = zz1;
301 sl->x[1] = xx2; sl->y[1] = yy2; sl->z[1] = zz2;
302 sl->x[2] = xx3; sl->y[2] = yy3; sl->z[2] = zz3;
303 sl->x[3] = xx4; sl->y[3] = yy4; sl->z[3] = zz4;
304}
305
306static void
307_slice_uv(Widget_Data *wd __UNUSED__, Slice *sl,
308 double u1, double v1,
309 double u2, double v2,
310 double u3, double v3,
311 double u4, double v4)
312{
313 sl->u[0] = u1; sl->v[0] = v1;
314 sl->u[1] = u2; sl->v[1] = v2;
315 sl->u[2] = u3; sl->v[2] = v3;
316 sl->u[3] = u4; sl->v[3] = v4;
317}
318
319static void
320_deform_point(Vertex2 *vi, Vertex3 *vo, double rho, double theta, double A)
321{
322 // ^Y
323 // |
324 // | X
325 // +---->
326 // theta == cone angle (0 -> PI/2)
327 // A == distance of cone apex from origin
328 // rho == angle of cone from vertical axis (...-PI/2 to PI/2...)
329 Vertex3 v1;
330 double d, r, b;
331
332 d = sqrt((vi->x * vi->x) + pow(vi->y - A, 2));
333 r = d * sin(theta);
334 b = asin(vi->x / d) / sin(theta);
335
336 v1.x = r * sin(b);
337 v1.y = d + A - (r * (1 - cos(b)) * sin(theta));
338 v1.z = r * (1 - cos(b)) * cos(theta);
339
340 vo->x = (v1.x * cos(rho)) - (v1.z * sin(rho));
341 vo->y = v1.y;
342 vo->z = (v1.x * sin(rho)) + (v1.z * cos(rho));
343}
344
345static void
346_interp_point(Vertex3 *vi1, Vertex3 *vi2, Vertex3 *vo, double v)
347{
348 vo->x = (v * vi2->x) + ((1.0 - v) * vi1->x);
349 vo->y = (v * vi2->y) + ((1.0 - v) * vi1->y);
350 vo->z = (v * vi2->z) + ((1.0 - v) * vi1->z);
351}
352
353static void
354_state_slices_clear(Widget_Data *wd)
355{
356 int i, j, num;
357
358 if (wd->slices)
359 {
360 num = 0;
361 for (j = 0; j < wd->slices_h; j++)
362 {
363 for (i = 0; i < wd->slices_w; i++)
364 {
365 if (wd->slices[num]) _slice_free(wd->slices[num]);
366 if (wd->slices2[num]) _slice_free(wd->slices2[num]);
367 num++;
368 }
369 }
370 free(wd->slices);
371 free(wd->slices2);
372 wd->slices = NULL;
373 wd->slices2 = NULL;
374 }
375 wd->slices_w = 0;
376 wd->slices_h = 0;
377}
378
379static int
380_slice_obj_color_sum(Slice *s, int p, int *r, int *g, int *b, int *a)
381{
382 Evas_Map *m;
383 int rr = 0, gg = 0, bb = 0, aa = 0;
384
385 if (!s) return 0;
386 m = (Evas_Map *)evas_object_map_get(s->obj);
387 if (!m) return 0;
388 evas_map_point_color_get(m, p, &rr, &gg, &bb, &aa);
389 *r += rr; *g += gg; *b += bb; *a += aa;
390 return 1;
391}
392
393static void
394_slice_obj_color_set(Slice *s, int p, int r, int g, int b, int a)
395{
396 Evas_Map *m;
397
398 if (!s) return;
399 m = (Evas_Map *) evas_object_map_get(s->obj);
400 if (!m) return;
401 evas_map_point_color_set(m, p, r, g, b, a);
402 evas_object_map_set(s->obj, m);
403}
404
405static void
406_slice_obj_vert_color_merge(Slice *s1, int p1, Slice *s2, int p2,
407 Slice *s3, int p3, Slice *s4, int p4)
408{
409 int r = 0, g = 0, b = 0, a = 0, n = 0;
410
411 n += _slice_obj_color_sum(s1, p1, &r, &g, &b, &a);
412 n += _slice_obj_color_sum(s2, p2, &r, &g, &b, &a);
413 n += _slice_obj_color_sum(s3, p3, &r, &g, &b, &a);
414 n += _slice_obj_color_sum(s4, p4, &r, &g, &b, &a);
415
416 if (n < 1) return;
417 r /= n; g /= n; b /= n; a /= n;
418
419 _slice_obj_color_set(s1, p1, r, g, b, a);
420 _slice_obj_color_set(s2, p2, r, g, b, a);
421 _slice_obj_color_set(s3, p3, r, g, b, a);
422 _slice_obj_color_set(s4, p4, r, g, b, a);
423}
424
425static int
426_state_update(Widget_Data *wd)
427{
428 Evas_Coord xx1, yy1, xx2, yy2, mx, my;
429 Evas_Coord x, y, w, h, ox, oy, ow, oh;
430 int i, j, num, nn, jump, num2;
431 Slice *sl;
432 double b, minv = 0.0, minva, mgrad;
433 int gx, gy, gszw, gszh, gw, gh, col, row, nw, nh;
434 double rho, A, theta, perc, percm, n, rhol, Al, thetal;
435 Vertex3 *tvo, *tvol;
436 Evas_Object *front, *back;
437
438 wd->backflip = EINA_TRUE;
439 if (wd->state)
440 {
441 front = wd->front.content;
442 back = wd->front.content;
443 }
444 else
445 {
446 front = wd->back.content;
447 back = wd->back.content;
448 }
449
450 evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
451 ox = x; oy = y; ow = w; oh = h;
452 xx1 = wd->down_x;
453 yy1 = wd->down_y;
454 xx2 = wd->x;
455 yy2 = wd->y;
456
457 if (wd->dir == 0)
458 {
459 // no nothing. left drag is standard
460 }
461 else if (wd->dir == 1)
462 {
463 xx1 = (w - 1) - xx1;
464 xx2 = (w - 1) - xx2;
465 }
466 else if (wd->dir == 2)
467 {
468 Evas_Coord tmp;
469
470 tmp = xx1; xx1 = yy1; yy1 = tmp;
471 tmp = xx2; xx2 = yy2; yy2 = tmp;
472 tmp = w; w = h; h = tmp;
473 }
474 else/* if (wd->dir == 3) will be this anyway */
475 {
476 Evas_Coord tmp;
477
478 tmp = xx1; xx1 = yy1; yy1 = tmp;
479 tmp = xx2; xx2 = yy2; yy2 = tmp;
480 tmp = w; w = h; h = tmp;
481 xx1 = (w - 1) - xx1;
482 xx2 = (w - 1) - xx2;
483 }
484
485 if (xx2 >= xx1) xx2 = xx1 - 1;
486 mx = (xx1 + xx2) / 2;
487 my = (yy1 + yy2) / 2;
488
489 if (mx < 0) mx = 0;
490 else if (mx >= w) mx = w - 1;
491 if (my < 0) my = 0;
492 else if (my >= h) my = h - 1;
493
494 mgrad = (double)(yy1 - yy2) / (double)(xx1 - xx2);
495
496 if (mx < 1) mx = 1; // quick hack to keep curl line visible
497
498 if (mgrad == 0.0) // special horizontal case
499 mgrad = 0.001; // quick dirty hack for now
500 // else
501 {
502 minv = 1.0 / mgrad;
503 // y = (m * x) + b
504 b = my + (minv * mx);
505 }
506 if ((b >= -5) && (b <= (h + 5)))
507 {
508 if (minv > 0.0) // clamp to h
509 {
510 minv = (double)(h + 5 - my) / (double)(mx);
511 b = my + (minv * mx);
512 }
513 else // clamp to 0
514 {
515 minv = (double)(-5 - my) / (double)(mx);
516 b = my + (minv * mx);
517 }
518 }
519
520 perc = (double)xx2 / (double)xx1;
521 percm = (double)mx / (double)xx1;
522 if (perc < 0.0) perc = 0.0;
523 else if (perc > 1.0) perc = 1.0;
524 if (percm < 0.0) percm = 0.0;
525 else if (percm > 1.0) percm = 1.0;
526
527 minva = atan(minv) / (M_PI / 2);
528 if (minva < 0.0) minva = -minva;
529
530 // A = apex of cone
531 if (b <= 0) A = b;
532 else A = h - b;
533 if (A < -(h * 20)) A = -h * 20;
534 //--//
535 Al = -5;
536
537 // rho = is how much the page is turned
538 n = 1.0 - perc;
539 n = 1.0 - cos(n * M_PI / 2.0);
540 n = n * n;
541 rho = -(n * M_PI);
542 //--//
543 rhol = -(n * M_PI);
544
545 // theta == curliness (how much page culrs in on itself
546 n = sin((1.0 - perc) * M_PI);
547 n = n * 1.2;
548 theta = 7.86 + n;
549 //--//
550 n = sin((1.0 - perc) * M_PI);
551 n = 1.0 - n;
552 n = n * n;
553 n = 1.0 - n;
554 thetal = 7.86 + n;
555
556 nw = 16;
557 nh = 16;
558 gszw = w / nw;
559 gszh = h / nh;
560 if (gszw < 4) gszw = 4;
561 if (gszh < 4) gszh = 4;
562
563 nw = (w + gszw - 1) / gszw;
564 nh = (h + gszh - 1) / gszh;
565 if ((wd->slices_w != nw) || (wd->slices_h != nh)) _state_slices_clear(wd);
566 wd->slices_w = nw;
567 wd->slices_h = nh;
568 if (!wd->slices)
569 {
570 wd->slices = calloc(wd->slices_w * wd->slices_h, sizeof(Slice *));
571 if (!wd->slices) return 0;
572 wd->slices2 = calloc(wd->slices_w * wd->slices_h, sizeof(Slice *));
573 if (!wd->slices2)
574 {
575 free(wd->slices);
576 wd->slices = NULL;
577 return 0;
578 }
579 }
580
581 num = (wd->slices_w + 1) * (wd->slices_h + 1);
582
583 tvo = alloca(sizeof(Vertex3) * num);
584 tvol = alloca(sizeof(Vertex3) * (wd->slices_w + 1));
585
586 for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
587 {
588 Vertex2 vil;
589
590 vil.x = gx;
591 vil.y = h - ((gx * h) / (w + gszw - 1));
592 _deform_point(&vil, &(tvol[col]), rhol, thetal, Al);
593 }
594
595 n = minva * sin(perc * M_PI);
596 n = n * n;
597
598 num = 0;
599 for (col = 0, gx = 0; gx <= (w + gszw - 1); gx += gszw, col++)
600 {
601 for (gy = 0; gy <= (h + gszh - 1); gy += gszh)
602 {
603 Vertex2 vi;
604 Vertex3 vo, tvo1;
605
606 if (gx > w) vi.x = w;
607 else vi.x = gx;
608 if (gy > h) vi.y = h;
609 else vi.y = gy;
610 _deform_point(&vi, &vo, rho, theta, A);
611 tvo1 = tvol[col];
612 if (gy > h) tvo1.y = h;
613 else tvo1.y = gy;
614 _interp_point(&vo, &tvo1, &(tvo[num]), n);
615 num++;
616 }
617 }
618
619 jump = wd->slices_h + 1;
620 for (col = 0, gx = 0; gx < w; gx += gszw, col++)
621 {
622 num = wd->slices_h * col;
623 num2 = jump * col;
624
625 gw = gszw;
626 if ((gx + gw) > w) gw = w - gx;
627
628 for (row = 0, gy = 0; gy < h; gy += gszh, row++)
629 {
630 Vertex3 vo[4];
631
632 if (b > 0) nn = num + wd->slices_h - row - 1;
633 else nn = num + row;
634
635 gh = gszh;
636 if ((gy + gh) > h) gh = h - gy;
637
638 vo[0] = tvo[num2 + row];
639 vo[1] = tvo[num2 + row + jump];
640 vo[2] = tvo[num2 + row + jump + 1];
641 vo[3] = tvo[num2 + row + 1];
642#define SWP(a, b) do {typeof(a) vt; vt = (a); (a) = (b); (b) = vt;} while (0)
643 if (b > 0)
644 {
645 SWP(vo[0], vo[3]);
646 SWP(vo[1], vo[2]);
647 vo[0].y = h - vo[0].y;
648 vo[1].y = h - vo[1].y;
649 vo[2].y = h - vo[2].y;
650 vo[3].y = h - vo[3].y;
651 }
652
653 // FRONT
654 sl = wd->slices[nn];
655 if (!sl)
656 {
657 sl = _slice_new(wd, front);
658 wd->slices[nn] = sl;
659 }
660 _slice_xyz(wd, sl,
661 vo[0].x, vo[0].y, vo[0].z,
662 vo[1].x, vo[1].y, vo[1].z,
663 vo[2].x, vo[2].y, vo[2].z,
664 vo[3].x, vo[3].y, vo[3].z);
665 if (b <= 0)
666 _slice_uv(wd, sl,
667 gx, gy, gx + gw, gy, gx + gw, gy + gh, gx, gy + gh);
668 else
669 _slice_uv(wd, sl,
670 gx, h - (gy + gh), gx + gw, h - (gy + gh), gx + gw,
671 h - gy, gx, h - gy);
672
673 // BACK
674 sl = wd->slices2[nn];
675 if (!sl)
676 {
677 sl = _slice_new(wd, back);
678 wd->slices2[nn] = sl;
679 }
680
681 _slice_xyz(wd, sl,
682 vo[1].x, vo[1].y, vo[1].z,
683 vo[0].x, vo[0].y, vo[0].z,
684 vo[3].x, vo[3].y, vo[3].z,
685 vo[2].x, vo[2].y, vo[2].z);
686 if (wd->backflip)
687 {
688 if (b <= 0)
689 _slice_uv(wd, sl, gx + gw, gy, gx, gy, gx, gy + gh, gx + gw,
690 gy + gh);
691 else
692 _slice_uv(wd, sl, gx + gw, h - (gy + gh), gx, h - (gy + gh),
693 gx, h - gy, gx + gw, h - gy);
694 }
695 else
696 {
697 if (b <= 0)
698 _slice_uv(wd, sl, w - (gx + gw), gy, w - (gx), gy, w - (gx),
699 gy + gh, w - (gx + gw), gy + gh);
700 else
701 _slice_uv(wd, sl, w - (gx + gw), h - (gy + gh), w - (gx),
702 h - (gy + gh), w - (gx), h - gy, w - (gx + gw),
703 h - gy);
704 }
705 }
706 }
707
708 for (num = 0; num < wd->slices_h * wd->slices_w; num++)
709 {
710 _slice_apply(wd, wd->slices[num], x, y, w, h, ox, oy, ow, oh);
711 _slice_apply(wd, wd->slices2[num], x, y, w, h, ox, oy, ow, oh);
712 _slice_light(wd, wd->slices[num], ox, oy, ow, oh);
713 _slice_light(wd, wd->slices2[num], ox, oy, ow, oh);
714 }
715
716 for (i = 0; i <= wd->slices_w; i++)
717 {
718 num = i * wd->slices_h;
719 for (j = 0; j <= wd->slices_h; j++)
720 {
721 Slice *s[4] = { NULL }, *s2[4] = { NULL };
722
723 if ((i > 0) && (j > 0))
724 s[0] = wd->slices[num - 1 - wd->slices_h],
725 s2[0] = wd->slices2[num - 1 - wd->slices_h];
726 if ((i < wd->slices_w) && (j > 0))
727 s[1] = wd->slices[num - 1],
728 s2[1] = wd->slices2[num - 1];
729 if ((i > 0) && (j < wd->slices_h))
730 s[2] = wd->slices[num - wd->slices_h],
731 s2[2] = wd->slices2[num - wd->slices_h];
732 if ((i < wd->slices_w) && (j < wd->slices_h))
733 s[3] = wd->slices[num],
734 s2[3] = wd->slices2[num];
735 switch (wd->dir)
736 {
737 case 0:
738 _slice_obj_vert_color_merge(s[0], 2, s[1], 3, s[2], 1, s[3], 0);
739 _slice_obj_vert_color_merge(s2[0], 3, s2[1], 2, s2[2], 0, s2[3], 1);
740 break;
741 case 1:
742 _slice_obj_vert_color_merge(s[0], 3, s[1], 2, s[2], 0, s[3], 1);
743 _slice_obj_vert_color_merge(s2[0], 2, s2[1], 3, s2[2], 1, s2[3], 0);
744 break;
745 case 2:
746 _slice_obj_vert_color_merge(s[0], 3, s[1], 2, s[2], 0, s[3], 1);
747 _slice_obj_vert_color_merge(s2[0], 2, s2[1], 3, s2[2], 1, s2[3], 0);
748 break;
749 default:
750 _slice_obj_vert_color_merge(s[0], 2, s[1], 3, s[2], 1, s[3], 0);
751 _slice_obj_vert_color_merge(s2[0], 3, s2[1], 2, s2[2], 0, s2[3], 1);
752 }
753 num++;
754 }
755 }
756
757 for (num = 0; num < wd->slices_h * wd->slices_w; num++)
758 {
759 _slice_3d(wd, wd->slices[num], ox, oy, ow, oh);
760 _slice_3d(wd, wd->slices2[num], ox, oy, ow, oh);
761 }
762
763 return 1;
764}
765
766static void
767_state_end(Widget_Data *wd)
768{
769 _state_slices_clear(wd);
770}
771
772
773static void
774flip_show_hide(Evas_Object *obj)
775{
776 Widget_Data *wd = elm_widget_data_get(obj);
777 if (elm_flip_front_visible_get(obj))
778 {
779 if (wd->pageflip)
780 {
781 if (wd->front.content)
782 {
783 evas_object_move(wd->front.content, 4999, 4999);
784 evas_object_show(wd->front.clip);
785 }
786 else
787 evas_object_hide(wd->front.clip);
788 if (wd->back.content)
789 evas_object_show(wd->back.clip);
790 else
791 evas_object_hide(wd->back.clip);
792 }
793 else
794 {
795 if (wd->front.content)
796 evas_object_show(wd->front.clip);
797 else
798 evas_object_hide(wd->front.clip);
799 evas_object_hide(wd->back.clip);
800 }
801 }
802 else
803 {
804 if (wd->pageflip)
805 {
806 if (wd->front.content)
807 evas_object_show(wd->front.clip);
808 else
809 evas_object_hide(wd->front.clip);
810 if (wd->back.content)
811 {
812 evas_object_move(wd->back.content, 4999, 4999);
813 evas_object_show(wd->back.clip);
814 }
815 else
816 evas_object_hide(wd->back.clip);
817 }
818 else
819 {
820 if (wd->front.content)
821 evas_object_hide(wd->front.clip);
822 else
823 evas_object_hide(wd->front.clip);
824 if (wd->back.content)
825 evas_object_show(wd->back.clip);
826 else
827 evas_object_hide(wd->back.clip);
828 }
829 }
830}
831
832static void
833_flip_do(Evas_Object *obj, double t, Elm_Flip_Mode mode, int lin, int rev)
834{
835 Evas_Coord x, y, w, h;
836 double p, deg, pp;
837 Evas_Map *mf, *mb;
838 Evas_Coord cx, cy, px, py, foc;
839 int lx, ly, lz, lr, lg, lb, lar, lag, lab;
840 Widget_Data *wd = elm_widget_data_get(obj);
841
842 if (!wd) return;
843
844 mf = evas_map_new(4);
845 evas_map_smooth_set(mf, EINA_FALSE);
846 mb = evas_map_new(4);
847 evas_map_smooth_set(mb, EINA_FALSE);
848
849 if (wd->front.content)
850 {
851 const char *type = evas_object_type_get(wd->front.content);
852
853 // FIXME: only handles filled obj
854 if ((type) && (!strcmp(type, "image")))
855 {
856 int iw, ih;
857 evas_object_image_size_get(wd->front.content, &iw, &ih);
858 evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
859 evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
860 evas_map_point_image_uv_set(mf, 0, 0, 0);
861 evas_map_point_image_uv_set(mf, 1, iw, 0);
862 evas_map_point_image_uv_set(mf, 2, iw, ih);
863 evas_map_point_image_uv_set(mf, 3, 0, ih);
864 }
865 else
866 {
867 evas_object_geometry_get(wd->front.content, &x, &y, &w, &h);
868 evas_map_util_points_populate_from_geometry(mf, x, y, w, h, 0);
869 }
870 }
871 if (wd->back.content)
872 {
873 const char *type = evas_object_type_get(wd->back.content);
874
875 if ((type) && (!strcmp(type, "image")))
876 {
877 int iw, ih;
878 evas_object_image_size_get(wd->back.content, &iw, &ih);
879 evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
880 evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
881 evas_map_point_image_uv_set(mb, 0, 0, 0);
882 evas_map_point_image_uv_set(mb, 1, iw, 0);
883 evas_map_point_image_uv_set(mb, 2, iw, ih);
884 evas_map_point_image_uv_set(mb, 3, 0, ih);
885 }
886 else
887 {
888 evas_object_geometry_get(wd->back.content, &x, &y, &w, &h);
889 evas_map_util_points_populate_from_geometry(mb, x, y, w, h, 0);
890 }
891 }
892
893 evas_object_geometry_get(obj, &x, &y, &w, &h);
894
895 cx = x + (w / 2);
896 cy = y + (h / 2);
897
898 px = x + (w / 2);
899 py = y + (h / 2);
900 foc = 2048;
901
902 lx = cx;
903 ly = cy;
904 lz = -10000;
905 lr = 255;
906 lg = 255;
907 lb = 255;
908 lar = 0;
909 lag = 0;
910 lab = 0;
911
912 switch (mode)
913 {
914 case ELM_FLIP_ROTATE_Y_CENTER_AXIS:
915 p = 1.0 - t;
916 pp = p;
917 if (!lin) pp = (p * p);
918 p = 1.0 - pp;
919 if (wd->state) deg = 180.0 * p;
920 else deg = 180 + (180.0 * p);
921 if (rev) deg = -deg;
922 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, 0);
923 evas_map_util_3d_rotate(mb, 0.0, 180 + deg, 0.0, cx, cy, 0);
924 break;
925 case ELM_FLIP_ROTATE_X_CENTER_AXIS:
926 p = 1.0 - t;
927 pp = p;
928 if (!lin) pp = (p * p);
929 p = 1.0 - pp;
930 if (wd->state) deg = 180.0 * p;
931 else deg = 180 + (180.0 * p);
932 if (rev) deg = -deg;
933 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, 0);
934 evas_map_util_3d_rotate(mb, 180.0 + deg, 0.0, 0.0, cx, cy, 0);
935 break;
936 case ELM_FLIP_ROTATE_XZ_CENTER_AXIS:
937 p = 1.0 - t;
938 pp = p;
939 if (!lin) pp = (p * p);
940 p = 1.0 - pp;
941 if (wd->state) deg = 180.0 * p;
942 else deg = 180 + (180.0 * p);
943 if (rev) deg = -deg;
944 evas_map_util_3d_rotate(mf, deg, 0.0, deg, cx, cy, 0);
945 evas_map_util_3d_rotate(mb, 180 + deg, 0.0, 180 + deg, cx, cy, 0);
946 break;
947 case ELM_FLIP_ROTATE_YZ_CENTER_AXIS:
948 p = 1.0 - t;
949 pp = p;
950 if (!lin) pp = (p * p);
951 p = 1.0 - pp;
952 if (wd->state) deg = 180.0 * p;
953 else deg = 180 + (180.0 * p);
954 if (rev) deg = -deg;
955 evas_map_util_3d_rotate(mf, 0.0, deg, deg, cx, cy, 0);
956 evas_map_util_3d_rotate(mb, 0.0, 180.0 + deg, 180.0 + deg, cx, cy, 0);
957 break;
958 case ELM_FLIP_CUBE_LEFT:
959 p = 1.0 - t;
960 pp = p;
961 if (!lin) pp = (p * p);
962 p = 1.0 - pp;
963 deg = -90.0 * p;
964 if (wd->state)
965 {
966 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
967 evas_map_util_3d_rotate(mb, 0.0, deg + 90, 0.0, cx, cy, w / 2);
968 }
969 else
970 {
971 evas_map_util_3d_rotate(mf, 0.0, deg + 90, 0.0, cx, cy, w / 2);
972 evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
973 }
974 break;
975 case ELM_FLIP_CUBE_RIGHT:
976 p = 1.0 - t;
977 pp = p;
978 if (!lin) pp = (p * p);
979 p = 1.0 - pp;
980 deg = 90.0 * p;
981 if (wd->state)
982 {
983 evas_map_util_3d_rotate(mf, 0.0, deg, 0.0, cx, cy, w / 2);
984 evas_map_util_3d_rotate(mb, 0.0, deg - 90, 0.0, cx, cy, w / 2);
985 }
986 else
987 {
988 evas_map_util_3d_rotate(mf, 0.0, deg - 90, 0.0, cx, cy, w / 2);
989 evas_map_util_3d_rotate(mb, 0.0, deg, 0.0, cx, cy, w / 2);
990 }
991 break;
992 case ELM_FLIP_CUBE_UP:
993 p = 1.0 - t;
994 pp = p;
995 if (!lin) pp = (p * p);
996 p = 1.0 - pp;
997 deg = -90.0 * p;
998 if (wd->state)
999 {
1000 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1001 evas_map_util_3d_rotate(mb, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1002 }
1003 else
1004 {
1005 evas_map_util_3d_rotate(mf, deg + 90, 0.0, 0.0, cx, cy, h / 2);
1006 evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1007 }
1008 break;
1009 case ELM_FLIP_CUBE_DOWN:
1010 p = 1.0 - t;
1011 pp = p;
1012 if (!lin) pp = (p * p);
1013 p = 1.0 - pp;
1014 deg = 90.0 * p;
1015 if (wd->state)
1016 {
1017 evas_map_util_3d_rotate(mf, deg, 0.0, 0.0, cx, cy, h / 2);
1018 evas_map_util_3d_rotate(mb, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1019 }
1020 else
1021 {
1022 evas_map_util_3d_rotate(mf, deg - 90, 0.0, 0.0, cx, cy, h / 2);
1023 evas_map_util_3d_rotate(mb, deg, 0.0, 0.0, cx, cy, h / 2);
1024 }
1025 break;
1026 case ELM_FLIP_PAGE_LEFT:
1027 break;
1028 case ELM_FLIP_PAGE_RIGHT:
1029 break;
1030 case ELM_FLIP_PAGE_UP:
1031 break;
1032 case ELM_FLIP_PAGE_DOWN:
1033 break;
1034 default:
1035 break;
1036 }
1037
1038
1039 if (wd->front.content)
1040 {
1041 evas_map_util_3d_lighting(mf, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1042 evas_map_util_3d_perspective(mf, px, py, 0, foc);
1043 evas_object_map_set(wd->front.content, mf);
1044 evas_object_map_enable_set(wd->front.content, 1);
1045 if (evas_map_util_clockwise_get(mf)) evas_object_show(wd->front.clip);
1046 else evas_object_hide(wd->front.clip);
1047 }
1048
1049 if (wd->back.content)
1050 {
1051 evas_map_util_3d_lighting(mb, lx, ly, lz, lr, lg, lb, lar, lag, lab);
1052 evas_map_util_3d_perspective(mb, px, py, 0, foc);
1053 evas_object_map_set(wd->back.content, mb);
1054 evas_object_map_enable_set(wd->back.content, 1);
1055 if (evas_map_util_clockwise_get(mb)) evas_object_show(wd->back.clip);
1056 else evas_object_hide(wd->back.clip);
1057 }
1058
1059 evas_map_free(mf);
1060 evas_map_free(mb);
1061}
1062
1063static void
1064_showhide(Evas_Object *obj)
1065{
1066 Widget_Data *wd = elm_widget_data_get(obj);
1067 Evas_Coord x, y, w, h;
1068 if (!wd) return;
1069
1070 evas_object_geometry_get(obj, &x, &y, &w, &h);
1071 if (wd->front.content)
1072 {
1073 if ((wd->pageflip) && (wd->state))
1074 {
1075 evas_object_move(wd->front.content, 4999, 4999);
1076 }
1077 else
1078 {
1079 if (!wd->animator)
1080 evas_object_move(wd->front.content, x, y);
1081 }
1082 evas_object_resize(wd->front.content, w, h);
1083 }
1084 if (wd->back.content)
1085 {
1086 if ((wd->pageflip) && (!wd->state))
1087 {
1088 evas_object_move(wd->back.content, 4999, 4999);
1089 }
1090 else
1091 {
1092 if (!wd->animator)
1093 evas_object_move(wd->back.content, x, y);
1094 }
1095 evas_object_resize(wd->back.content, w, h);
1096 }
1097
1098}
1099
1100static Eina_Bool
1101_flip(Evas_Object *obj)
1102{
1103 Widget_Data *wd = elm_widget_data_get(obj);
1104 double t = ecore_loop_time_get() - wd->start;
1105 Evas_Coord w, h;
1106
1107 if (!wd) return ECORE_CALLBACK_CANCEL;
1108 if (!wd->animator) return ECORE_CALLBACK_CANCEL;
1109
1110 t = t / wd->len;
1111 if (t > 1.0) t = 1.0;
1112
1113 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1114 if (wd->mode == ELM_FLIP_PAGE_LEFT)
1115 {
1116 wd->dir = 0;
1117 wd->started = EINA_TRUE;
1118 wd->pageflip = EINA_TRUE;
1119 wd->down_x = w - 1;
1120 wd->down_y = h / 2;
1121 wd->x = (1.0 - t) * wd->down_x;
1122 wd->y = wd->down_y;
1123 flip_show_hide(obj);
1124 _state_update(wd);
1125 }
1126 else if (wd->mode == ELM_FLIP_PAGE_RIGHT)
1127 {
1128 wd->dir = 1;
1129 wd->started = EINA_TRUE;
1130 wd->pageflip = EINA_TRUE;
1131 wd->down_x = 0;
1132 wd->down_y = h / 2;
1133 wd->x = (t) * w;
1134 wd->y = wd->down_y;
1135 flip_show_hide(obj);
1136 _state_update(wd);
1137 }
1138 else if (wd->mode == ELM_FLIP_PAGE_UP)
1139 {
1140 wd->dir = 2;
1141 wd->started = EINA_TRUE;
1142 wd->pageflip = EINA_TRUE;
1143 wd->down_x = w / 2;
1144 wd->down_y = h - 1;
1145 wd->x = wd->down_x;
1146 wd->y = (1.0 - t) * wd->down_y;
1147 flip_show_hide(obj);
1148 _state_update(wd);
1149 }
1150 else if (wd->mode == ELM_FLIP_PAGE_DOWN)
1151 {
1152 wd->dir = 3;
1153 wd->started = EINA_TRUE;
1154 wd->pageflip = EINA_TRUE;
1155 wd->down_x = w / 2;
1156 wd->down_y = 0;
1157 wd->x = wd->down_x;
1158 wd->y = (t) * h;
1159 flip_show_hide(obj);
1160 _state_update(wd);
1161 }
1162 else
1163 _flip_do(obj, t, wd->mode, 0, 0);
1164
1165 if (t >= 1.0)
1166 {
1167 wd->pageflip = EINA_FALSE;
1168 _state_end(wd);
1169 evas_object_map_enable_set(wd->front.content, 0);
1170 evas_object_map_enable_set(wd->back.content, 0);
1171 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1172 evas_object_resize(wd->front.content, 0, 0);
1173 evas_object_resize(wd->back.content, 0, 0);
1174 evas_smart_objects_calculate(evas_object_evas_get(obj));
1175 // FIXME: end hack
1176 wd->animator = NULL;
1177 wd->state = !wd->state;
1178 _configure(obj);
1179 flip_show_hide(obj);
1180 evas_object_smart_callback_call(obj, SIG_ANIMATE_DONE, NULL);
1181 return ECORE_CALLBACK_CANCEL;
1182 }
1183 return ECORE_CALLBACK_RENEW;
1184}
1185
1186static void
1187_configure(Evas_Object *obj)
1188{
1189 Widget_Data *wd = elm_widget_data_get(obj);
1190 Evas_Coord x, y, w, h;
1191 Evas_Coord fsize;
1192 if (!wd) return;
1193
1194 _showhide(obj);
1195 evas_object_geometry_get(obj, &x, &y, &w, &h);
1196 // FIXME: manual flip wont get fixed
1197 if (wd->animator) _flip(obj);
1198
1199 if (wd->event[0])
1200 {
1201 fsize = (double)w * wd->dir_hitsize[0];
1202 elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1203 evas_object_move(wd->event[0], x, y);
1204 evas_object_resize(wd->event[0], w, fsize);
1205 }
1206 if (wd->event[1])
1207 {
1208 fsize = (double)w * wd->dir_hitsize[1];
1209 elm_coords_finger_size_adjust(0, NULL, 1, &fsize);
1210 evas_object_move(wd->event[1], x, y + h - fsize);
1211 evas_object_resize(wd->event[1], w, fsize);
1212 }
1213 if (wd->event[2])
1214 {
1215 fsize = (double)h * wd->dir_hitsize[2];
1216 elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1217 evas_object_move(wd->event[2], x, y);
1218 evas_object_resize(wd->event[2], fsize, h);
1219 }
1220 if (wd->event[3])
1221 {
1222 fsize = (double)h * wd->dir_hitsize[3];
1223 elm_coords_finger_size_adjust(1, &fsize, 0, NULL);
1224 evas_object_move(wd->event[3], x + w - fsize, y);
1225 evas_object_resize(wd->event[3], fsize, h);
1226 }
1227}
1228
1229static void
1230_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1231{
1232 _configure(obj);
1233}
1234
1235static void
1236_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1237{
1238 _configure(obj);
1239}
1240
1241static Eina_Bool
1242_animate(void *data)
1243{
1244 return _flip(data);
1245}
1246
1247static double
1248_pos_get(Widget_Data *wd, int *rev, Elm_Flip_Mode *m)
1249{
1250 Evas_Coord x, y, w, h;
1251 double t = 1.0;
1252
1253 evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
1254 switch (wd->intmode)
1255 {
1256 case ELM_FLIP_INTERACTION_ROTATE:
1257 case ELM_FLIP_INTERACTION_CUBE:
1258 {
1259 if (wd->dir == 0)
1260 {
1261 if (wd->down_x > 0)
1262 t = 1.0 - ((double)wd->x / (double)wd->down_x);
1263 *rev = 1;
1264 }
1265 else if (wd->dir == 1)
1266 {
1267 if (wd->down_x < w)
1268 t = 1.0 - ((double)(w - wd->x) / (double)(w - wd->down_x));
1269 }
1270 else if (wd->dir == 2)
1271 {
1272 if (wd->down_y > 0)
1273 t = 1.0 - ((double)wd->y / (double)wd->down_y);
1274 }
1275 else if (wd->dir == 3)
1276 {
1277 if (wd->down_y < h)
1278 t = 1.0 - ((double)(h - wd->y) / (double)(h - wd->down_y));
1279 *rev = 1;
1280 }
1281
1282 if (t < 0.0) t = 0.0;
1283 else if (t > 1.0) t = 1.0;
1284
1285 if ((wd->dir == 0) || (wd->dir == 1))
1286 {
1287 if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
1288 *m = ELM_FLIP_ROTATE_Y_CENTER_AXIS;
1289 else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
1290 {
1291 if (*rev)
1292 *m = ELM_FLIP_CUBE_LEFT;
1293 else
1294 *m = ELM_FLIP_CUBE_RIGHT;
1295 }
1296 }
1297 else
1298 {
1299 if (wd->intmode == ELM_FLIP_INTERACTION_ROTATE)
1300 *m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1301 else if (wd->intmode == ELM_FLIP_INTERACTION_CUBE)
1302 {
1303 if (*rev)
1304 *m = ELM_FLIP_CUBE_UP;
1305 else
1306 *m = ELM_FLIP_CUBE_DOWN;
1307 }
1308 }
1309 }
1310 default:
1311 break;
1312 }
1313 return t;
1314}
1315
1316static Eina_Bool
1317_event_anim(void *data, double pos)
1318{
1319 Widget_Data *wd = data;
1320 double p;
1321
1322 p = ecore_animator_pos_map(pos, ECORE_POS_MAP_ACCELERATE, 0.0, 0.0);
1323 if (wd->finish)
1324 {
1325 if (wd->dir == 0)
1326 wd->x = wd->ox * (1.0 - p);
1327 else if (wd->dir == 1)
1328 wd->x = wd->ox + ((wd->w - wd->ox) * p);
1329 else if (wd->dir == 2)
1330 wd->y = wd->oy * (1.0 - p);
1331 else if (wd->dir == 3)
1332 wd->y = wd->oy + ((wd->h - wd->oy) * p);
1333 }
1334 else
1335 {
1336 if (wd->dir == 0)
1337 wd->x = wd->ox + ((wd->w - wd->ox) * p);
1338 else if (wd->dir == 1)
1339 wd->x = wd->ox * (1.0 - p);
1340 else if (wd->dir == 2)
1341 wd->y = wd->oy + ((wd->h - wd->oy) * p);
1342 else if (wd->dir == 3)
1343 wd->y = wd->oy * (1.0 - p);
1344 }
1345 switch (wd->intmode)
1346 {
1347 case ELM_FLIP_INTERACTION_NONE:
1348 break;
1349 case ELM_FLIP_INTERACTION_ROTATE:
1350 case ELM_FLIP_INTERACTION_CUBE:
1351 {
1352 Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1353 int rev = 0;
1354 p = _pos_get(wd, &rev, &m);
1355 _flip_do(wd->obj, p, m, 1, rev);
1356 }
1357 break;
1358 case ELM_FLIP_INTERACTION_PAGE:
1359 wd->pageflip = EINA_TRUE;
1360 _configure(data);
1361 _state_update(wd);
1362 break;
1363 default:
1364 break;
1365 }
1366 if (pos < 1.0) return ECORE_CALLBACK_RENEW;
1367
1368 wd->pageflip = EINA_FALSE;
1369 _state_end(wd);
1370 evas_object_map_enable_set(wd->front.content, 0);
1371 evas_object_map_enable_set(wd->back.content, 0);
1372 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow
1373 evas_object_resize(wd->front.content, 0, 0);
1374 evas_object_resize(wd->back.content, 0, 0);
1375 evas_smart_objects_calculate(evas_object_evas_get(wd->obj));
1376 // FIXME: end hack
1377 wd->animator = NULL;
1378 if (wd->finish) wd->state = !wd->state;
1379 flip_show_hide(wd->obj);
1380 _configure(wd->obj);
1381 wd->animator = NULL;
1382 evas_object_smart_callback_call(wd->obj, SIG_ANIMATE_DONE, NULL);
1383
1384 return ECORE_CALLBACK_CANCEL;
1385}
1386
1387static void
1388_update_job(void *data)
1389{
1390 Widget_Data *wd = data;
1391 double p;
1392 Elm_Flip_Mode m = ELM_FLIP_ROTATE_X_CENTER_AXIS;
1393 int rev = 0;
1394
1395 wd->job = NULL;
1396 switch (wd->intmode)
1397 {
1398 case ELM_FLIP_INTERACTION_ROTATE:
1399 case ELM_FLIP_INTERACTION_CUBE:
1400 p = _pos_get(wd, &rev, &m);
1401 _flip_do(wd->obj, p, m, 1, rev);
1402 break;
1403 case ELM_FLIP_INTERACTION_PAGE:
1404 wd->pageflip = EINA_TRUE;
1405 _configure(data);
1406 _state_update(wd);
1407 break;
1408 default:
1409 break;
1410 }
1411}
1412
1413static void
1414_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1415{
1416 Evas_Object *fl = data;
1417 Widget_Data *wd = elm_widget_data_get(fl);
1418 Evas_Event_Mouse_Down *ev = event_info;
1419 Evas_Coord x, y, w, h;
1420
1421 if (!wd) return;
1422 if (ev->button != 1) return;
1423 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1424 if (wd->animator)
1425 {
1426 ecore_animator_del(wd->animator);
1427 wd->animator = NULL;
1428 }
1429 wd->down = EINA_TRUE;
1430 wd->started = EINA_FALSE;
1431 evas_object_geometry_get(data, &x, &y, &w, &h);
1432 wd->x = ev->canvas.x - x;
1433 wd->y = ev->canvas.y - y;
1434 wd->w = w;
1435 wd->h = h;
1436 wd->down_x = wd->x;
1437 wd->down_y = wd->y;
1438}
1439
1440static void
1441_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1442{
1443 Evas_Object *fl = data;
1444 Widget_Data *wd = elm_widget_data_get(fl);
1445 Evas_Event_Mouse_Up *ev = event_info;
1446 Evas_Coord x, y, w, h;
1447 double tm = 0.5;
1448
1449 if (!wd) return;
1450 if (ev->button != 1) return;
1451 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1452 wd->down = 0;
1453 evas_object_geometry_get(data, &x, &y, &w, &h);
1454 wd->x = ev->canvas.x - x;
1455 wd->y = ev->canvas.y - y;
1456 wd->w = w;
1457 wd->h = h;
1458 wd->ox = wd->x;
1459 wd->oy = wd->y;
1460 if (wd->job)
1461 {
1462 ecore_job_del(wd->job);
1463 wd->job = NULL;
1464 }
1465 wd->finish = EINA_FALSE;
1466 if (wd->dir == 0)
1467 {
1468 tm = (double)wd->x / (double)wd->w;
1469 if (wd->x < (wd->w / 2)) wd->finish = EINA_TRUE;
1470 }
1471 else if (wd->dir == 1)
1472 {
1473 if (wd->x > (wd->w / 2)) wd->finish = EINA_TRUE;
1474 tm = 1.0 - ((double)wd->x / (double)wd->w);
1475 }
1476 else if (wd->dir == 2)
1477 {
1478 if (wd->y < (wd->h / 2)) wd->finish = EINA_TRUE;
1479 tm = (double)wd->y / (double)wd->h;
1480 }
1481 else if (wd->dir == 3)
1482 {
1483 if (wd->y > (wd->h / 2)) wd->finish = EINA_TRUE;
1484 tm = 1.0 - ((double)wd->y / (double)wd->h);
1485 }
1486 if (tm < 0.01) tm = 0.01;
1487 else if (tm > 0.99) tm = 0.99;
1488 if (!wd->finish) tm = 1.0 - tm;
1489 tm *= 1.0; // FIXME: config for anim time
1490 if (wd->animator) ecore_animator_del(wd->animator);
1491 wd->animator = ecore_animator_timeline_add(tm, _event_anim, wd);
1492 _event_anim(wd, 0.0);
1493}
1494
1495static void
1496_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1497{
1498 Evas_Object *fl = data;
1499 Widget_Data *wd = elm_widget_data_get(fl);
1500 Evas_Event_Mouse_Move *ev = event_info;
1501 Evas_Coord x, y, w, h;
1502
1503 if (!wd) return;
1504 if (!wd->down) return;
1505 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1506 evas_object_geometry_get(data, &x, &y, &w, &h);
1507 wd->x = ev->cur.canvas.x - x;
1508 wd->y = ev->cur.canvas.y - y;
1509 wd->w = w;
1510 wd->h = h;
1511 if (!wd->started)
1512 {
1513 Evas_Coord dx, dy;
1514
1515 dx = wd->x - wd->down_x;
1516 dy = wd->y - wd->down_y;
1517 if (((dx * dx) + (dy * dy)) >
1518 (_elm_config->finger_size * _elm_config->finger_size / 4))
1519 {
1520 wd->dir = 0;
1521 if ((wd->x > (w / 2)) &&
1522 (dx < 0) && (abs(dx) > abs(dy)))
1523 wd->dir = 0; // left
1524 else if ((wd->x < (w / 2)) && (dx >= 0) &&
1525 (abs(dx) > abs(dy)))
1526 wd->dir = 1; // right
1527 else if ((wd->y > (h / 2)) && (dy < 0) && (abs(dy) >= abs(dx)))
1528 wd->dir = 2; // up
1529 else if ((wd->y < (h / 2)) && (dy >= 0) && (abs(dy) >= abs(dx)))
1530 wd->dir = 3; // down
1531 wd->started = EINA_TRUE;
1532 if (wd->intmode == ELM_FLIP_INTERACTION_PAGE)
1533 wd->pageflip = EINA_TRUE;
1534 flip_show_hide(data);
1535 evas_smart_objects_calculate(evas_object_evas_get(data));
1536 _flip(data);
1537 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1538 evas_object_map_enable_set(wd->front.content, EINA_FALSE);
1539 evas_object_map_enable_set(wd->back.content, EINA_FALSE);
1540// FIXME: XXX why does this bork interactive flip??
1541// evas_object_resize(wd->front.content, 0, 0);
1542// evas_object_resize(wd->back.content, 0, 0);
1543 evas_smart_objects_calculate(evas_object_evas_get(data));
1544 _configure(obj);
1545 // FIXME: end hack
1546 evas_object_smart_callback_call(obj, SIG_ANIMATE_BEGIN, NULL);
1547 }
1548 else return;
1549 }
1550 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1551 if (wd->job) ecore_job_del(wd->job);
1552 wd->job = ecore_job_add(_update_job, wd);
1553}
1554
1555static void
1556_flip_content_front_set(Evas_Object *obj, Evas_Object *content)
1557{
1558 Widget_Data *wd = elm_widget_data_get(obj);
1559 if (!wd) return;
1560
1561 int i;
1562
1563 if (wd->front.content == content) return;
1564 if (wd->front.content) evas_object_del(wd->front.content);
1565 wd->front.content = content;
1566 if (content)
1567 {
1568 elm_widget_sub_object_add(obj, content);
1569 evas_object_smart_member_add(content, obj);
1570 //FIXME: smart member clip could be reset by the obj.
1571 evas_object_clip_set(content, wd->front.clip);
1572 evas_object_event_callback_add(content,
1573 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1574 _changed_size_hints, obj);
1575 _sizing_eval(obj);
1576 }
1577
1578 // force calc to contents are the right size before transition
1579 evas_smart_objects_calculate(evas_object_evas_get(obj));
1580 flip_show_hide(obj);
1581 _configure(obj);
1582 if (wd->intmode != ELM_FLIP_INTERACTION_NONE)
1583 {
1584 for (i = 0; i < 4; i++) evas_object_raise(wd->event[i]);
1585 }
1586}
1587
1588static void
1589_flip_content_back_set(Evas_Object *obj, Evas_Object *content)
1590{
1591 Widget_Data *wd = elm_widget_data_get(obj);
1592 if (!wd) return;
1593
1594 int i;
1595 if (wd->back.content == content) return;
1596 if (wd->back.content) evas_object_del(wd->back.content);
1597 wd->back.content = content;
1598 if (content)
1599 {
1600 elm_widget_sub_object_add(obj, content);
1601 evas_object_smart_member_add(content, obj);
1602 //FIXME: smart member clip could be reset by the obj.
1603 evas_object_clip_set(content, wd->back.clip);
1604 evas_object_event_callback_add(content,
1605 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1606 _changed_size_hints, obj);
1607 _sizing_eval(obj);
1608 }
1609
1610 // force calc to contents are the right size before transition
1611 evas_smart_objects_calculate(evas_object_evas_get(obj));
1612 flip_show_hide(obj);
1613 _configure(obj);
1614 if (wd->intmode != ELM_FLIP_INTERACTION_NONE)
1615 {
1616 for (i = 0; i < 4; i++) evas_object_raise(wd->event[i]);
1617 }
1618}
1619
1620static Evas_Object *
1621_content_front_unset(Evas_Object *obj)
1622{
1623 Widget_Data *wd = elm_widget_data_get(obj);
1624 if ((!wd) || (!wd->front.content)) return NULL;
1625
1626 Evas_Object *content = wd->front.content;
1627 elm_widget_sub_object_del(obj, content);
1628 evas_object_smart_member_del(content);
1629 return content;
1630}
1631
1632static Evas_Object *
1633_content_back_unset(Evas_Object *obj)
1634{
1635 Widget_Data *wd = elm_widget_data_get(obj);
1636 if ((!wd) || (!wd->back.content)) return NULL;
1637
1638 Evas_Object *content = wd->back.content;
1639 elm_widget_sub_object_del(obj, content);
1640 evas_object_smart_member_del(content);
1641 return content;
1642}
1643
1644static void
1645_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
1646{
1647 ELM_CHECK_WIDTYPE(obj, widtype);
1648
1649 if (!part || !strcmp(part, "front"))
1650 _flip_content_front_set(obj, content);
1651 else if (!strcmp(part, "back"))
1652 _flip_content_back_set(obj, content);
1653}
1654
1655static Evas_Object *
1656_content_get_hook(const Evas_Object *obj, const char *part)
1657{
1658 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1659 Widget_Data *wd = elm_widget_data_get(obj);
1660 if (!wd) return NULL;
1661
1662 if (!part || !strcmp(part, "front"))
1663 return wd->front.content;
1664 else if (!strcmp(part, "back"))
1665 return wd->back.content;
1666
1667 return NULL;
1668}
1669
1670static Evas_Object *
1671_content_unset_hook(Evas_Object *obj, const char *part)
1672{
1673 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1674
1675 if (!part || !strcmp(part, "front"))
1676 return _content_front_unset(obj);
1677 else if (!strcmp(part, "back"))
1678 return _content_back_unset(obj);
1679
1680 return NULL;
1681}
1682
1683EAPI Evas_Object *
1684elm_flip_add(Evas_Object *parent)
1685{
1686 Evas_Object *obj;
1687 Evas *e;
1688 Widget_Data *wd;
1689
1690 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1691
1692 ELM_SET_WIDTYPE(widtype, "flip");
1693 elm_widget_type_set(obj, "flip");
1694 elm_widget_sub_object_add(parent, obj);
1695 elm_widget_data_set(obj, wd);
1696 elm_widget_del_hook_set(obj, _del_hook);
1697 elm_widget_theme_hook_set(obj, _theme_hook);
1698 elm_widget_focus_next_hook_set(obj, _elm_flip_focus_next_hook);
1699 elm_widget_can_focus_set(obj, EINA_FALSE);
1700 elm_widget_content_set_hook_set(obj, _content_set_hook);
1701 elm_widget_content_get_hook_set(obj, _content_get_hook);
1702 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
1703
1704 wd->obj = obj;
1705
1706 wd->clip = evas_object_rectangle_add(e);
1707 evas_object_static_clip_set(wd->clip, EINA_TRUE);
1708 evas_object_move(wd->clip, -49999, -49999);
1709 evas_object_resize(wd->clip, 99999, 99999);
1710 elm_widget_sub_object_add(obj, wd->clip);
1711 evas_object_smart_member_add(wd->clip, obj);
1712
1713 wd->front.clip = evas_object_rectangle_add(e);
1714 evas_object_static_clip_set(wd->front.clip, EINA_TRUE);
1715 evas_object_data_set(wd->front.clip, "_elm_leaveme", obj);
1716 evas_object_move(wd->front.clip, -49999, -49999);
1717 evas_object_resize(wd->front.clip, 99999, 99999);
1718 elm_widget_sub_object_add(obj, wd->front.clip);
1719 evas_object_smart_member_add(wd->front.clip, obj);
1720 evas_object_clip_set(wd->front.clip, wd->clip);
1721
1722 wd->back.clip = evas_object_rectangle_add(e);
1723 evas_object_static_clip_set(wd->back.clip, EINA_TRUE);
1724 evas_object_data_set(wd->back.clip, "_elm_leaveme", obj);
1725 evas_object_move(wd->back.clip, -49999, -49999);
1726 evas_object_resize(wd->back.clip, 99999, 99999);
1727 elm_widget_sub_object_add(obj, wd->back.clip);
1728 evas_object_smart_member_add(wd->back.clip, obj);
1729 evas_object_clip_set(wd->back.clip, wd->clip);
1730
1731 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1732 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _move, NULL);
1733 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, NULL);
1734 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1735 _changed_size_hints, obj);;
1736
1737 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1738
1739 wd->state = EINA_TRUE;
1740 wd->intmode = ELM_FLIP_INTERACTION_NONE;
1741
1742 _sizing_eval(obj);
1743
1744 return obj;
1745}
1746
1747EAPI Eina_Bool
1748elm_flip_front_visible_get(const Evas_Object *obj)
1749{
1750 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1751 Widget_Data *wd = elm_widget_data_get(obj);
1752 if (!wd) return EINA_FALSE;
1753 return wd->state;
1754}
1755
1756EAPI void
1757elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
1758{
1759 ELM_CHECK_WIDTYPE(obj, widtype);
1760 Widget_Data *wd = elm_widget_data_get(obj);
1761 if (!wd) return;
1762}
1763
1764// FIXME: add ambient and lighting control
1765
1766EAPI void
1767elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode)
1768{
1769 ELM_CHECK_WIDTYPE(obj, widtype);
1770 Widget_Data *wd = elm_widget_data_get(obj);
1771 if (!wd) return;
1772 if (!wd->animator) wd->animator = ecore_animator_add(_animate, obj);
1773 flip_show_hide(obj);
1774 wd->mode = mode;
1775 wd->start = ecore_loop_time_get();
1776 wd->len = 0.5; // FIXME: make config val
1777 if ((wd->mode == ELM_FLIP_PAGE_LEFT) ||
1778 (wd->mode == ELM_FLIP_PAGE_RIGHT) ||
1779 (wd->mode == ELM_FLIP_PAGE_UP) ||
1780 (wd->mode == ELM_FLIP_PAGE_DOWN))
1781 wd->pageflip = EINA_TRUE;
1782 // force calc to contents are the right size before transition
1783 evas_smart_objects_calculate(evas_object_evas_get(obj));
1784 _flip(obj);
1785 // FIXME: hack around evas rendering bug (only fix makes evas bitch-slow)
1786 evas_object_map_enable_set(wd->front.content, 0);
1787 evas_object_map_enable_set(wd->back.content, 0);
1788 evas_object_resize(wd->front.content, 0, 0);
1789 evas_object_resize(wd->back.content, 0, 0);
1790 evas_smart_objects_calculate(evas_object_evas_get(obj));
1791 _configure(obj);
1792 // FIXME: end hack
1793 evas_object_smart_callback_call(obj, SIG_ANIMATE_BEGIN, NULL);
1794}
1795
1796EAPI void
1797elm_flip_interaction_set(Evas_Object *obj, Elm_Flip_Interaction mode)
1798{
1799 ELM_CHECK_WIDTYPE(obj, widtype);
1800 int i;
1801 Widget_Data *wd = elm_widget_data_get(obj);
1802 if (!wd) return;
1803 if (wd->intmode == mode) return;
1804 wd->intmode = mode;
1805 for (i = 0; i < 4; i++)
1806 {
1807 if (wd->intmode == ELM_FLIP_INTERACTION_NONE)
1808 {
1809 if (wd->event[i])
1810 {
1811 evas_object_del(wd->event[i]);
1812 wd->event[i] = NULL;
1813 }
1814 }
1815 else
1816 {
1817 if ((wd->dir_enabled[i]) && (!wd->event[i]))
1818 {
1819 Evas *e = evas_object_evas_get(obj);
1820 wd->event[i] = evas_object_rectangle_add(e);
1821 elm_widget_sub_object_add(obj, wd->event[i]);
1822 evas_object_data_set(wd->event[i], "_elm_leaveme", obj);
1823 evas_object_clip_set(wd->event[i], evas_object_clip_get(obj));
1824 evas_object_color_set(wd->event[i], 0, 0, 0, 0);
1825 evas_object_show(wd->event[i]);
1826 evas_object_smart_member_add(wd->event[i], obj);
1827 evas_object_event_callback_add(wd->event[i],
1828 EVAS_CALLBACK_MOUSE_DOWN,
1829 _down_cb, obj);
1830 evas_object_event_callback_add(wd->event[i],
1831 EVAS_CALLBACK_MOUSE_UP,
1832 _up_cb, obj);
1833 evas_object_event_callback_add(wd->event[i],
1834 EVAS_CALLBACK_MOUSE_MOVE,
1835 _move_cb, obj);
1836 }
1837 }
1838 }
1839 _sizing_eval(obj);
1840 _configure(obj);
1841}
1842
1843EAPI Elm_Flip_Interaction
1844elm_flip_interaction_get(const Evas_Object *obj)
1845{
1846 ELM_CHECK_WIDTYPE(obj, widtype) ELM_FLIP_INTERACTION_NONE;
1847 Widget_Data *wd = elm_widget_data_get(obj);
1848 if (!wd) return ELM_FLIP_INTERACTION_NONE;
1849 return wd->intmode;
1850}
1851
1852EAPI void
1853elm_flip_interaction_direction_enabled_set(Evas_Object *obj, Elm_Flip_Direction dir, Eina_Bool enabled)
1854{
1855 ELM_CHECK_WIDTYPE(obj, widtype);
1856 Widget_Data *wd = elm_widget_data_get(obj);
1857 int i = -1;
1858 if (!wd) return;
1859 enabled = !!enabled;
1860 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1861 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1862 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1863 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1864 if (i < 0) return;
1865 if (wd->dir_enabled[i] == enabled) return;
1866 wd->dir_enabled[i] = enabled;
1867 if (wd->intmode == ELM_FLIP_INTERACTION_NONE) return;
1868 if ((wd->dir_enabled[i]) && (!wd->event[i]))
1869 {
1870 wd->event[i] = evas_object_rectangle_add(evas_object_evas_get(obj));
1871 elm_widget_sub_object_add(obj, wd->event[i]);
1872 evas_object_data_set(wd->event[i], "_elm_leaveme", obj);
1873 evas_object_clip_set(wd->event[i], evas_object_clip_get(obj));
1874 evas_object_color_set(wd->event[i], 0, 0, 0, 0);
1875 evas_object_show(wd->event[i]);
1876 evas_object_smart_member_add(wd->event[i], obj);
1877 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_DOWN,
1878 _down_cb, obj);
1879 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_UP,
1880 _up_cb, obj);
1881 evas_object_event_callback_add(wd->event[i], EVAS_CALLBACK_MOUSE_MOVE,
1882 _move_cb, obj);
1883 }
1884 else if (!(wd->dir_enabled[i]) && (wd->event[i]))
1885 {
1886 evas_object_del(wd->event[i]);
1887 wd->event[i] = NULL;
1888 }
1889 _sizing_eval(obj);
1890 _configure(obj);
1891}
1892
1893EAPI Eina_Bool
1894elm_flip_interaction_direction_enabled_get(Evas_Object *obj, Elm_Flip_Direction dir)
1895{
1896 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1897 Widget_Data *wd = elm_widget_data_get(obj);
1898 int i = -1;
1899 if (!wd) return EINA_FALSE;
1900 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1901 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1902 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1903 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1904 if (i < 0) return EINA_FALSE;
1905 return wd->dir_enabled[i];
1906}
1907
1908EAPI void
1909elm_flip_interaction_direction_hitsize_set(Evas_Object *obj, Elm_Flip_Direction dir, double hitsize)
1910{
1911 ELM_CHECK_WIDTYPE(obj, widtype);
1912 Widget_Data *wd = elm_widget_data_get(obj);
1913 int i = -1;
1914 if (!wd) return;
1915 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1916 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1917 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1918 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1919 if (i < 0) return;
1920 if (hitsize < 0.0) hitsize = 0.0;
1921 else if (hitsize > 1.0) hitsize = 1.0;
1922 if (wd->dir_hitsize[i] == hitsize) return;
1923 wd->dir_hitsize[i] = hitsize;
1924 _sizing_eval(obj);
1925 _configure(obj);
1926}
1927
1928EAPI double
1929elm_flip_interaction_direction_hitsize_get(Evas_Object *obj, Elm_Flip_Direction dir)
1930{
1931 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1932 Widget_Data *wd = elm_widget_data_get(obj);
1933 int i = -1;
1934 if (!wd) return 0.0;
1935 if (dir == ELM_FLIP_DIRECTION_UP) i = 0;
1936 else if (dir == ELM_FLIP_DIRECTION_DOWN) i = 1;
1937 else if (dir == ELM_FLIP_DIRECTION_LEFT) i = 2;
1938 else if (dir == ELM_FLIP_DIRECTION_RIGHT) i = 3;
1939 if (i < 0) return 0.0;
1940 return wd->dir_hitsize[i];
1941}
diff --git a/libraries/elementary/src/lib/elm_flip.h b/libraries/elementary/src/lib/elm_flip.h
new file mode 100644
index 0000000..124809b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_flip.h
@@ -0,0 +1,257 @@
1/**
2 * @defgroup Flip Flip
3 * @ingroup Elementary
4 *
5 * @image html img/widget/flip/preview-00.png
6 * @image latex img/widget/flip/preview-00.eps
7 *
8 * This widget holds 2 content objects(Evas_Object): one on the front and one
9 * on the back. It allows you to flip from front to back and vice-versa using
10 * various animations.
11 *
12 * If either the front or back contents are not set the flip will treat that
13 * as transparent. So if you wore to set the front content but not the back,
14 * and then call elm_flip_go() you would see whatever is below the flip.
15 *
16 * For a list of supported animations see elm_flip_go().
17 *
18 * Signals that you can add callbacks for are:
19 * "animate,begin" - when a flip animation was started
20 * "animate,done" - when a flip animation is finished
21 *
22 * Default content parts of the flip widget that you can use for are:
23 * @li "front" - A front content of the flip
24 * @li "back" - A back content of the flip
25 *
26 * Supported elm_object common APIs.
27 * @li @ref elm_object_part_content_set
28 * @li @ref elm_object_part_content_get
29 * @li @ref elm_object_part_content_unset
30 *
31 * @ref tutorial_flip show how to use most of the API.
32 *
33 * @{
34 */
35typedef enum
36{
37 ELM_FLIP_ROTATE_Y_CENTER_AXIS,
38 ELM_FLIP_ROTATE_X_CENTER_AXIS,
39 ELM_FLIP_ROTATE_XZ_CENTER_AXIS,
40 ELM_FLIP_ROTATE_YZ_CENTER_AXIS,
41 ELM_FLIP_CUBE_LEFT,
42 ELM_FLIP_CUBE_RIGHT,
43 ELM_FLIP_CUBE_UP,
44 ELM_FLIP_CUBE_DOWN,
45 ELM_FLIP_PAGE_LEFT,
46 ELM_FLIP_PAGE_RIGHT,
47 ELM_FLIP_PAGE_UP,
48 ELM_FLIP_PAGE_DOWN
49} Elm_Flip_Mode;
50
51typedef enum
52{
53 ELM_FLIP_INTERACTION_NONE,
54 ELM_FLIP_INTERACTION_ROTATE,
55 ELM_FLIP_INTERACTION_CUBE,
56 ELM_FLIP_INTERACTION_PAGE
57} Elm_Flip_Interaction;
58
59typedef enum
60{
61 ELM_FLIP_DIRECTION_UP, /**< Allows interaction with the top of the widget */
62 ELM_FLIP_DIRECTION_DOWN, /**< Allows interaction with the bottom of the widget */
63 ELM_FLIP_DIRECTION_LEFT, /**< Allows interaction with the left portion of the widget */
64 ELM_FLIP_DIRECTION_RIGHT /**< Allows interaction with the right portion of the widget */
65} Elm_Flip_Direction;
66
67/**
68 * @brief Add a new flip to the parent
69 *
70 * @param parent The parent object
71 * @return The new object or NULL if it cannot be created
72 *
73 * @ingroup Flip
74 */
75EAPI Evas_Object *elm_flip_add(Evas_Object *parent);
76
77/**
78 * @brief Get flip front visibility state
79 *
80 * @param obj The flip object
81 * @return EINA_TRUE if front front is showing, EINA_FALSE if the back is
82 * showing.
83 *
84 * @ingroup Flip
85 */
86Eina_Bool elm_flip_front_visible_get(const Evas_Object *obj);
87
88/**
89 * @brief Set flip perspective
90 *
91 * @param obj The flip object
92 * @param foc The coordinate to set the focus on
93 * @param x The X coordinate
94 * @param y The Y coordinate
95 *
96 * @warning This function currently does nothing.
97 *
98 * @ingroup Flip
99 */
100EAPI void elm_flip_perspective_set(Evas_Object *obj, Evas_Coord foc, Evas_Coord x, Evas_Coord y);
101
102/**
103 * @brief Runs the flip animation
104 *
105 * @param obj The flip object
106 * @param mode The mode type
107 *
108 * Flips the front and back contents using the @p mode animation. This
109 * effectively hides the currently visible content and shows the hidden one.
110 *
111 * There a number of possible animations to use for the flipping:
112 * @li ELM_FLIP_ROTATE_X_CENTER_AXIS - Rotate the currently visible content
113 * around a horizontal axis in the middle of its height, the other content
114 * is shown as the other side of the flip.
115 * @li ELM_FLIP_ROTATE_Y_CENTER_AXIS - Rotate the currently visible content
116 * around a vertical axis in the middle of its width, the other content is
117 * shown as the other side of the flip.
118 * @li ELM_FLIP_ROTATE_XZ_CENTER_AXIS - Rotate the currently visible content
119 * around a diagonal axis in the middle of its width, the other content is
120 * shown as the other side of the flip.
121 * @li ELM_FLIP_ROTATE_YZ_CENTER_AXIS - Rotate the currently visible content
122 * around a diagonal axis in the middle of its height, the other content is
123 * shown as the other side of the flip.
124 * @li ELM_FLIP_CUBE_LEFT - Rotate the currently visible content to the left
125 * as if the flip was a cube, the other content is show as the right face of
126 * the cube.
127 * @li ELM_FLIP_CUBE_RIGHT - Rotate the currently visible content to the
128 * right as if the flip was a cube, the other content is show as the left
129 * face of the cube.
130 * @li ELM_FLIP_CUBE_UP - Rotate the currently visible content up as if the
131 * flip was a cube, the other content is show as the bottom face of the cube.
132 * @li ELM_FLIP_CUBE_DOWN - Rotate the currently visible content down as if
133 * the flip was a cube, the other content is show as the upper face of the
134 * cube.
135 * @li ELM_FLIP_PAGE_LEFT - Move the currently visible content to the left as
136 * if the flip was a book, the other content is shown as the page below that.
137 * @li ELM_FLIP_PAGE_RIGHT - Move the currently visible content to the right
138 * as if the flip was a book, the other content is shown as the page below
139 * that.
140 * @li ELM_FLIP_PAGE_UP - Move the currently visible content up as if the
141 * flip was a book, the other content is shown as the page below that.
142 * @li ELM_FLIP_PAGE_DOWN - Move the currently visible content down as if the
143 * flip was a book, the other content is shown as the page below that.
144 *
145 * @image html elm_flip.png
146 * @image latex elm_flip.eps width=\textwidth
147 *
148 * @ingroup Flip
149 */
150EAPI void elm_flip_go(Evas_Object *obj, Elm_Flip_Mode mode);
151
152/**
153 * @brief Set the interactive flip mode
154 *
155 * @param obj The flip object
156 * @param mode The interactive flip mode to use
157 *
158 * This sets if the flip should be interactive (allow user to click and
159 * drag a side of the flip to reveal the back page and cause it to flip).
160 * By default a flip is not interactive. You may also need to set which
161 * sides of the flip are "active" for flipping and how much space they use
162 * (a minimum of a finger size) with elm_flip_interaction_direction_enabled_set()
163 * and elm_flip_interaction_direction_hitsize_set()
164 *
165 * The four available mode of interaction are:
166 * @li ELM_FLIP_INTERACTION_NONE - No interaction is allowed
167 * @li ELM_FLIP_INTERACTION_ROTATE - Interaction will cause rotate animation
168 * @li ELM_FLIP_INTERACTION_CUBE - Interaction will cause cube animation
169 * @li ELM_FLIP_INTERACTION_PAGE - Interaction will cause page animation
170 *
171 * @note ELM_FLIP_INTERACTION_ROTATE won't cause
172 * ELM_FLIP_ROTATE_XZ_CENTER_AXIS or ELM_FLIP_ROTATE_YZ_CENTER_AXIS to
173 * happen, those can only be achieved with elm_flip_go();
174 *
175 * @ingroup Flip
176 */
177EAPI void elm_flip_interaction_set(Evas_Object *obj, Elm_Flip_Interaction mode);
178
179/**
180 * @brief Get the interactive flip mode
181 *
182 * @param obj The flip object
183 * @return The interactive flip mode
184 *
185 * Returns the interactive flip mode set by elm_flip_interaction_set()
186 *
187 * @ingroup Flip
188 */
189EAPI Elm_Flip_Interaction elm_flip_interaction_get(const Evas_Object *obj);
190
191/**
192 * @brief Set which directions of the flip respond to interactive flip
193 *
194 * @param obj The flip object
195 * @param dir The direction to change
196 * @param enabled If that direction is enabled or not
197 *
198 * By default all directions are disabled, so you may want to enable the
199 * desired directions for flipping if you need interactive flipping. You must
200 * call this function once for each direction that should be enabled.
201 *
202 * @see elm_flip_interaction_set()
203 *
204 * @ingroup Flip
205 */
206EAPI void elm_flip_interaction_direction_enabled_set(Evas_Object *obj, Elm_Flip_Direction dir, Eina_Bool enabled);
207
208/**
209 * @brief Get the enabled state of that flip direction
210 *
211 * @param obj The flip object
212 * @param dir The direction to check
213 * @return If that direction is enabled or not
214 *
215 * Gets the enabled state set by elm_flip_interaction_direction_enabled_set()
216 *
217 * @see elm_flip_interaction_set()
218 *
219 * @ingroup Flip
220 */
221EAPI Eina_Bool elm_flip_interaction_direction_enabled_get(Evas_Object *obj, Elm_Flip_Direction dir);
222
223/**
224 * @brief Set the amount of the flip that is sensitive to interactive flip
225 *
226 * @param obj The flip object
227 * @param dir The direction to modify
228 * @param hitsize The amount of that dimension (0.0 to 1.0) to use
229 *
230 * Set the amount of the flip that is sensitive to interactive flip, with 0
231 * representing no area in the flip and 1 representing the entire flip. There
232 * is however a consideration to be made in that the area will never be
233 * smaller than the finger size set(as set in your Elementary configuration).
234 *
235 * @see elm_flip_interaction_set()
236 *
237 * @ingroup Flip
238 */
239EAPI void elm_flip_interaction_direction_hitsize_set(Evas_Object *obj, Elm_Flip_Direction dir, double hitsize);
240
241/**
242 * @brief Get the amount of the flip that is sensitive to interactive flip
243 *
244 * @param obj The flip object
245 * @param dir The direction to check
246 * @return The size set for that direction
247 *
248 * Returns the amount of sensitive area set by
249 * elm_flip_interaction_direction_hitsize_set().
250 *
251 * @ingroup Flip
252 */
253EAPI double elm_flip_interaction_direction_hitsize_get(Evas_Object *obj, Elm_Flip_Direction dir);
254
255/**
256 * @}
257 */
diff --git a/libraries/elementary/src/lib/elm_flipselector.c b/libraries/elementary/src/lib/elm_flipselector.c
new file mode 100644
index 0000000..7939aba
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_flipselector.c
@@ -0,0 +1,936 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4/* TODO: ideally, the default theme would use map{} blocks on the TEXT
5 parts to implement their fading in/out propertly (as in the clock
6 widget) */
7/* TODO: if one ever wants to extend it to receiving generic widgets
8 as items, be my guest. in this case, remember to implement the
9 items tooltip infra. */
10/* TODO: fix default theme image borders for looong strings as item
11 labels. */
12/* TODO: set text elipsis on labels if one enforces mininum size on
13 * the overall widget less the required for displaying it. */
14/* TODO: find a way to, in the default theme, to detect we are
15 * bootstrapping (receiving the 1st message) and populate the downmost
16 * TEXT parts with the same text as the upmost, where appropriate. */
17
18#define FLIP_FIRST_INTERVAL (0.85)
19#define FLIP_MIN_INTERVAL (0.1)
20#define MSG_FLIP_DOWN (1)
21#define MSG_FLIP_UP (2)
22#define MAX_LEN_DEFAULT (50)
23
24#define DATA_GET eina_list_data_get
25
26struct _Elm_Flipselector_Item
27{
28 ELM_WIDGET_ITEM;
29 const char *label;
30 Evas_Smart_Cb func;
31 void *data;
32 int deleted : 1;
33};
34
35typedef struct _Widget_Data Widget_Data;
36typedef struct _Elm_Flipselector_Item Elm_Flipselector_Item;
37
38struct _Widget_Data
39{
40 Evas_Object *self;
41 Evas_Object *base;
42 Eina_List *items;
43 Eina_List *current;
44 Eina_List *sentinel; /* item containing the largest label string */
45 int walking;
46 unsigned int max_len;
47 Ecore_Timer *spin;
48 double interval, first_interval;
49};
50
51static const char *widtype = NULL;
52static void _del_hook(Evas_Object *obj);
53static void _theme_hook(Evas_Object *obj);
54static void _sizing_eval(Evas_Object *obj);
55static void _update_view(Evas_Object *obj);
56static void _callbacks_set(Evas_Object *obj);
57static void _flip_up(Widget_Data *wd);
58static void _flip_down(Widget_Data *wd);
59static Eina_Bool _item_del_pre_hook(Elm_Object_Item *it);
60
61static const char SIG_SELECTED[] = "selected";
62static const char SIG_UNDERFLOWED[] = "underflowed";
63static const char SIG_OVERFLOWED[] = "overflowed";
64static const Evas_Smart_Cb_Description _signals[] = {
65 {SIG_SELECTED, ""},
66 {SIG_UNDERFLOWED, ""},
67 {SIG_OVERFLOWED, ""},
68 {NULL, NULL}
69};
70
71static void
72_item_text_set_hook(Elm_Object_Item *it,
73 const char *part,
74 const char *label)
75{
76 Widget_Data *wd;
77 Eina_List *l;
78 Elm_Flipselector_Item *item;
79
80 if (!label) return;
81
82 if (part && strcmp(part ,"default")) return;
83
84 item = (Elm_Flipselector_Item *)it;
85 wd = elm_widget_data_get(WIDGET(item));
86 if ((!wd) || (!wd->items)) return;
87
88 l = eina_list_data_find_list(wd->items, item);
89 if (!l) return;
90
91 eina_stringshare_del(item->label);
92 item->label = eina_stringshare_add_length(label, wd->max_len);
93
94 if (strlen(label) > strlen(elm_object_item_text_get(DATA_GET(wd->sentinel))))
95 wd->sentinel = l;
96
97 if (wd->current == l)
98 {
99 _update_view(WIDGET(item));
100 _sizing_eval(wd->self);
101 }
102}
103
104static const char *
105_item_text_get_hook(const Elm_Object_Item *it, const char *part)
106{
107 if (part && strcmp(part ,"default")) return NULL;
108
109 return ((Elm_Flipselector_Item *)it)->label;
110}
111
112static void
113_item_signal_emit_hook(Elm_Object_Item *it,
114 const char *emission,
115 const char *source)
116{
117 Elm_Flipselector_Item *item = (Elm_Flipselector_Item *)it;
118 edje_object_signal_emit(VIEW(item), emission, source);
119}
120
121static Elm_Flipselector_Item *
122_item_new(Evas_Object *obj, const char *label, Evas_Smart_Cb func, const void *data)
123{
124 unsigned int len;
125 Elm_Flipselector_Item *it;
126 Widget_Data *wd = elm_widget_data_get(obj);
127
128 it = elm_widget_item_new(obj, Elm_Flipselector_Item);
129 if (!it) return NULL;
130
131 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
132 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
133 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
134 elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
135
136 len = strlen(label);
137 if (len > wd->max_len)
138 len = wd->max_len;
139
140 it->label = eina_stringshare_add_length(label, len);
141 it->func = func;
142 it->base.data = data;
143
144 /* TODO: no view here, but if one desires general contents in the
145 * future... */
146 return it;
147}
148
149static inline void
150_item_free(Elm_Flipselector_Item *it)
151{
152 eina_stringshare_del(it->label);
153 elm_widget_item_free(it);
154}
155
156static void
157_del_hook(Evas_Object *obj)
158{
159 Elm_Flipselector_Item *item;
160
161 Widget_Data *wd = elm_widget_data_get(obj);
162 if (!wd) return;
163
164 if (wd->walking) ERR("flipselector deleted while walking.\n");
165
166 EINA_LIST_FREE(wd->items, item)
167 _item_free(item);
168
169 if (wd->spin) ecore_timer_del(wd->spin);
170 free(wd);
171}
172
173static void
174_disable_hook(Evas_Object *obj)
175{
176 Widget_Data *wd = elm_widget_data_get(obj);
177 if (!wd) return;
178
179 if (elm_widget_disabled_get(obj))
180 edje_object_signal_emit(wd->base, "elm,state,disabled", "elm");
181 else
182 edje_object_signal_emit(wd->base, "elm,state,enabled", "elm");
183}
184
185static void
186_theme_hook(Evas_Object *obj)
187{
188 Widget_Data *wd;
189 const char *max_len;
190
191 wd = elm_widget_data_get(obj);
192 if (!wd) return;
193
194 _elm_theme_object_set(obj, wd->base, "flipselector", "base",
195 elm_widget_style_get(obj));
196 edje_object_scale_set(wd->base,
197 elm_widget_scale_get(obj) * _elm_config->scale);
198
199 max_len = edje_object_data_get(wd->base, "max_len");
200 if (!max_len)
201 wd->max_len = MAX_LEN_DEFAULT;
202 else
203 {
204 wd->max_len = atoi(max_len);
205 if (!wd->max_len)
206 wd->max_len = MAX_LEN_DEFAULT;
207 }
208
209 _update_view(obj);
210 _sizing_eval(obj);
211}
212
213static void
214_sentinel_eval(Widget_Data *wd)
215{
216 Elm_Flipselector_Item *it;
217 Eina_List *l;
218
219 if (!wd->items)
220 {
221 wd->sentinel = NULL;
222 return;
223 }
224
225 wd->sentinel = wd->items;
226
227 EINA_LIST_FOREACH(wd->items, l, it)
228 {
229 if (strlen(elm_object_item_text_get((Elm_Object_Item *)it)) >
230 strlen(elm_object_item_text_get(DATA_GET(wd->sentinel))))
231 wd->sentinel = l;
232 }
233}
234
235/* TODO: create a flag to avoid looping here all times */
236static void
237_flipselector_process_deletions(Widget_Data *wd)
238{
239 Elm_Flipselector_Item *it;
240 Eina_List *l;
241 Eina_Bool skip = EINA_TRUE;
242 Eina_Bool sentinel_eval = EINA_FALSE;
243
244 wd->walking++; /* avoid nested deletions */
245
246 EINA_LIST_FOREACH(wd->items, l, it)
247 {
248 if (!it->deleted) continue;
249
250 if (wd->current == l)
251 {
252 if (wd->current == wd->sentinel)
253 sentinel_eval = EINA_TRUE;
254 wd->current = eina_list_prev(wd->current);
255 }
256 wd->items = eina_list_remove(wd->items, it);
257
258 if (!wd->current)
259 wd->current = wd->items;
260
261 _item_free(it);
262 skip = EINA_FALSE;
263
264 if (eina_list_count(wd->items) <= 1)
265 edje_object_signal_emit(wd->base, "elm,state,button,hidden", "elm");
266 else
267 edje_object_signal_emit(wd->base, "elm,state,button,visible", "elm");
268 }
269
270 if (!skip)
271 _update_view(wd->self);
272
273 if (sentinel_eval)
274 _sentinel_eval(wd);
275
276 wd->walking--;
277}
278
279static inline void
280_flipselector_walk(Widget_Data *wd)
281{
282 if (wd->walking < 0)
283 {
284 ERR("walking was negative. fixed!\n");
285 wd->walking = 0;
286 }
287 wd->walking++;
288}
289
290static inline void
291_flipselector_unwalk(Widget_Data *wd)
292{
293 wd->walking--;
294 if (wd->walking < 0)
295 {
296 ERR("walking became negative. fixed!\n");
297 wd->walking = 0;
298 }
299 if (wd->walking) return;
300
301 _flipselector_process_deletions(wd);
302}
303
304static Eina_Bool
305_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
306{
307 Evas_Event_Key_Down *ev;
308 Widget_Data *wd;
309 Eina_Bool is_up = EINA_TRUE;
310
311 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
312
313 wd = elm_widget_data_get(obj);
314 if (!wd) return EINA_FALSE;
315
316 ev = event_info;
317 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
318
319 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
320
321 if ((!strcmp(ev->keyname, "Down")) || (!strcmp(ev->keyname, "KP_Down")))
322 is_up = EINA_FALSE;
323 else if ((strcmp(ev->keyname, "Up")) && (strcmp(ev->keyname, "KP_Up")))
324 return EINA_FALSE;
325
326 if (wd->spin) ecore_timer_del(wd->spin);
327 wd->spin = NULL;
328
329 /* TODO: if direction setting via API is not coming in, replace
330 these calls by flip_{next,prev} */
331 _flipselector_walk(wd);
332 if (is_up) _flip_up(wd);
333 else _flip_down(wd);
334 _flipselector_unwalk(wd);
335
336 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
337 return EINA_TRUE;
338}
339
340static void
341_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
342{
343 Widget_Data *wd = elm_widget_data_get(obj);
344 if (!wd) return;
345
346 /* FIXME: no treatment of this signal so far */
347 if (elm_widget_focus_get(obj))
348 {
349 edje_object_signal_emit(wd->base, "elm,action,focus", "elm");
350 evas_object_focus_set(wd->base, EINA_TRUE);
351 }
352 else
353 {
354 edje_object_signal_emit(wd->base, "elm,action,unfocus", "elm");
355 evas_object_focus_set(wd->base, EINA_FALSE);
356 }
357}
358
359static void
360_sizing_eval(Evas_Object *obj)
361{
362 Widget_Data *wd;
363 const char *tmp = NULL;
364 Evas_Coord minw = -1, minh = -1, w, h;
365
366 wd = elm_widget_data_get(obj);
367 if (!wd) return;
368
369 elm_coords_finger_size_adjust(1, &minw, 2, &minh);
370
371 if (wd->sentinel)
372 {
373 const char *label = elm_object_item_text_get(DATA_GET(wd->sentinel));
374 tmp = edje_object_part_text_get(wd->base, "elm.top");
375 edje_object_part_text_escaped_set(wd->base, "elm.top", label);
376 }
377
378 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
379 elm_coords_finger_size_adjust(1, &minw, 2, &minh);
380 evas_object_size_hint_min_get(obj, &w, &h);
381
382 if (wd->sentinel) edje_object_part_text_escaped_set(wd->base, "elm.top", tmp);
383
384 if (w > minw) minw = w;
385 if (h > minh) minh = h;
386
387 evas_object_size_hint_min_set(obj, minw, minh);
388}
389
390static void
391_update_view(Evas_Object *obj)
392{
393 Widget_Data *wd;
394 const char *label;
395 Elm_Flipselector_Item *item;
396
397 wd = elm_widget_data_get(obj);
398 if (!wd) return;
399
400 label = NULL;
401 item = DATA_GET(wd->current);
402 if (item) label = item->label;
403
404 edje_object_part_text_escaped_set(wd->base, "elm.top", label ? label : "");
405 edje_object_part_text_escaped_set(wd->base, "elm.bottom", label ? label : "");
406 edje_object_message_signal_process(wd->base);
407}
408
409static void
410_changed(Widget_Data *wd)
411{
412 Elm_Flipselector_Item *item;
413
414 item = DATA_GET(wd->current);
415 if (!item) return;
416
417 if (item->func)
418 item->func((void *)item->base.data, WIDGET(item), item);
419 if (!item->deleted)
420 evas_object_smart_callback_call(wd->self, SIG_SELECTED, item);
421}
422
423static void
424_send_msg(Widget_Data *wd, int flipside, char *label)
425{
426 Edje_Message_String msg;
427
428 msg.str = label;
429 edje_object_message_send(wd->base, EDJE_MESSAGE_STRING, flipside, &msg);
430 edje_object_message_signal_process(wd->base);
431
432 _changed(wd);
433}
434
435static void
436_flip_up(Widget_Data *wd)
437{
438 Elm_Flipselector_Item *item;
439
440 if (!wd->current) return;
441
442 if (wd->current == wd->items)
443 {
444 wd->current = eina_list_last(wd->items);
445 evas_object_smart_callback_call(wd->self, SIG_UNDERFLOWED, NULL);
446 }
447 else
448 wd->current = eina_list_prev(wd->current);
449
450 item = DATA_GET(wd->current);
451 if (!item) return;
452
453 _send_msg(wd, MSG_FLIP_UP, (char *)item->label);
454}
455
456static Eina_Bool
457_signal_val_up(void *data)
458{
459 Widget_Data *wd = elm_widget_data_get(data);
460
461 if (!wd) goto val_up_exit_on_error;
462
463 _flipselector_walk(wd);
464
465 if (wd->interval > FLIP_MIN_INTERVAL)
466 wd->interval = wd->interval / 1.05;
467
468 ecore_timer_interval_set(wd->spin, wd->interval);
469
470 _flip_up(wd);
471
472 _flipselector_unwalk(wd);
473
474 return ECORE_CALLBACK_RENEW;
475
476val_up_exit_on_error:
477 return ECORE_CALLBACK_CANCEL;
478}
479
480static void
481_signal_val_up_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
482{
483 Widget_Data *wd = elm_widget_data_get(data);
484 if (!wd) return;
485
486 wd->interval = wd->first_interval;
487
488 if (wd->spin) ecore_timer_del(wd->spin);
489 wd->spin = ecore_timer_add(wd->interval, _signal_val_up, data);
490
491 _signal_val_up(data);
492}
493
494static void
495_flip_down(Widget_Data *wd)
496{
497 Elm_Flipselector_Item *item;
498
499 if (!wd->current) return;
500
501 wd->current = eina_list_next(wd->current);
502 if (!wd->current)
503 {
504 wd->current = wd->items;
505 evas_object_smart_callback_call(wd->self, SIG_OVERFLOWED, NULL);
506 }
507
508 item = DATA_GET(wd->current);
509 if (!item) return;
510
511 _send_msg(wd, MSG_FLIP_DOWN, (char *)item->label);
512}
513
514static Eina_Bool
515_signal_val_down(void *data)
516{
517 Widget_Data *wd = elm_widget_data_get(data);
518
519 if (!wd) goto val_down_exit_on_error;
520
521 _flipselector_walk(wd);
522
523 if (wd->interval > FLIP_MIN_INTERVAL)
524 wd->interval = wd->interval / 1.05;
525 ecore_timer_interval_set(wd->spin, wd->interval);
526
527 _flip_down(wd);
528
529 _flipselector_unwalk(wd);
530
531 return ECORE_CALLBACK_RENEW;
532
533val_down_exit_on_error:
534 return ECORE_CALLBACK_CANCEL;
535}
536
537static void
538_signal_val_down_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
539{
540 Widget_Data *wd = elm_widget_data_get(data);
541 if (!wd) return;
542
543 wd->interval = wd->first_interval;
544
545 if (wd->spin) ecore_timer_del(wd->spin);
546 wd->spin = ecore_timer_add(wd->interval, _signal_val_down, data);
547
548 _signal_val_down(data);
549}
550
551static void
552_signal_val_change_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
553{
554 Widget_Data *wd = elm_widget_data_get(data);
555 if (!wd) return;
556
557 if (wd->spin) ecore_timer_del(wd->spin);
558 wd->spin = NULL;
559}
560
561static void
562_callbacks_set(Evas_Object *obj)
563{
564 Widget_Data *wd = elm_widget_data_get(obj);
565
566 edje_object_signal_callback_add(wd->base, "elm,action,up,start",
567 "", _signal_val_up_start, obj);
568 edje_object_signal_callback_add(wd->base, "elm,action,up,stop",
569 "", _signal_val_change_stop, obj);
570 edje_object_signal_callback_add(wd->base, "elm,action,down,start",
571 "", _signal_val_down_start, obj);
572 edje_object_signal_callback_add(wd->base, "elm,action,down,stop",
573 "", _signal_val_change_stop, obj);
574}
575
576static Eina_Bool
577_item_del_pre_hook(Elm_Object_Item *it)
578{
579 Widget_Data *wd;
580 Elm_Flipselector_Item *item, *item2;
581 Eina_List *l;
582
583 item = (Elm_Flipselector_Item *)it;
584 wd = elm_widget_data_get(WIDGET(item));
585 if (!wd) return EINA_FALSE;
586
587 if (wd->walking > 0)
588 {
589 item->deleted = EINA_TRUE;
590 return EINA_FALSE;
591 }
592
593 _flipselector_walk(wd);
594
595 EINA_LIST_FOREACH(wd->items, l, item2)
596 {
597 if (item2 == item)
598 {
599 wd->items = eina_list_remove_list(wd->items, l);
600 if (wd->current == l)
601 {
602 wd->current = l->prev;
603 if (!wd->current) wd->current = l->next;
604 if (wd->current)
605 {
606 item2 = wd->current->data;
607 _send_msg(wd, MSG_FLIP_DOWN, (char *)item2->label);
608 }
609 else
610 _send_msg(wd, MSG_FLIP_DOWN, "");
611 }
612 break;
613 }
614 }
615 eina_stringshare_del(item->label);
616 _sentinel_eval(wd);
617 _flipselector_unwalk(wd);
618
619 return EINA_TRUE;
620}
621
622EAPI Evas_Object *
623elm_flipselector_add(Evas_Object *parent)
624{
625 Evas_Object *obj;
626 Evas *e;
627 Widget_Data *wd;
628
629 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
630
631 ELM_SET_WIDTYPE(widtype, "flipselector");
632 elm_widget_type_set(obj, "flipselector");
633 elm_widget_sub_object_add(parent, obj);
634 elm_widget_data_set(obj, wd);
635
636 wd->self = obj;
637 elm_widget_del_hook_set(obj, _del_hook);
638 elm_widget_theme_hook_set(obj, _theme_hook);
639 elm_widget_disable_hook_set(obj, _disable_hook);
640
641 elm_widget_can_focus_set(obj, EINA_TRUE);
642 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
643 elm_widget_event_hook_set(obj, _event_hook);
644
645 wd->base = edje_object_add(e);
646 elm_widget_resize_object_set(obj, wd->base);
647
648 _callbacks_set(obj);
649
650 wd->first_interval = FLIP_FIRST_INTERVAL;
651
652 _theme_hook(obj);
653
654 evas_object_smart_callbacks_descriptions_set(obj, _signals);
655 return obj;
656}
657
658EAPI void
659elm_flipselector_flip_next(Evas_Object *obj)
660{
661 ELM_CHECK_WIDTYPE(obj, widtype);
662
663 Widget_Data *wd = elm_widget_data_get(obj);
664 if (!wd) return;
665
666 if (wd->spin) ecore_timer_del(wd->spin);
667 wd->spin = NULL;
668
669 _flipselector_walk(wd);
670 _flip_down(wd);
671 _flipselector_unwalk(wd);
672}
673
674EAPI void
675elm_flipselector_flip_prev(Evas_Object *obj)
676{
677 ELM_CHECK_WIDTYPE(obj, widtype);
678
679 Widget_Data *wd = elm_widget_data_get(obj);
680 if (!wd) return;
681
682 if (wd->spin) ecore_timer_del(wd->spin);
683 wd->spin = NULL;
684
685 _flipselector_walk(wd);
686 _flip_up(wd);
687 _flipselector_unwalk(wd);
688}
689
690EAPI Elm_Object_Item *
691elm_flipselector_item_append(Evas_Object *obj, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), void *data)
692{
693 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
694
695 Elm_Flipselector_Item *item;
696 Widget_Data *wd;
697
698 wd = elm_widget_data_get(obj);
699 if (!wd) return NULL;
700
701 item = _item_new(obj, label, func, data);
702 if (!item) return NULL;
703
704 wd->items = eina_list_append(wd->items, item);
705 if (!wd->current)
706 {
707 wd->current = wd->items;
708 _update_view(obj);
709 }
710
711 if (!wd->sentinel ||
712 (strlen(elm_object_item_text_get((Elm_Object_Item *)item)) >
713 strlen(elm_object_item_text_get(DATA_GET(wd->sentinel)))))
714 {
715 wd->sentinel = eina_list_last(wd->items);
716 _sizing_eval(obj);
717 }
718
719 if (eina_list_count(wd->items) >= 2)
720 edje_object_signal_emit(wd->base, "elm,state,button,visible", "elm");
721
722 return (Elm_Object_Item *)item;
723}
724
725EAPI Elm_Object_Item *
726elm_flipselector_item_prepend(Evas_Object *obj, const char *label, void (*func)(void *data, Evas_Object *obj, void *event_info), void *data)
727{
728 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
729
730 Elm_Flipselector_Item *item;
731 Widget_Data *wd;
732
733 wd = elm_widget_data_get(obj);
734 if (!wd) return NULL;
735
736 item = _item_new(obj, label, func, data);
737 if (!item) return NULL;
738
739 wd->items = eina_list_prepend(wd->items, item);
740 if (!wd->current)
741 {
742 wd->current = wd->items;
743 _update_view(obj);
744 }
745
746 if (!wd->sentinel ||
747 (strlen(elm_object_item_text_get((Elm_Object_Item *)item)) >
748 strlen(elm_object_item_text_get(DATA_GET(wd->sentinel)))))
749 {
750 wd->sentinel = wd->items;
751 _sizing_eval(obj);
752 }
753
754 if (eina_list_count(wd->items) >= 2)
755 edje_object_signal_emit(wd->base, "elm,state,button,visible", "elm");
756
757 return (Elm_Object_Item *)item;
758}
759
760EAPI const Eina_List *
761elm_flipselector_items_get(const Evas_Object *obj)
762{
763 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
764
765 Widget_Data *wd = elm_widget_data_get(obj);
766 if (!wd) return NULL;
767 return wd->items;
768}
769
770EAPI Elm_Object_Item *
771elm_flipselector_first_item_get(const Evas_Object *obj)
772{
773 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
774
775 Elm_Flipselector_Item *it;
776 Widget_Data *wd;
777 Eina_List *l;
778
779 wd = elm_widget_data_get(obj);
780 if (!wd || !wd->items) return NULL;
781
782 EINA_LIST_FOREACH(wd->items, l, it)
783 {
784 if (it->deleted) continue;
785 return (Elm_Object_Item *)it;
786 }
787 return NULL;
788}
789
790EAPI Elm_Object_Item *
791elm_flipselector_last_item_get(const Evas_Object *obj)
792{
793 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
794
795 Elm_Flipselector_Item *it;
796 Widget_Data *wd;
797 Eina_List *l;
798
799 wd = elm_widget_data_get(obj);
800 if (!wd || !wd->items) return NULL;
801
802 EINA_LIST_REVERSE_FOREACH(wd->items, l, it)
803 {
804 if (it->deleted) continue;
805 return (Elm_Object_Item *)it;
806 }
807 return NULL;
808}
809
810EAPI Elm_Object_Item *
811elm_flipselector_selected_item_get(const Evas_Object *obj)
812{
813 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
814
815 Widget_Data *wd = elm_widget_data_get(obj);
816 if (!wd) return NULL;
817 return DATA_GET(wd->current);
818}
819
820EAPI void
821elm_flipselector_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
822{
823 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
824
825 Elm_Flipselector_Item *item, *_item, *cur;
826 int flipside = MSG_FLIP_UP;
827 Widget_Data *wd;
828 Eina_List *l;
829
830 item = (Elm_Flipselector_Item *)it;
831 wd = elm_widget_data_get(WIDGET(item));
832 if (!wd) return;
833
834 cur = DATA_GET(wd->current);
835 if ((selected) && (cur == item)) return;
836
837 _flipselector_walk(wd);
838
839 if ((!selected) && (cur == item))
840 {
841 EINA_LIST_FOREACH(wd->items, l, _item)
842 {
843 if (!_item->deleted)
844 {
845 wd->current = l;
846 _send_msg(wd, MSG_FLIP_UP, (char *)_item->label);
847 break;
848 }
849 }
850 _flipselector_unwalk(wd);
851 return;
852 }
853
854 EINA_LIST_FOREACH(wd->items, l, _item)
855 {
856 if (_item == cur) flipside = MSG_FLIP_DOWN;
857
858 if (_item == item)
859 {
860 wd->current = l;
861 _send_msg(wd, flipside, (char *)item->label);
862 break;
863 }
864 }
865
866 _flipselector_unwalk(wd);
867}
868
869EAPI Eina_Bool
870elm_flipselector_item_selected_get(const Elm_Object_Item *it)
871{
872 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
873 Widget_Data *wd;
874 Elm_Flipselector_Item *item;
875
876 item = (Elm_Flipselector_Item *)it;
877 wd = elm_widget_data_get(WIDGET(item));
878 if (!wd) return EINA_FALSE;
879 return (eina_list_data_get(wd->current) == item);
880}
881
882EAPI Elm_Object_Item *
883elm_flipselector_item_prev_get(const Elm_Object_Item *it)
884{
885 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
886
887 Widget_Data *wd;
888 Eina_List *l;
889 Elm_Flipselector_Item *item = (Elm_Flipselector_Item *)it;
890
891 wd = elm_widget_data_get(WIDGET(item));
892 if ((!wd) || (!wd->items)) return NULL;
893
894 l = eina_list_data_find_list(wd->items, it);
895 if (l && l->prev) return DATA_GET(l->prev);
896
897 return NULL;
898}
899
900EAPI Elm_Object_Item *
901elm_flipselector_item_next_get(const Elm_Object_Item *it)
902{
903 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
904
905 Widget_Data *wd;
906 Eina_List *l;
907 Elm_Flipselector_Item *item = (Elm_Flipselector_Item *)it;
908
909 wd = elm_widget_data_get(WIDGET(item));
910 if ((!wd) || (!wd->items)) return NULL;
911
912 l = eina_list_data_find_list(wd->items, it);
913 if (l && l->next) return DATA_GET(l->next);
914
915 return NULL;
916}
917
918EAPI void
919elm_flipselector_first_interval_set(Evas_Object *obj, double interval)
920{
921 ELM_CHECK_WIDTYPE(obj, widtype);
922
923 Widget_Data *wd = elm_widget_data_get(obj);
924 if (!wd) return;
925 wd->first_interval = interval;
926}
927
928EAPI double
929elm_flipselector_first_interval_get(const Evas_Object *obj)
930{
931 ELM_CHECK_WIDTYPE(obj, widtype) 0;
932
933 Widget_Data *wd = elm_widget_data_get(obj);
934 if (!wd) return 0;
935 return wd->first_interval;
936}
diff --git a/libraries/elementary/src/lib/elm_flipselector.h b/libraries/elementary/src/lib/elm_flipselector.h
new file mode 100644
index 0000000..bdc52df
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_flipselector.h
@@ -0,0 +1,310 @@
1/**
2 * @defgroup Flipselector Flip Selector
3 * @ingroup Elementary
4 *
5 * @image html img/widget/flipselector/preview-00.png
6 * @image latex img/widget/flipselector/preview-00.eps
7 *
8 * A flip selector is a widget to show a set of @b text items, one
9 * at a time, with the same sheet switching style as the @ref Clock
10 * "clock" widget, when one changes the current displaying sheet
11 * (thus, the "flip" in the name).
12 *
13 * User clicks to flip sheets which are @b held for some time will
14 * make the flip selector to flip continuously and automatically for
15 * the user. The interval between flips will keep growing in time,
16 * so that it helps the user to reach an item which is distant from
17 * the current selection.
18 *
19 * Smart callbacks one can register to:
20 * - @c "selected" - when the widget's selected text item is changed
21 * - @c "overflowed" - when the widget's current selection is changed
22 * from the first item in its list to the last
23 * - @c "underflowed" - when the widget's current selection is changed
24 * from the last item in its list to the first
25 *
26 * Available styles for it:
27 * - @c "default"
28 *
29 * Default text parts of the flipselector items that you can use for are:
30 * @li "default" - label of the flipselector item
31 *
32 * Supported elm_object common APIs.
33 * @li @ref elm_object_disabled_set
34 * @li @ref elm_object_disabled_get
35 *
36 * Supported elm_object_item common APIs.
37 * @li @ref elm_object_item_text_set
38 * @li @ref elm_object_item_part_text_set
39 * @li @ref elm_object_item_signal_emit
40 *
41 * Here is an example on its usage:
42 * @li @ref flipselector_example
43 */
44
45/**
46 * @addtogroup Flipselector
47 * @{
48 */
49
50/**
51 * Add a new flip selector widget to the given parent Elementary
52 * (container) widget
53 *
54 * @param parent The parent object
55 * @return a new flip selector widget handle or @c NULL, on errors
56 *
57 * This function inserts a new flip selector widget on the canvas.
58 *
59 * @ingroup Flipselector
60 */
61EAPI Evas_Object *elm_flipselector_add(Evas_Object *parent);
62
63/**
64 * Programmatically select the next item of a flip selector widget
65 *
66 * @param obj The flipselector object
67 *
68 * @note The selection will be animated. Also, if it reaches the
69 * end of its list of member items, it will continue with the first
70 * one onwards.
71 *
72 * @ingroup Flipselector
73 */
74EAPI void elm_flipselector_flip_next(Evas_Object *obj);
75
76/**
77 * Programmatically select the previous item of a flip selector
78 * widget
79 *
80 * @param obj The flipselector object
81 *
82 * @note The selection will be animated. Also, if it reaches the
83 * beginning of its list of member items, it will continue with the
84 * last one backwards.
85 *
86 * @ingroup Flipselector
87 */
88EAPI void elm_flipselector_flip_prev(Evas_Object *obj);
89
90/**
91 * Append a (text) item to a flip selector widget
92 *
93 * @param obj The flipselector object
94 * @param label The (text) label of the new item
95 * @param func Convenience callback function to take place when
96 * item is selected
97 * @param data Data passed to @p func, above
98 * @return A handle to the item added or @c NULL, on errors
99 *
100 * The widget's list of labels to show will be appended with the
101 * given value. If the user wishes so, a callback function pointer
102 * can be passed, which will get called when this same item is
103 * selected.
104 *
105 * @note The current selection @b won't be modified by appending an
106 * element to the list.
107 *
108 * @note The maximum length of the text label is going to be
109 * determined <b>by the widget's theme</b>. Strings larger than
110 * that value are going to be @b truncated.
111 *
112 * @ingroup Flipselector
113 */
114EAPI Elm_Object_Item *elm_flipselector_item_append(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data);
115
116/**
117 * Prepend a (text) item to a flip selector widget
118 *
119 * @param obj The flipselector object
120 * @param label The (text) label of the new item
121 * @param func Convenience callback function to take place when
122 * item is selected
123 * @param data Data passed to @p func, above
124 * @return A handle to the item added or @c NULL, on errors
125 *
126 * The widget's list of labels to show will be prepended with the
127 * given value. If the user wishes so, a callback function pointer
128 * can be passed, which will get called when this same item is
129 * selected.
130 *
131 * @note The current selection @b won't be modified by prepending
132 * an element to the list.
133 *
134 * @note The maximum length of the text label is going to be
135 * determined <b>by the widget's theme</b>. Strings larger than
136 * that value are going to be @b truncated.
137 *
138 * @ingroup Flipselector
139 */
140EAPI Elm_Object_Item *elm_flipselector_item_prepend(Evas_Object *obj, const char *label, Evas_Smart_Cb func, void *data);
141
142/**
143 * Get the internal list of items in a given flip selector widget.
144 *
145 * @param obj The flipselector object
146 * @return The list of items (#Elm_Object_Item as data) or
147 * @c NULL on errors.
148 *
149 * This list is @b not to be modified in any way and must not be
150 * freed. Use the list members with functions like
151 * elm_object_item_text_set(),
152 * elm_object_item_text_get(),
153 * elm_object_item_del(),
154 * elm_flipselector_item_selected_get(),
155 * elm_flipselector_item_selected_set().
156 *
157 * @warning This list is only valid until @p obj object's internal
158 * items list is changed. It should be fetched again with another
159 * call to this function when changes happen.
160 *
161 * @ingroup Flipselector
162 */
163EAPI const Eina_List *elm_flipselector_items_get(const Evas_Object *obj);
164
165/**
166 * Get the first item in the given flip selector widget's list of
167 * items.
168 *
169 * @param obj The flipselector object
170 * @return The first item or @c NULL, if it has no items (and on
171 * errors)
172 *
173 * @see elm_flipselector_item_append()
174 * @see elm_flipselector_last_item_get()
175 *
176 * @ingroup Flipselector
177 */
178EAPI Elm_Object_Item *elm_flipselector_first_item_get(const Evas_Object *obj);
179
180/**
181 * Get the last item in the given flip selector widget's list of
182 * items.
183 *
184 * @param obj The flipselector object
185 * @return The last item or @c NULL, if it has no items (and on
186 * errors)
187 *
188 * @see elm_flipselector_item_prepend()
189 * @see elm_flipselector_first_item_get()
190 *
191 * @ingroup Flipselector
192 */
193EAPI Elm_Object_Item *elm_flipselector_last_item_get(const Evas_Object *obj);
194
195/**
196 * Get the currently selected item in a flip selector widget.
197 *
198 * @param obj The flipselector object
199 * @return The selected item or @c NULL, if the widget has no items
200 * (and on errors)
201 *
202 * @ingroup Flipselector
203 */
204EAPI Elm_Object_Item *elm_flipselector_selected_item_get(const Evas_Object *obj);
205
206/**
207 * Set whether a given flip selector widget's item should be the
208 * currently selected one.
209 *
210 * @param it The flip selector item
211 * @param selected @c EINA_TRUE to select it, @c EINA_FALSE to unselect.
212 *
213 * This sets whether @p item is or not the selected (thus, under
214 * display) one. If @p item is different than the one under display,
215 * the latter will be unselected. If the @p item is set to be
216 * unselected, on the other hand, the @b first item in the widget's
217 * internal members list will be the new selected one.
218 *
219 * @see elm_flipselector_item_selected_get()
220 *
221 * @ingroup Flipselector
222 */
223EAPI void elm_flipselector_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
224
225/**
226 * Get whether a given flip selector widget's item is the currently
227 * selected one.
228 *
229 * @param it The flip selector item
230 * @return @c EINA_TRUE, if it's selected, @c EINA_FALSE otherwise
231 * (or on errors).
232 *
233 * @see elm_flipselector_item_selected_set()
234 *
235 * @ingroup Flipselector
236 */
237EAPI Eina_Bool elm_flipselector_item_selected_get(const Elm_Object_Item *it);
238
239/**
240 * Gets the item before @p item in a flip selector widget's internal list of
241 * items.
242 *
243 * @param it The item to fetch previous from
244 * @return The item before the @p item, in its parent's list. If there is no
245 * previous item for @p item or there's an error, @c NULL is returned.
246 *
247 * @see elm_flipselector_item_next_get()
248 *
249 * @ingroup Flipselector
250 */
251EAPI Elm_Object_Item *elm_flipselector_item_prev_get(const Elm_Object_Item *it);
252
253/**
254 * Gets the item after @p item in a flip selector widget's
255 * internal list of items.
256 *
257 * @param it The item to fetch next from
258 * @return The item after the @p item, in its parent's list. If there is no next
259 * item for @p item or there's an error, @c NULL is returned.
260 *
261 * @see elm_flipselector_item_prev_get()
262 *
263 * @ingroup Flipselector
264 */
265EAPI Elm_Object_Item *elm_flipselector_item_next_get(const Elm_Object_Item *it);
266
267/**
268 * Set the interval on time updates for a user mouse button hold
269 * on a flip selector widget.
270 *
271 * @param obj The flip selector object
272 * @param interval The (first) interval value in seconds
273 *
274 * This interval value is @b decreased while the user holds the
275 * mouse pointer either flipping up or flipping down a given flip
276 * selector.
277 *
278 * This helps the user to get to a given item distant from the
279 * current one easier/faster, as it will start to flip quicker and
280 * quicker on mouse button holds.
281 *
282 * The calculation for the next flip interval value, starting from
283 * the one set with this call, is the previous interval divided by
284 * 1.05, so it decreases a little bit.
285 *
286 * The default starting interval value for automatic flips is
287 * @b 0.85 seconds.
288 *
289 * @see elm_flipselector_first_interval_get()
290 *
291 * @ingroup Flipselector
292 */
293EAPI void elm_flipselector_first_interval_set(Evas_Object *obj, double interval);
294
295/**
296 * Get the interval on time updates for an user mouse button hold
297 * on a flip selector widget.
298 *
299 * @param obj The flip selector object
300 * @return The (first) interval value, in seconds, set on it
301 *
302 * @see elm_flipselector_first_interval_set() for more details
303 *
304 * @ingroup Flipselector
305 */
306EAPI double elm_flipselector_first_interval_get(const Evas_Object *obj);
307
308/**
309 * @}
310 */
diff --git a/libraries/elementary/src/lib/elm_focus.h b/libraries/elementary/src/lib/elm_focus.h
new file mode 100644
index 0000000..59fc97c
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_focus.h
@@ -0,0 +1,214 @@
1/**
2 * @defgroup Focus Focus
3 * @ingroup Elementary
4 *
5 * An Elementary application has, at all times, one (and only one)
6 * @b focused object. This is what determines where the input
7 * events go to within the application's window. Also, focused
8 * objects can be decorated differently, in order to signal to the
9 * user where the input is, at a given moment.
10 *
11 * Elementary applications also have the concept of <b>focus
12 * chain</b>: one can cycle through all the windows' focusable
13 * objects by input (tab key) or programmatically. The default
14 * focus chain for an application is the one define by the order in
15 * which the widgets where added in code. One will cycle through
16 * top level widgets, and, for each one containing sub-objects, cycle
17 * through them all, before returning to the level
18 * above. Elementary also allows one to set @b custom focus chains
19 * for their applications.
20 *
21 * Besides the focused decoration a widget may exhibit, when it
22 * gets focus, Elementary has a @b global focus highlight object
23 * that can be enabled for a window. If one chooses to do so, this
24 * extra highlight effect will surround the current focused object,
25 * too.
26 *
27 * @note Some Elementary widgets are @b unfocusable, after
28 * creation, by their very nature: they are not meant to be
29 * interacted with input events, but are there just for visual
30 * purposes.
31 *
32 * @ref general_functions_example_page "This" example contemplates
33 * some of these functions.
34 */
35
36/**
37 * Get the whether an Elementary object has the focus or not.
38 *
39 * @param obj The Elementary object to get the information from
40 * @return @c EINA_TRUE, if the object is focused, @c EINA_FALSE if
41 * not (and on errors).
42 *
43 * @see elm_object_focus_set()
44 *
45 * @ingroup Focus
46 */
47EAPI Eina_Bool elm_object_focus_get(const Evas_Object *obj);
48
49/**
50 * Set/unset focus to a given Elementary object.
51 *
52 * @param obj The Elementary object to operate on.
53 * @param focus @c EINA_TRUE Set focus to a given object,
54 * @c EINA_FALSE Unset focus to a given object.
55 *
56 * @note When you set focus to this object, if it can handle focus, will
57 * take the focus away from the one who had it previously and will, for
58 * now on, be the one receiving input events. Unsetting focus will remove
59 * the focus from @p obj, passing it back to the previous element in the
60 * focus chain list.
61 *
62 * @see elm_object_focus_get(), elm_object_focus_custom_chain_get()
63 *
64 * @ingroup Focus
65 */
66EAPI void elm_object_focus_set(Evas_Object *obj, Eina_Bool focus);
67
68/**
69 * Set the ability for an Elementary object to be focused
70 *
71 * @param obj The Elementary object to operate on
72 * @param enable @c EINA_TRUE if the object can be focused, @c
73 * EINA_FALSE if not (and on errors)
74 *
75 * This sets whether the object @p obj is able to take focus or
76 * not. Unfocusable objects do nothing when programmatically
77 * focused, being the nearest focusable parent object the one
78 * really getting focus. Also, when they receive mouse input, they
79 * will get the event, but not take away the focus from where it
80 * was previously.
81 *
82 * @ingroup Focus
83 */
84EAPI void elm_object_focus_allow_set(Evas_Object *obj, Eina_Bool enable);
85
86/**
87 * Get whether an Elementary object is focusable or not
88 *
89 * @param obj The Elementary object to operate on
90 * @return @c EINA_TRUE if the object is allowed to be focused, @c
91 * EINA_FALSE if not (and on errors)
92 *
93 * @note Objects which are meant to be interacted with by input
94 * events are created able to be focused, by default. All the
95 * others are not.
96 *
97 * @ingroup Focus
98 */
99EAPI Eina_Bool elm_object_focus_allow_get(const Evas_Object *obj);
100
101/**
102 * Set custom focus chain.
103 *
104 * This function overwrites any previous custom focus chain within
105 * the list of objects. The previous list will be deleted and this list
106 * will be managed by elementary. After it is set, don't modify it.
107 *
108 * @note On focus cycle, only will be evaluated children of this container.
109 *
110 * @param obj The container object
111 * @param objs Chain of objects to pass focus
112 * @ingroup Focus
113 */
114EAPI void elm_object_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs);
115
116/**
117 * Unset a custom focus chain on a given Elementary widget
118 *
119 * @param obj The container object to remove focus chain from
120 *
121 * Any focus chain previously set on @p obj (for its child objects)
122 * is removed entirely after this call.
123 *
124 * @ingroup Focus
125 */
126EAPI void elm_object_focus_custom_chain_unset(Evas_Object *obj);
127
128/**
129 * Get custom focus chain
130 *
131 * @param obj The container object
132 * @ingroup Focus
133 */
134EAPI const Eina_List *elm_object_focus_custom_chain_get(const Evas_Object *obj);
135
136/**
137 * Append object to custom focus chain.
138 *
139 * @note If relative_child equal to NULL or not in custom chain, the object
140 * will be added in end.
141 *
142 * @note On focus cycle, only will be evaluated children of this container.
143 *
144 * @param obj The container object
145 * @param child The child to be added in custom chain
146 * @param relative_child The relative object to position the child
147 * @ingroup Focus
148 */
149EAPI void elm_object_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
150
151/**
152 * Prepend object to custom focus chain.
153 *
154 * @note If relative_child equal to NULL or not in custom chain, the object
155 * will be added in begin.
156 *
157 * @note On focus cycle, only will be evaluated children of this container.
158 *
159 * @param obj The container object
160 * @param child The child to be added in custom chain
161 * @param relative_child The relative object to position the child
162 * @ingroup Focus
163 */
164EAPI void elm_object_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
165
166/**
167 * Give focus to next object in object tree.
168 *
169 * Give focus to next object in focus chain of one object sub-tree.
170 * If the last object of chain already have focus, the focus will go to the
171 * first object of chain.
172 *
173 * @param obj The object root of sub-tree
174 * @param dir Direction to move the focus
175 *
176 * @ingroup Focus
177 */
178EAPI void elm_object_focus_next(Evas_Object *obj, Elm_Focus_Direction dir);
179
180/**
181 * Make the elementary object and its children to be focusable
182 * (or unfocusable).
183 *
184 * @param obj The Elementary object to operate on
185 * @param focusable @c EINA_TRUE for focusable,
186 * @c EINA_FALSE for unfocusable.
187 *
188 * This sets whether the object @p obj and its children objects
189 * are able to take focus or not. If the tree is set as unfocusable,
190 * newest focused object which is not in this tree will get focus.
191 * This API can be helpful for an object to be deleted.
192 * When an object will be deleted soon, it and its children may not
193 * want to get focus (by focus reverting or by other focus controls).
194 * Then, just use this API before deleting.
195 *
196 * @see elm_object_tree_focus_allow_get()
197 *
198 * @ingroup Focus
199 *
200 */
201EAPI void elm_object_tree_focus_allow_set(Evas_Object *obj, Eina_Bool focusable);
202
203/**
204 * Get whether an Elementary object and its children are focusable or not.
205 *
206 * @param obj The Elementary object to get the information from
207 * @return @c EINA_TRUE, if the tree is focusable,
208 * @c EINA_FALSE if not (and on errors).
209 *
210 * @see elm_object_tree_focus_allow_set()
211 *
212 * @ingroup Focus
213 */
214EAPI Eina_Bool elm_object_tree_focus_allow_get(const Evas_Object *obj);
diff --git a/libraries/elementary/src/lib/elm_font.c b/libraries/elementary/src/lib/elm_font.c
new file mode 100644
index 0000000..43e9ebc
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_font.c
@@ -0,0 +1,221 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#include <Elementary.h>
10#include "elm_priv.h"
11
12Elm_Font_Properties *
13_elm_font_properties_get(Eina_Hash **font_hash,
14 const char *font)
15{
16 Elm_Font_Properties *efp = NULL;
17 char *s1;
18
19 s1 = strchr(font, ':');
20 if (s1)
21 {
22 char *s2, *name, *style;
23 int len;
24
25 len = s1 - font;
26 name = calloc(sizeof(char), len + 1);
27 if (!name) return NULL;
28 strncpy(name, font, len);
29
30 /* get subname (should be english) */
31 s2 = strchr(name, ',');
32 if (s2)
33 {
34 len = s2 - name;
35 name = realloc(name, sizeof(char) * len + 1);
36 if (name)
37 {
38 memset(name, 0, sizeof(char) * len + 1);
39 strncpy(name, font, len);
40 }
41 }
42
43 if (!strncmp(s1, ELM_FONT_TOKEN_STYLE, strlen(ELM_FONT_TOKEN_STYLE)))
44 {
45 style = s1 + strlen(ELM_FONT_TOKEN_STYLE);
46
47 if (font_hash) efp = eina_hash_find(*font_hash, name);
48 if (!efp)
49 {
50 efp = calloc(1, sizeof(Elm_Font_Properties));
51 if (efp)
52 {
53 efp->name = eina_stringshare_add(name);
54 if ((font_hash && !*font_hash))
55 {
56 *font_hash = eina_hash_string_superfast_new(NULL);
57 eina_hash_add(*font_hash, name, efp);
58 }
59 }
60 }
61 s2 = strchr(style, ',');
62 if (s2)
63 {
64 char *style_old;
65
66 len = s2 - style;
67 style_old = style;
68 style = calloc(sizeof(char), len + 1);
69 if (style)
70 {
71 strncpy(style, style_old, len);
72 efp->styles = eina_list_append(efp->styles,
73 eina_stringshare_add(style));
74 free(style);
75 }
76 }
77 else
78 efp->styles = eina_list_append(efp->styles,
79 eina_stringshare_add(style));
80 }
81 free(name);
82 }
83 else
84 {
85 if (font_hash) efp = eina_hash_find(*font_hash, font);
86 if (!efp)
87 {
88 efp = calloc(1, sizeof(Elm_Font_Properties));
89 if (efp)
90 {
91 efp->name = eina_stringshare_add(font);
92 if (font_hash && !*font_hash)
93 {
94 *font_hash = eina_hash_string_superfast_new(NULL);
95 eina_hash_add(*font_hash, font, efp);
96 }
97 }
98 }
99 }
100 return efp;
101}
102
103Eina_Hash *
104_elm_font_available_hash_add(Eina_Hash *font_hash,
105 const char *full_name)
106{
107 _elm_font_properties_get(&font_hash, full_name);
108 return font_hash;
109}
110
111static void
112_elm_font_properties_free(Elm_Font_Properties *efp)
113{
114 const char *str;
115
116 EINA_LIST_FREE(efp->styles, str)
117 if (str) eina_stringshare_del(str);
118
119 if (efp->name) eina_stringshare_del(efp->name);
120 free(efp);
121}
122
123static Eina_Bool
124_font_hash_free_cb(const Eina_Hash *hash __UNUSED__, const void *key __UNUSED__, void *data, void *fdata __UNUSED__)
125{
126 Elm_Font_Properties *efp;
127
128 efp = data;
129 _elm_font_properties_free(efp);
130 return EINA_TRUE;
131}
132
133void
134_elm_font_available_hash_del(Eina_Hash *hash)
135{
136 if (!hash) return;
137
138 eina_hash_foreach(hash, _font_hash_free_cb, NULL);
139 eina_hash_free(hash);
140}
141
142EAPI Elm_Font_Properties *
143elm_font_properties_get(const char *font)
144{
145 EINA_SAFETY_ON_NULL_RETURN_VAL(font, NULL);
146 return _elm_font_properties_get(NULL, font);
147}
148
149EAPI void
150elm_font_properties_free(Elm_Font_Properties *efp)
151{
152 const char *str;
153
154 EINA_SAFETY_ON_NULL_RETURN(efp);
155 EINA_LIST_FREE(efp->styles, str)
156 if (str) eina_stringshare_del(str);
157 if (efp->name) eina_stringshare_del(efp->name);
158 free(efp);
159}
160
161EAPI char *
162elm_font_fontconfig_name_get(const char *name,
163 const char *style)
164{
165 char buf[256];
166
167 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
168 if (!style || style[0] == 0) return (char *) eina_stringshare_add(name);
169 snprintf(buf, 256, "%s" ELM_FONT_TOKEN_STYLE "%s", name, style);
170 return (char *) eina_stringshare_add(buf);
171}
172
173EAPI void
174elm_font_fontconfig_name_free(char *name)
175{
176 eina_stringshare_del(name);
177}
178
179EAPI Eina_Hash *
180elm_font_available_hash_add(Eina_List *list)
181{
182 Eina_Hash *font_hash;
183 Eina_List *l;
184 void *key;
185
186 font_hash = NULL;
187
188 /* populate with default font families */
189 //FIXME: Need to check whether fonts are being added multiple times.
190 font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Regular");
191 font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Bold");
192 font_hash = _elm_font_available_hash_add(font_hash, "Sans:style=Oblique");
193 font_hash = _elm_font_available_hash_add(font_hash,
194 "Sans:style=Bold Oblique");
195
196 font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Regular");
197 font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Bold");
198 font_hash = _elm_font_available_hash_add(font_hash, "Serif:style=Oblique");
199 font_hash = _elm_font_available_hash_add(font_hash,
200 "Serif:style=Bold Oblique");
201
202 font_hash = _elm_font_available_hash_add(font_hash,
203 "Monospace:style=Regular");
204 font_hash = _elm_font_available_hash_add(font_hash,
205 "Monospace:style=Bold");
206 font_hash = _elm_font_available_hash_add(font_hash,
207 "Monospace:style=Oblique");
208 font_hash = _elm_font_available_hash_add(font_hash,
209 "Monospace:style=Bold Oblique");
210
211 EINA_LIST_FOREACH(list, l, key)
212 if (key) _elm_font_available_hash_add(font_hash, key);
213
214 return font_hash;
215}
216
217EAPI void
218elm_font_available_hash_del(Eina_Hash *hash)
219{
220 _elm_font_available_hash_del(hash);
221}
diff --git a/libraries/elementary/src/lib/elm_font.h b/libraries/elementary/src/lib/elm_font.h
new file mode 100644
index 0000000..cf21df7
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_font.h
@@ -0,0 +1,99 @@
1/**
2 * @defgroup Fonts Elementary Fonts
3 * @ingroup Elementary
4 *
5 * These are functions dealing with font rendering, selection and the
6 * like for Elementary applications. One might fetch which system
7 * fonts are there to use and set custom fonts for individual classes
8 * of UI items containing text (text classes).
9 *
10 * @{
11 */
12
13typedef struct _Elm_Font_Properties
14{
15 const char *name;
16 Eina_List *styles;
17} Elm_Font_Properties;
18
19/**
20 * Translate a font (family) name string in fontconfig's font names
21 * syntax into an @c Elm_Font_Properties struct.
22 *
23 * @param font The font name and styles string
24 * @return the font properties struct
25 *
26 * @ingroup Fonts
27 *
28 * @note The reverse translation can be achieved with
29 * elm_font_fontconfig_name_get(), for one style only (single font
30 * instance, not family).
31 */
32EAPI Elm_Font_Properties *elm_font_properties_get(const char *font);
33
34/**
35 * Free font properties return by elm_font_properties_get().
36 *
37 * @param efp the font properties struct
38 *
39 * @ingroup Fonts
40 */
41EAPI void elm_font_properties_free(Elm_Font_Properties *efp);
42
43/**
44 * Translate a font name, bound to a style, into fontconfig's font names
45 * syntax.
46 *
47 * @param name The font (family) name
48 * @param style The given style (may be @c NULL)
49 *
50 * @return the font name and style string
51 *
52 * @ingroup Fonts
53 *
54 * @note The reverse translation can be achieved with
55 * elm_font_properties_get(), for one style only (single font
56 * instance, not family).
57 */
58EAPI char *elm_font_fontconfig_name_get(const char *name, const char *style);
59
60/**
61 * Free the font string return by elm_font_fontconfig_name_get().
62 *
63 * @param name the font properties struct
64 *
65 * @ingroup Fonts
66 */
67EAPI void elm_font_fontconfig_name_free(char *name);
68
69/**
70 * Create a font hash table of available system fonts.
71 *
72 * One must call it with @p list being the return value of
73 * evas_font_available_list(). The hash will be indexed by font
74 * (family) names, being its values @c Elm_Font_Properties blobs.
75 *
76 * @param list The list of available system fonts, as returned by
77 * evas_font_available_list().
78 * @return the font hash.
79 *
80 * @ingroup Fonts
81 *
82 * @note The user is supposed to get it populated at least with 3
83 * default font families (Sans, Serif, Monospace), which should be
84 * present on most systems.
85 */
86EAPI Eina_Hash *elm_font_available_hash_add(Eina_List *list);
87
88/**
89 * Free the hash returned by elm_font_available_hash_add().
90 *
91 * @param hash the hash to be freed.
92 *
93 * @ingroup Fonts
94 */
95EAPI void elm_font_available_hash_del(Eina_Hash *hash);
96
97/**
98 * @}
99 */
diff --git a/libraries/elementary/src/lib/elm_frame.c b/libraries/elementary/src/lib/elm_frame.c
new file mode 100644
index 0000000..0d32c16
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_frame.c
@@ -0,0 +1,325 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *frm;
9 Evas_Object *content;
10 const char *label;
11 unsigned int recalc_count;
12 Eina_Bool collapsed : 1;
13 Eina_Bool collapsible : 1;
14 Eina_Bool anim : 1;
15};
16
17static const char SIG_CLICKED[] = "clicked";
18
19static const Evas_Smart_Cb_Description _signals[] = {
20 {SIG_CLICKED, ""},
21 {NULL, NULL}
22};
23
24static const char *widtype = NULL;
25static void _del_hook(Evas_Object *obj);
26static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
27static void _theme_hook(Evas_Object *obj);
28static void _sizing_eval(Evas_Object *obj);
29static void _changed_size_hints(void *data,
30 Evas *e, Evas_Object *obj,
31 void *event_info);
32static void _sub_del(void *data, Evas_Object *obj, void *event_info);
33
34static void
35_del_hook(Evas_Object *obj)
36{
37 Widget_Data *wd = elm_widget_data_get(obj);
38 if (!wd) return;
39 if (wd->label) eina_stringshare_del(wd->label);
40 free(wd);
41}
42
43static void
44_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
45{
46 Widget_Data *wd = elm_widget_data_get(obj);
47 if (!wd) return;
48 edje_object_mirrored_set(wd->frm, rtl);
49}
50
51static void
52_theme_hook(Evas_Object *obj)
53{
54 Widget_Data *wd = elm_widget_data_get(obj);
55 if (!wd) return;
56 _elm_widget_mirrored_reload(obj);
57 _mirrored_set(obj, elm_widget_mirrored_get(obj));
58 _elm_theme_object_set(obj, wd->frm, "frame", "base",
59 elm_widget_style_get(obj));
60 edje_object_part_text_escaped_set(wd->frm, "elm.text", wd->label);
61 if (wd->content)
62 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
63 edje_object_scale_set(wd->frm,
64 elm_widget_scale_get(obj) * _elm_config->scale);
65 _sizing_eval(obj);
66}
67
68static Eina_Bool
69_elm_frame_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
70{
71 Widget_Data *wd = elm_widget_data_get(obj);
72
73 if ((!wd) || (!wd->content))
74 return EINA_FALSE;
75
76 /* Try Focus cycle in subitem */
77 return elm_widget_focus_next_get(wd->content, dir, next);
78}
79
80static void
81_sizing_eval(Evas_Object *obj)
82{
83 Widget_Data *wd = elm_widget_data_get(obj);
84 Evas_Coord minw = -1, minh = -1;
85 Evas_Coord cminw = -1, cminh = -1;
86 if (!wd) return;
87 edje_object_size_min_calc(wd->frm, &minw, &minh);
88 evas_object_size_hint_min_get(obj, &cminw, &cminh);
89 if ((minw == cminw) && (minh == cminh)) return;
90 evas_object_size_hint_min_set(obj, minw, minh);
91 evas_object_size_hint_max_set(obj, -1, -1);
92}
93
94static void
95_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
96{
97 Widget_Data *wd = elm_widget_data_get(data);
98 if (!wd) return;
99 if (wd->anim) return;
100 // FIXME: why is this needed? how does edje get this unswallowed or
101 // lose its callbacks to edje
102 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
103 _sizing_eval(data);
104}
105
106static void
107_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
108{
109 Widget_Data *wd = elm_widget_data_get(obj);
110 Evas_Object *sub = event_info;
111 if (!wd) return;
112 if (sub == wd->content)
113 {
114 evas_object_event_callback_del_full(sub,
115 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
116 _changed_size_hints, obj);
117 wd->content = NULL;
118 _sizing_eval(obj);
119 }
120}
121
122static void
123_elm_frame_label_set(Evas_Object *obj, const char *item, const char *label)
124{
125 ELM_CHECK_WIDTYPE(obj, widtype);
126 Widget_Data *wd = elm_widget_data_get(obj);
127 if (item && strcmp(item, "default")) return;
128 if (!wd) return;
129 eina_stringshare_replace(&(wd->label), label);
130 edje_object_part_text_escaped_set(wd->frm, "elm.text", wd->label);
131 _sizing_eval(obj);
132}
133
134static const char *
135_elm_frame_label_get(const Evas_Object *obj, const char *item)
136{
137 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
138 Widget_Data *wd = elm_widget_data_get(obj);
139 if (!wd) return NULL;
140 if (item && strcmp(item, "default")) return NULL;
141 return wd->label;
142}
143
144static void
145_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
146{
147 ELM_CHECK_WIDTYPE(obj, widtype);
148 Widget_Data *wd;
149
150 if (part && strcmp(part, "default")) return;
151 wd = elm_widget_data_get(obj);
152 if (!wd) return;
153 if (wd->content == content) return;
154 if (wd->content) evas_object_del(wd->content);
155 wd->content = content;
156 if (content)
157 {
158 elm_widget_sub_object_add(obj, content);
159 evas_object_event_callback_add(content,
160 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
161 _changed_size_hints, obj);
162 edje_object_part_swallow(wd->frm, "elm.swallow.content", content);
163 }
164 _sizing_eval(obj);
165}
166
167static Evas_Object *
168_content_get_hook(const Evas_Object *obj, const char *part)
169{
170 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
171 Widget_Data *wd;
172
173 if (part && strcmp(part, "default")) return NULL;
174 wd = elm_widget_data_get(obj);
175 if (!wd) return NULL;
176
177 return wd->content;
178}
179
180static Evas_Object *
181_content_unset_hook(Evas_Object *obj, const char *part)
182{
183 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
184 Widget_Data *wd;
185 Evas_Object *content;
186 if (part && strcmp(part, "default")) return NULL;
187 wd = elm_widget_data_get(obj);
188 if (!wd || !wd->content) return NULL;
189 content = wd->content;
190 elm_widget_sub_object_del(obj, wd->content);
191 edje_object_part_unswallow(wd->frm, content);
192 return content;
193}
194
195static void
196_recalc(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
197{
198 _sizing_eval(data);
199}
200
201static void
202_recalc_done(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__)
203{
204 Widget_Data *wd = elm_widget_data_get(data);
205 if (!wd) return;
206 evas_object_smart_callback_del(wd->frm, "recalc", _recalc);
207 wd->anim = EINA_FALSE;
208 _sizing_eval(data);
209}
210
211static void
212_signal_click(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *src __UNUSED__)
213{
214 Widget_Data *wd = elm_widget_data_get(data);
215 if (!wd) return;
216 if (wd->anim) return;
217 if (wd->collapsible)
218 {
219 evas_object_smart_callback_add(wd->frm, "recalc", _recalc, data);
220 edje_object_signal_emit(wd->frm, "elm,action,toggle", "elm");
221 wd->collapsed++;
222 wd->anim = EINA_TRUE;
223 }
224 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
225}
226
227EAPI Evas_Object *
228elm_frame_add(Evas_Object *parent)
229{
230 Evas_Object *obj;
231 Evas *e;
232 Widget_Data *wd;
233
234 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
235
236 ELM_SET_WIDTYPE(widtype, "frame");
237 elm_widget_type_set(obj, "frame");
238 elm_widget_sub_object_add(parent, obj);
239 elm_widget_data_set(obj, wd);
240 elm_widget_del_hook_set(obj, _del_hook);
241 elm_widget_theme_hook_set(obj, _theme_hook);
242 elm_widget_focus_next_hook_set(obj, _elm_frame_focus_next_hook);
243 elm_widget_can_focus_set(obj, EINA_FALSE);
244 elm_widget_text_set_hook_set(obj, _elm_frame_label_set);
245 elm_widget_text_get_hook_set(obj, _elm_frame_label_get);
246 elm_widget_content_set_hook_set(obj, _content_set_hook);
247 elm_widget_content_get_hook_set(obj, _content_get_hook);
248 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
249
250 wd->frm = edje_object_add(e);
251 _elm_theme_object_set(obj, wd->frm, "frame", "base", "default");
252 elm_widget_resize_object_set(obj, wd->frm);
253
254 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
255 edje_object_signal_callback_add(wd->frm, "elm,anim,done", "elm",
256 _recalc_done, obj);
257 edje_object_signal_callback_add(wd->frm, "elm,action,click", "elm",
258 _signal_click, obj);
259 evas_object_smart_callbacks_descriptions_set(obj, _signals);
260
261 _mirrored_set(obj, elm_widget_mirrored_get(obj));
262 _sizing_eval(obj);
263 return obj;
264}
265
266EAPI void
267elm_frame_autocollapse_set(Evas_Object *obj, Eina_Bool autocollapse)
268{
269 Widget_Data *wd;
270 ELM_CHECK_WIDTYPE(obj, widtype);
271 wd = elm_widget_data_get(obj);
272 if (!wd) return;
273 wd->collapsible = !!autocollapse;
274}
275
276EAPI Eina_Bool
277elm_frame_autocollapse_get(const Evas_Object *obj)
278{
279 Widget_Data *wd;
280 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
281 wd = elm_widget_data_get(obj);
282 if (!wd) return EINA_FALSE;
283 return wd->collapsible;
284}
285
286EAPI void
287elm_frame_collapse_set(Evas_Object *obj, Eina_Bool collapse)
288{
289 Widget_Data *wd;
290 ELM_CHECK_WIDTYPE(obj, widtype);
291 wd = elm_widget_data_get(obj);
292 if (!wd) return;
293 collapse = !!collapse;
294 if (wd->collapsed == collapse) return;
295 edje_object_signal_emit(wd->frm, "elm,action,switch", "elm");
296 edje_object_message_signal_process(wd->frm);
297 wd->collapsed = !!collapse;
298 wd->anim = EINA_FALSE;
299 _sizing_eval(obj);
300}
301
302EAPI void
303elm_frame_collapse_go(Evas_Object *obj, Eina_Bool collapse)
304{
305 Widget_Data *wd;
306 ELM_CHECK_WIDTYPE(obj, widtype);
307 wd = elm_widget_data_get(obj);
308 if (!wd) return;
309 collapse = !!collapse;
310 if (wd->collapsed == collapse) return;
311 edje_object_signal_emit(wd->frm, "elm,action,toggle", "elm");
312 evas_object_smart_callback_add(wd->frm, "recalc", _recalc, obj);
313 wd->collapsed = collapse;
314 wd->anim = EINA_TRUE;
315}
316
317EAPI Eina_Bool
318elm_frame_collapse_get(const Evas_Object *obj)
319{
320 Widget_Data *wd;
321 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
322 wd = elm_widget_data_get(obj);
323 if (!wd) return EINA_FALSE;
324 return wd->collapsed;
325}
diff --git a/libraries/elementary/src/lib/elm_frame.h b/libraries/elementary/src/lib/elm_frame.h
new file mode 100644
index 0000000..58c3d93
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_frame.h
@@ -0,0 +1,114 @@
1/**
2 * @defgroup Frame Frame
3 * @ingroup Elementary
4 *
5 * @image html img/widget/frame/preview-00.png
6 * @image latex img/widget/frame/preview-00.eps
7 *
8 * @brief Frame is a widget that holds some content and has a title.
9 *
10 * The default look is a frame with a title, but Frame supports multiple
11 * styles:
12 * @li default
13 * @li pad_small
14 * @li pad_medium
15 * @li pad_large
16 * @li pad_huge
17 * @li outdent_top
18 * @li outdent_bottom
19 *
20 * Of all this styles only default shows the title.
21 *
22 * Smart callbacks one can listen to:
23 * - @c "clicked" - The user has clicked the frame's label
24 *
25 * Default content parts of the frame widget that you can use for are:
26 * @li "default" - A content of the frame
27 *
28 * Default text parts of the frame widget that you can use for are:
29 * @li "default" - Label of the frame
30 *
31 * Supported elm_object common APIs.
32 * @li @ref elm_object_part_text_set
33 * @li @ref elm_object_part_text_get
34 * @li @ref elm_object_part_content_set
35 * @li @ref elm_object_part_content_get
36 * @li @ref elm_object_part_content_unset
37 *
38 * For a detailed example see the @ref tutorial_frame.
39 *
40 * @{
41 */
42
43/**
44 * @brief Add a new frame to the parent
45 *
46 * @param parent The parent object
47 * @return The new object or NULL if it cannot be created
48 *
49 * @ingroup Frame
50 */
51EAPI Evas_Object *elm_frame_add(Evas_Object *parent);
52
53/**
54 * @brief Toggle autocollapsing of a frame
55 * @param obj The frame
56 * @param autocollapse Whether to enable autocollapse
57 *
58 * When @p enable is EINA_TRUE, clicking a frame's label will collapse the frame
59 * vertically, shrinking it to the height of the label.
60 * By default, this is DISABLED.
61 *
62 * @ingroup Frame
63 */
64EAPI void elm_frame_autocollapse_set(Evas_Object *obj, Eina_Bool autocollapse);
65
66/**
67 * @brief Determine autocollapsing of a frame
68 * @param obj The frame
69 * @return Whether autocollapse is enabled
70 *
71 * When this returns EINA_TRUE, clicking a frame's label will collapse the frame
72 * vertically, shrinking it to the height of the label.
73 * By default, this is DISABLED.
74 *
75 * @ingroup Frame
76 */
77EAPI Eina_Bool elm_frame_autocollapse_get(const Evas_Object *obj);
78
79/**
80 * @brief Manually collapse a frame without animations
81 * @param obj The frame
82 * @param collapse true to collapse, false to expand
83 *
84 * Use this to toggle the collapsed state of a frame, bypassing animations.
85 *
86 * @ingroup Frame
87 */
88EAPI void elm_frame_collapse_set(Evas_Object *obj, Eina_Bool collapse);
89
90/**
91 * @brief Determine the collapse state of a frame
92 * @param obj The frame
93 * @return true if collapsed, false otherwise
94 *
95 * Use this to determine the collapse state of a frame.
96 *
97 * @ingroup Frame
98 */
99EAPI Eina_Bool elm_frame_collapse_get(const Evas_Object *obj);
100
101/**
102 * @brief Manually collapse a frame with animations
103 * @param obj The frame
104 * @param collapse true to collapse, false to expand
105 *
106 * Use this to toggle the collapsed state of a frame, triggering animations.
107 *
108 * @ingroup Frame
109 */
110EAPI void elm_frame_collapse_go(Evas_Object *obj, Eina_Bool collapse);
111
112/**
113 * @}
114 */
diff --git a/libraries/elementary/src/lib/elm_gen.h b/libraries/elementary/src/lib/elm_gen.h
new file mode 100644
index 0000000..431f7b1
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_gen.h
@@ -0,0 +1,63 @@
1typedef struct Elm_Gen_Item Elm_Gen_Item;
2
3/**
4 * @struct Elm_Gen_Item_Class
5 *
6 * Gengrid or Genlist item class definition.
7 * field details.
8 */
9typedef struct _Elm_Gen_Item_Class Elm_Gen_Item_Class;
10
11/**
12 * Text fetching class function for Elm_Gen_Item_Class.
13 * @param data The data passed in the item creation function
14 * @param obj The base widget object
15 * @param part The part name of the swallow
16 * @return The allocated (NOT stringshared) string to set as the text
17 */
18typedef char *(*Elm_Gen_Item_Text_Get_Cb)(void *data, Evas_Object *obj, const char *part); /**< Label fetching class function for gen item classes. */
19
20/**
21 * Content (swallowed object) fetching class function for Elm_Gen_Item_Class.
22 * @param data The data passed in the item creation function
23 * @param obj The base widget object
24 * @param part The part name of the swallow
25 * @return The content object to swallow
26 */
27typedef Evas_Object *(*Elm_Gen_Item_Content_Get_Cb)(void *data, Evas_Object *obj, const char *part); /**< Content(swallowed object) fetching class function for gen item classes. */
28
29/**
30 * State fetching class function for Elm_Gen_Item_Class.
31 * @param data The data passed in the item creation function
32 * @param obj The base widget object
33 * @param part The part name of the swallow
34 * @return The hell if I know
35 */
36typedef Eina_Bool (*Elm_Gen_Item_State_Get_Cb)(void *data, Evas_Object *obj, const char *part); /**< State fetching class function for gen item classes. */
37
38/**
39 * Deletion class function for Elm_Gen_Item_Class.
40 * @param data The data passed in the item creation function
41 * @param obj The base widget object
42 */
43typedef void (*Elm_Gen_Item_Del_Cb)(void *data, Evas_Object *obj); /**< Deletion class function for gen item classes. */
44
45struct _Elm_Gen_Item_Class
46{
47 int version; /**< Set by elementary if you alloc an item class using elm_genlist/gengrid_item_class_new(), or if you set your own class (must be const) then set it to ELM_GENLIST/GENGRID_ITEM_CLASS_VERSION */
48 unsigned int refcount; /**< Set it to 0 if you use your own const class, or its managed for you by class ref/unref calls */
49 Eina_Bool delete_me : 1; /**< Leave this alone - set it to 0 if you have a const class of your own */
50 const char *item_style; /**< Name of the visual style to use for this item. If you don't know use "default" */
51 const char *decorate_item_style; /**< Style used if item is set to a decorate mode. @see elm_genlist_item_decorate_mode_set() or NULL if you don't care. currently it's used only in genlist. */
52 const char *decorate_all_item_style; /**< Style to use when in edit mode, or NULL if you don't care. currently it's used only in genlist. */
53 struct
54 {
55 Elm_Gen_Item_Text_Get_Cb text_get; /**< Text fetching class function for genlist/gengrid item classes.*/
56 Elm_Gen_Item_Content_Get_Cb content_get; /**< Content fetching class function for genlist/gengrid item classes. */
57 Elm_Gen_Item_State_Get_Cb state_get; /**< State fetching class function for genlist/gengrid item classes. */
58 Elm_Gen_Item_Del_Cb del; /**< Deletion class function for genlist/gengrid item classes. */
59 } func;
60}; /**< #Elm_Gen_Item_Class member definitions */
61
62#define ELM_GEN_ITEM_CLASS_VERSION 2
63#define ELM_GEN_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_VERSION, 0, 0
diff --git a/libraries/elementary/src/lib/elm_gen_common.h b/libraries/elementary/src/lib/elm_gen_common.h
new file mode 100644
index 0000000..ec6d03f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_gen_common.h
@@ -0,0 +1,204 @@
1#ifndef ELM_GEN_H_
2#define ELM_GEN_H_
3
4#include <Elementary.h>
5#include <Elementary_Cursor.h>
6#include "elm_priv.h"
7
8#define ELM_GEN_ITEM_FROM_INLIST(it) \
9 ((it) ? EINA_INLIST_CONTAINER_GET(it, Elm_Gen_Item) : NULL)
10
11#define SWIPE_MOVES 12
12
13typedef struct Elm_Gen_Item_Type Elm_Gen_Item_Type;
14typedef struct Elm_Gen_Item_Tooltip Elm_Gen_Item_Tooltip;
15typedef struct _Widget_Data Widget_Data;
16
17struct Elm_Gen_Item_Tooltip
18{
19 const void *data;
20 Elm_Tooltip_Item_Content_Cb content_cb;
21 Evas_Smart_Cb del_cb;
22 const char *style;
23 Eina_Bool free_size : 1;
24};
25
26struct Elm_Gen_Item
27{
28 ELM_WIDGET_ITEM;
29 EINA_INLIST;
30 Widget_Data *wd;
31 Elm_Gen_Item_Type *item;
32 const Elm_Gen_Item_Class *itc;
33 Evas_Coord x, y, dx, dy;
34 Evas_Object *spacer, *deco_all_view;
35 Elm_Gen_Item *parent;
36 Eina_List *texts, *contents, *states, *content_objs;
37 Ecore_Timer *long_timer;
38 int relcount;
39 int walking;
40 int generation; /**< a generation of an item. when the item is created, this value is set to the value of genlist generation. this value will be decreased when the item is going to be deleted */
41 const char *mouse_cursor;
42
43 struct
44 {
45 Evas_Smart_Cb func;
46 const void *data;
47 } func;
48
49 Elm_Gen_Item_Tooltip tooltip;
50 Ecore_Cb del_cb, sel_cb, highlight_cb;
51 Ecore_Cb unsel_cb, unhighlight_cb, unrealize_cb;
52
53 int position;
54 Elm_Object_Select_Mode select_mode;
55
56 Eina_Bool position_update : 1;
57 Eina_Bool want_unrealize : 1;
58 Eina_Bool realized : 1;
59 Eina_Bool selected : 1;
60 Eina_Bool highlighted : 1;
61 Eina_Bool dragging : 1; /**< this is set true when an item is being dragged. this is set false on multidown/mouseup/mousedown. when this is true, the item should not be unrealized. or evas mouse down/up event will be corrupted. */
62 Eina_Bool down : 1;
63 Eina_Bool group : 1;
64 Eina_Bool reorder : 1;
65 Eina_Bool decorate_it_set : 1; /**< item uses style mode for highlight/select */
66 Eina_Bool flipped : 1; /**< a flag that shows the flip status of the item. */
67};
68
69typedef struct _Pan Pan;
70struct _Pan
71{
72 Evas_Object_Smart_Clipped_Data __clipped_data;
73 Widget_Data *wd;
74 Ecore_Job *resize_job;
75};
76
77typedef enum
78{
79 ELM_GENLIST_TREE_EFFECT_NONE = 0,
80 ELM_GENLIST_TREE_EFFECT_EXPAND = 1,
81 ELM_GENLIST_TREE_EFFECT_CONTRACT = 2
82} Elm_Genlist_Item_Move_Effect_Mode;
83
84struct _Widget_Data
85{
86 Eina_Inlist_Sorted_State *state;
87 Evas_Object *obj; /**< the genlist object */
88 Evas_Object *scr; /**< a smart scroller object which is used internally in genlist */
89 Evas_Object *pan_smart; /**< "elm_genlist_pan" evas smart object. this is an extern pan of smart scroller(scr). */
90 Eina_List *selected; /**< a list of selected items */
91 Eina_List *group_items; /**< a list of groups index items */
92 Eina_Inlist *items; /**< an inlist of all items */
93 Elm_Gen_Item *reorder_it; /**< item currently being repositioned */
94 Elm_Object_Item *last_selected_item;
95 Pan *pan; /**< pan_smart object's smart data */
96 Ecore_Job *calc_job;
97 int walking;
98 int item_width, item_height;
99 int group_item_width, group_item_height;
100 int minw, minh;
101 unsigned int item_count;
102 Evas_Coord pan_x, pan_y;
103 Elm_Object_Select_Mode select_mode;
104 Eina_Bool reorder_mode : 1; /**< a flag for reorder mode enable/disable */
105 Eina_Bool on_hold : 1;
106 Eina_Bool multi : 1; /**< a flag for item multi selection */
107 Eina_Bool wasselected : 1;
108 Eina_Bool highlight : 1; /**< a flag for items can be highlighted or not. by default this flag is true. */
109 Eina_Bool clear_me : 1; /**< a flag whether genlist is marked as to be cleared or not. if this flag is true, genlist clear was already deferred. */
110 Eina_Bool h_bounce : 1;
111 Eina_Bool v_bounce : 1;
112 Ecore_Cb del_cb, calc_cb, sizing_cb;
113 Ecore_Cb clear_cb;
114 ////////////////////////////////////
115 Eina_Inlist *blocks; /**< an inlist of all blocks. a block consists of a certain number of items. maximum number of items in a block is 'max_items_per_block'. */
116 Evas_Coord reorder_old_pan_y, w, h, realminw, prev_viewport_w;
117 Ecore_Job *update_job;
118 Ecore_Idle_Enterer *queue_idle_enterer;
119 Ecore_Idler *must_recalc_idler;
120 Eina_List *queue;
121 Elm_Gen_Item *show_item, *anchor_item, *mode_item, *reorder_rel, *expanded_item;
122 Eina_Inlist *item_cache; /**< an inlist of edje object it cache. */
123 Evas_Coord anchor_y;
124 Evas_Coord reorder_start_y; /**< reorder it's initial y coordinate in the pan. */
125 Elm_List_Mode mode;
126 Ecore_Timer *multi_timer, *scr_hold_timer;
127 Ecore_Animator *reorder_move_animator;
128 const char *decorate_it_type;
129 double start_time;
130 Evas_Coord prev_x, prev_y, prev_mx, prev_my;
131 Evas_Coord cur_x, cur_y, cur_mx, cur_my;
132 Eina_Bool mouse_down : 1;
133 Eina_Bool multi_down : 1;
134 Eina_Bool multi_timeout : 1;
135 Eina_Bool multitouched : 1;
136 Eina_Bool longpressed : 1;
137 Eina_Bool bring_in : 1; /**< a flag to describe the scroll animation. (show, bring in) */
138 Eina_Bool height_for_width : 1;
139 Eina_Bool homogeneous : 1;
140 Eina_Bool swipe : 1;
141 Eina_Bool decorate_all_mode : 1;
142 Eina_Bool reorder_pan_move : 1;
143 Eina_Bool auto_scroll_enabled : 1;
144 Eina_Bool pan_changed : 1;
145 Eina_Bool requeued : 1; /**< this is set to EINA_TRUE when the item is re-queued. this happens when the item is un-queued but the rel item is still in the queue. this item will be processed later. */
146 Eina_Bool check_scroll : 1; /**< this flag means genlist is supposed to be scrolled. if this flag is set to EINA_TRUE, genlist checks whether it's ok to scroll genlist now or not. */
147 Eina_Bool tree_effect_enabled : 1; /**< tree effect */
148 struct
149 {
150 Evas_Coord x, y;
151 } history[SWIPE_MOVES];
152 int multi_device;
153 int item_cache_count;
154 int item_cache_max; /**< maximum number of cached items */
155 int movements;
156 int max_items_per_block; /**< maximum number of items per block */
157 double longpress_timeout; /**< longpress timeout. this value comes from _elm_config by default. this can be changed by elm_genlist_longpress_timeout_set() */
158 int generation; /**< a generation of genlist. when genlist is cleared, this value will be increased and a new generation will start */
159 Eina_Compare_Cb item_compare_cb;
160 Eina_Compare_Cb item_compare_data_cb;
161 Elm_Genlist_Item_Scrollto_Type scrollto_type; /**< a scrollto type which remembers where to scroll ex) in, top, middle */
162 Evas_Object *alpha_bg; /**< not to receive event when tree effect is not finished */
163 Eina_List *move_items; /**< items move for tree effect */
164 Elm_Gen_Item *expanded_next_item;
165 Ecore_Animator *tree_effect_animator; /**< tree effect animator */
166 Elm_Genlist_Item_Move_Effect_Mode move_effect_mode;
167
168 /* The stuff below directly come from gengrid without any thinking */
169 unsigned int nmax;
170 Evas_Coord reorder_item_x, reorder_item_y;
171 Evas_Coord old_pan_x, old_pan_y;
172 long items_lost;
173 double align_x, align_y;
174
175 Eina_Bool horizontal : 1;
176 Eina_Bool move_effect_enabled : 1;
177 Eina_Bool reorder_item_changed : 1;
178 Eina_Bool filled : 1;
179};
180
181Elm_Gen_Item *_elm_genlist_item_new(Widget_Data *wd, const Elm_Gen_Item_Class *itc, const void *data, Elm_Gen_Item *parent, Evas_Smart_Cb func, const void *func_data);
182
183Evas_Object *_elm_genlist_item_widget_get(const Elm_Gen_Item *it);
184
185void _elm_genlist_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel);
186
187void _elm_genlist_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel);
188
189void _elm_genlist_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize);
190
191void _elm_genlist_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
192
193void _elm_genlist_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
194
195void _elm_genlist_page_show(const Evas_Object *obj, int h_pagenumber, int v_pagenumber);
196
197void _elm_genlist_page_bring_in(const Evas_Object *obj, int h_pagenumber, int v_pagenumber);
198
199void _elm_genlist_item_unrealize(Elm_Gen_Item *it, Eina_Bool calc);
200void _elm_genlist_item_del_serious(Elm_Gen_Item *it);
201
202void _elm_genlist_item_del_notserious(Elm_Gen_Item *it);
203
204#endif
diff --git a/libraries/elementary/src/lib/elm_general.h b/libraries/elementary/src/lib/elm_general.h
new file mode 100644
index 0000000..08cd205
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_general.h
@@ -0,0 +1,365 @@
1/**
2 * @defgroup General General
3 * @ingroup Elementary
4 *
5 * @brief General Elementary API. Functions that don't relate to
6 * Elementary objects specifically.
7 *
8 * Here are documented functions which init/shutdown the library,
9 * that apply to generic Elementary objects, that deal with
10 * configuration, et cetera.
11 *
12 * @ref general_functions_example_page "This" example contemplates
13 * some of these functions.
14 */
15
16/**
17 * @addtogroup General
18 * @{
19 */
20
21/**
22 * Defines couple of standard Evas_Object layers to be used
23 * with evas_object_layer_set().
24 *
25 * @note whenever extending with new values, try to keep some padding
26 * to siblings so there is room for further extensions.
27 */
28typedef enum
29{
30 ELM_OBJECT_LAYER_BACKGROUND = EVAS_LAYER_MIN + 64, /**< where to place backgrounds */
31 ELM_OBJECT_LAYER_DEFAULT = 0, /**< Evas_Object default layer (and thus for Elementary) */
32 ELM_OBJECT_LAYER_FOCUS = EVAS_LAYER_MAX - 128, /**< where focus object visualization is */
33 ELM_OBJECT_LAYER_TOOLTIP = EVAS_LAYER_MAX - 64, /**< where to show tooltips */
34 ELM_OBJECT_LAYER_CURSOR = EVAS_LAYER_MAX - 32, /**< where to show cursors */
35 ELM_OBJECT_LAYER_LAST /**< last layer known by Elementary */
36} Elm_Object_Layer;
37
38/**************************************************************************/
39EAPI extern int ELM_ECORE_EVENT_ETHUMB_CONNECT;
40
41/**
42 * Emitted when the application has reconfigured elementary settings due
43 * to an external configuration tool asking it to.
44 */
45EAPI extern int ELM_EVENT_CONFIG_ALL_CHANGED;
46
47/**
48 * Emitted when any Elementary's policy value is changed.
49 */
50EAPI extern int ELM_EVENT_POLICY_CHANGED;
51
52/**
53 * @typedef Elm_Event_Policy_Changed
54 *
55 * Data on the event when an Elementary policy has changed
56 */
57typedef struct _Elm_Event_Policy_Changed Elm_Event_Policy_Changed;
58
59/**
60 * @struct _Elm_Event_Policy_Changed
61 *
62 * Data on the event when an Elementary policy has changed
63 */
64struct _Elm_Event_Policy_Changed
65{
66 unsigned int policy; /**< the policy identifier */
67 int new_value; /**< value the policy had before the change */
68 int old_value; /**< new value the policy got */
69};
70
71/**
72 * Policy identifiers.
73 */
74typedef enum
75{
76 ELM_POLICY_QUIT, /**< under which circumstances the application
77 * should quit automatically. @see
78 * Elm_Policy_Quit.
79 */
80 ELM_POLICY_LAST
81} Elm_Policy; /**< Elementary policy identifiers/groups enumeration. @see elm_policy_set() */
82
83typedef enum
84{
85 ELM_POLICY_QUIT_NONE = 0, /**< never quit the application
86 * automatically */
87 ELM_POLICY_QUIT_LAST_WINDOW_CLOSED /**< quit when the
88 * application's last
89 * window is closed */
90} Elm_Policy_Quit; /**< Possible values for the #ELM_POLICY_QUIT policy */
91
92typedef enum
93{
94 ELM_FOCUS_PREVIOUS,
95 ELM_FOCUS_NEXT
96} Elm_Focus_Direction;
97
98typedef enum
99{
100 ELM_OBJECT_SELECT_MODE_DEFAULT = 0, /**< default select mode */
101 ELM_OBJECT_SELECT_MODE_ALWAYS, /**< always select mode */
102 ELM_OBJECT_SELECT_MODE_NONE, /**< no select mode */
103 ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY, /**< no select mode with no finger size rule*/
104 ELM_OBJECT_SELECT_MODE_MAX
105} Elm_Object_Select_Mode;
106
107/**
108 * @typedef Elm_Object_Item
109 * An Elementary Object item handle.
110 * @ingroup General
111 */
112typedef struct _Elm_Object_Item Elm_Object_Item;
113
114typedef Eina_Bool (*Elm_Event_Cb)(void *data, Evas_Object *obj, Evas_Object *src, Evas_Callback_Type type, void *event_info); /**< Function prototype definition for callbacks on input events happening on Elementary widgets. @a data will receive the user data pointer passed to elm_object_event_callback_add(). @a src will be a pointer to the widget on which the input event took place. @a type will get the type of this event and @a event_info, the struct with details on this event. */
115
116#ifndef ELM_LIB_QUICKLAUNCH
117#define ELM_MAIN() int main(int argc, char **argv) {elm_init(argc, argv); return elm_main(argc, argv); } /**< macro to be used after the elm_main() function */
118#else
119#define ELM_MAIN() int main(int argc, char **argv) {return elm_quicklaunch_fallback(argc, argv); } /**< macro to be used after the elm_main() function */
120#endif
121
122/**************************************************************************/
123/* General calls */
124
125/**
126 * Initialize Elementary
127 *
128 * @param[in] argc System's argument count value
129 * @param[in] argv System's pointer to array of argument strings
130 * @return The init counter value.
131 *
132 * This function initializes Elementary and increments a counter of
133 * the number of calls to it. It returns the new counter's value.
134 *
135 * @warning This call is exported only for use by the @c ELM_MAIN()
136 * macro. There is no need to use this if you use this macro (which
137 * is highly advisable). An elm_main() should contain the entry
138 * point code for your application, having the same prototype as
139 * elm_init(), and @b not being static (putting the @c EAPI_MAIN symbol
140 * in front of its type declaration is advisable). The @c
141 * ELM_MAIN() call should be placed just after it.
142 *
143 * Example:
144 * @dontinclude bg_example_01.c
145 * @skip static void
146 * @until ELM_MAIN
147 *
148 * See the full @ref bg_example_01_c "example".
149 *
150 * @see elm_shutdown().
151 * @ingroup General
152 */
153EAPI int elm_init(int argc, char **argv);
154
155/**
156 * Shut down Elementary
157 *
158 * @return The init counter value.
159 *
160 * This should be called at the end of your application, just
161 * before it ceases to do any more processing. This will clean up
162 * any permanent resources your application may have allocated via
163 * Elementary that would otherwise persist.
164 *
165 * @see elm_init() for an example
166 *
167 * @ingroup General
168 */
169EAPI int elm_shutdown(void);
170
171/**
172 * Run Elementary's main loop
173 *
174 * This call should be issued just after all initialization is
175 * completed. This function will not return until elm_exit() is
176 * called. It will keep looping, running the main
177 * (event/processing) loop for Elementary.
178 *
179 * @see elm_init() for an example
180 *
181 * @ingroup General
182 */
183EAPI void elm_run(void);
184
185/**
186 * Exit Elementary's main loop
187 *
188 * If this call is issued, it will flag the main loop to cease
189 * processing and return back to its parent function (usually your
190 * elm_main() function).
191 *
192 * @see elm_init() for an example. There, just after a request to
193 * close the window comes, the main loop will be left.
194 *
195 * @note By using the appropriate #ELM_POLICY_QUIT on your Elementary
196 * applications, you'll be able to get this function called automatically for you.
197 *
198 * @ingroup General
199 */
200EAPI void elm_exit(void);
201
202/**
203 * Exposed symbol used only by macros and should not be used by apps
204 */
205EAPI void elm_quicklaunch_mode_set(Eina_Bool ql_on);
206
207/**
208 * Exposed symbol used only by macros and should not be used by apps
209 */
210EAPI Eina_Bool elm_quicklaunch_mode_get(void);
211
212/**
213 * Exposed symbol used only by macros and should not be used by apps
214 */
215EAPI int elm_quicklaunch_init(int argc, char **argv);
216
217/**
218 * Exposed symbol used only by macros and should not be used by apps
219 */
220EAPI int elm_quicklaunch_sub_init(int argc, char **argv);
221
222/**
223 * Exposed symbol used only by macros and should not be used by apps
224 */
225EAPI int elm_quicklaunch_sub_shutdown(void);
226
227/**
228 * Exposed symbol used only by macros and should not be used by apps
229 */
230EAPI int elm_quicklaunch_shutdown(void);
231
232/**
233 * Exposed symbol used only by macros and should not be used by apps
234 */
235EAPI void elm_quicklaunch_seed(void);
236
237/**
238 * Exposed symbol used only by macros and should not be used by apps
239 */
240EAPI Eina_Bool elm_quicklaunch_prepare(int argc, char **argv);
241
242/**
243 * Exposed symbol used only by macros and should not be used by apps
244 */
245EAPI Eina_Bool elm_quicklaunch_fork(int argc, char **argv, char *cwd, void (postfork_func) (void *data), void *postfork_data);
246
247/**
248 * Exposed symbol used only by macros and should not be used by apps
249 */
250EAPI void elm_quicklaunch_cleanup(void);
251
252/**
253 * Exposed symbol used only by macros and should not be used by apps
254 */
255EAPI int elm_quicklaunch_fallback(int argc, char **argv);
256
257/**
258 * Exposed symbol used only by macros and should not be used by apps
259 */
260EAPI char *elm_quicklaunch_exe_path_get(const char *exe);
261
262/**
263 * Set a new policy's value (for a given policy group/identifier).
264 *
265 * @param policy policy identifier, as in @ref Elm_Policy.
266 * @param value policy value, which depends on the identifier
267 *
268 * @return @c EINA_TRUE on success or @c EINA_FALSE, on error.
269 *
270 * Elementary policies define applications' behavior,
271 * somehow. These behaviors are divided in policy groups (see
272 * #Elm_Policy enumeration). This call will emit the Ecore event
273 * #ELM_EVENT_POLICY_CHANGED, which can be hooked at with
274 * handlers. An #Elm_Event_Policy_Changed struct will be passed,
275 * then.
276 *
277 * @note Currently, we have only one policy identifier/group
278 * (#ELM_POLICY_QUIT), which has two possible values.
279 *
280 * @ingroup General
281 */
282EAPI Eina_Bool elm_policy_set(unsigned int policy, int value);
283
284/**
285 * Gets the policy value for given policy identifier.
286 *
287 * @param policy policy identifier, as in #Elm_Policy.
288 * @return The currently set policy value, for that
289 * identifier. Will be @c 0 if @p policy passed is invalid.
290 *
291 * @ingroup General
292 */
293EAPI int elm_policy_get(unsigned int policy);
294
295/**
296 * Change the language of the current application
297 *
298 * The @p lang passed must be the full name of the locale to use, for
299 * example "en_US.utf8" or "es_ES@euro".
300 *
301 * Changing language with this function will make Elementary run through
302 * all its widgets, translating strings set with
303 * elm_object_domain_translatable_text_part_set(). This way, an entire
304 * UI can have its language changed without having to restart the program.
305 *
306 * For more complex cases, like having formatted strings that need
307 * translation, widgets will also emit a "language,changed" signal that
308 * the user can listen to to manually translate the text.
309 *
310 * @param lang Language to set, must be the full name of the locale
311 *
312 * @ingroup General
313 */
314EAPI void elm_language_set(const char *lang);
315
316/**
317 * Set the text for an objects' part, marking it as translatable.
318 *
319 * The string to set as @p text must be the original one. Do not pass the
320 * return of @c gettext() here. Elementary will translate the string
321 * internally and set it on the object using elm_object_part_text_set(),
322 * also storing the original string so that it can be automatically
323 * translated when the language is changed with elm_language_set().
324 *
325 * The @p domain will be stored along to find the translation in the
326 * correct catalog. It can be NULL, in which case it will use whatever
327 * domain was set by the application with @c textdomain(). This is useful
328 * in case you are building a library on top of Elementary that will have
329 * its own translatable strings, that should not be mixed with those of
330 * programs using the library.
331 *
332 * @param obj The object containing the text part
333 * @param part The name of the part to set
334 * @param domain The translation domain to use
335 * @param text The original, non-translated text to set
336 *
337 * @ingroup General
338 */
339EAPI void elm_object_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text);
340
341#define elm_object_domain_translatable_text_set(obj, domain, text) elm_object_domain_translatable_text_part_set((obj), NULL, (domain), (text))
342
343#define elm_object_translatable_text_set(obj, text) elm_object_domain_translatable_text_part_set((obj), NULL, NULL, (text))
344
345/**
346 * Gets the original string set as translatable for an object
347 *
348 * When setting translated strings, the function elm_object_part_text_get()
349 * will return the translation returned by @c gettext(). To get the
350 * original string use this function.
351 *
352 * @param obj The object
353 * @param part The name of the part that was set
354 *
355 * @return The original, untranslated string
356 *
357 * @ingroup General
358 */
359EAPI const char *elm_object_translatable_text_part_get(const Evas_Object *obj, const char *part);
360
361#define elm_object_translatable_text_get(obj) elm_object_translatable_text_part_get((obj), NULL)
362
363/**
364 * @}
365 */
diff --git a/libraries/elementary/src/lib/elm_gengrid.c b/libraries/elementary/src/lib/elm_gengrid.c
new file mode 100644
index 0000000..8ee50c4
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_gengrid.c
@@ -0,0 +1,2869 @@
1#include <Elementary.h>
2#include <Elementary_Cursor.h>
3#include "elm_priv.h"
4#include "els_scroller.h"
5#include "elm_gen_common.h"
6
7// internally allocated
8#define CLASS_ALLOCATED 0x3a70f00f
9
10/* --
11 * TODO:
12 * Handle non-homogeneous objects too.
13 */
14
15#define PRELOAD 1
16#define REORDER_EFFECT_TIME 0.5
17
18#define ELM_GEN_SETUP(wd) \
19 (wd)->calc_cb = (Ecore_Cb)_calc_job
20
21#define ELM_GEN_ITEM_SETUP(it) \
22 (it)->del_cb = (Ecore_Cb)_item_del; \
23 (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
24 (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
25 (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
26
27struct Elm_Gen_Item_Type
28{
29 Elm_Gen_Item *it;
30 Ecore_Animator *item_reorder_move_animator;
31 Evas_Coord gx, gy, ox, oy, tx, ty, rx, ry;
32 unsigned int moving_effect_start_time;
33 int prev_group;
34
35 Eina_Bool group_realized : 1;
36 Eina_Bool moving : 1;
37};
38
39static const char *widtype = NULL;
40static void _item_highlight(Elm_Gen_Item *it);
41static void _item_unrealize_cb(Elm_Gen_Item *it);
42static void _item_unselect(Elm_Gen_Item *it);
43static void _calc_job(void *data);
44static void _on_focus_hook(void *data,
45 Evas_Object *obj);
46static Eina_Bool _item_multi_select_up(Widget_Data *wd);
47static Eina_Bool _item_multi_select_down(Widget_Data *wd);
48static Eina_Bool _item_multi_select_left(Widget_Data *wd);
49static Eina_Bool _item_multi_select_right(Widget_Data *wd);
50static Eina_Bool _item_single_select_up(Widget_Data *wd);
51static Eina_Bool _item_single_select_down(Widget_Data *wd);
52static Eina_Bool _item_single_select_left(Widget_Data *wd);
53static Eina_Bool _item_single_select_right(Widget_Data *wd);
54static Eina_Bool _event_hook(Evas_Object *obj,
55 Evas_Object *src,
56 Evas_Callback_Type type,
57 void *event_info);
58static Eina_Bool _deselect_all_items(Widget_Data *wd);
59
60static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
61static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
62
63static const char SIG_ACTIVATED[] = "activated";
64static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
65static const char SIG_LONGPRESSED[] = "longpressed";
66static const char SIG_SELECTED[] = "selected";
67static const char SIG_UNSELECTED[] = "unselected";
68static const char SIG_REALIZED[] = "realized";
69static const char SIG_UNREALIZED[] = "unrealized";
70static const char SIG_CHANGED[] = "changed";
71static const char SIG_DRAG_START_UP[] = "drag,start,up";
72static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
73static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
74static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
75static const char SIG_DRAG_STOP[] = "drag,stop";
76static const char SIG_DRAG[] = "drag";
77static const char SIG_SCROLL[] = "scroll";
78static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
79static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
80static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
81static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
82static const char SIG_EDGE_TOP[] = "edge,top";
83static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
84static const char SIG_EDGE_LEFT[] = "edge,left";
85static const char SIG_EDGE_RIGHT[] = "edge,right";
86static const char SIG_MOVED[] = "moved";
87static const char SIG_INDEX_UPDATE[] = "index,update";
88
89static const Evas_Smart_Cb_Description _signals[] = {
90 {SIG_ACTIVATED, ""},
91 {SIG_CLICKED_DOUBLE, ""},
92 {SIG_LONGPRESSED, ""},
93 {SIG_SELECTED, ""},
94 {SIG_UNSELECTED, ""},
95 {SIG_REALIZED, ""},
96 {SIG_UNREALIZED, ""},
97 {SIG_CHANGED, ""},
98 {SIG_DRAG_START_UP, ""},
99 {SIG_DRAG_START_DOWN, ""},
100 {SIG_DRAG_START_LEFT, ""},
101 {SIG_DRAG_START_RIGHT, ""},
102 {SIG_DRAG_STOP, ""},
103 {SIG_DRAG, ""},
104 {SIG_SCROLL, ""},
105 {SIG_SCROLL_ANIM_START, ""},
106 {SIG_SCROLL_ANIM_STOP, ""},
107 {SIG_SCROLL_DRAG_START, ""},
108 {SIG_SCROLL_DRAG_STOP, ""},
109 {SIG_EDGE_TOP, ""},
110 {SIG_EDGE_BOTTOM, ""},
111 {SIG_EDGE_LEFT, ""},
112 {SIG_EDGE_RIGHT, ""},
113 {SIG_MOVED, ""},
114 {NULL, NULL}
115};
116
117static Eina_Bool
118_event_hook(Evas_Object *obj,
119 Evas_Object *src __UNUSED__,
120 Evas_Callback_Type type,
121 void *event_info)
122{
123 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
124 Evas_Event_Key_Down *ev = event_info;
125 Widget_Data *wd = elm_widget_data_get(obj);
126 if (!wd) return EINA_FALSE;
127 if (!wd->items) return EINA_FALSE;
128 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
129 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
130
131 Elm_Object_Item *it = NULL;
132 Evas_Coord x = 0;
133 Evas_Coord y = 0;
134 Evas_Coord step_x = 0;
135 Evas_Coord step_y = 0;
136 Evas_Coord v_w = 0;
137 Evas_Coord v_h = 0;
138 Evas_Coord page_x = 0;
139 Evas_Coord page_y = 0;
140
141 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
142 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
143 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
144 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
145
146 if ((!strcmp(ev->keyname, "Left")) ||
147 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
148 {
149 if ((wd->horizontal) &&
150 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
151 (_item_multi_select_up(wd)))
152 || (_item_single_select_up(wd))))
153 {
154 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
155 return EINA_TRUE;
156 }
157 else if ((!wd->horizontal) &&
158 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
159 (_item_multi_select_left(wd)))
160 || (_item_single_select_left(wd))))
161 {
162 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
163 return EINA_TRUE;
164 }
165 else
166 x -= step_x;
167 }
168 else if ((!strcmp(ev->keyname, "Right")) ||
169 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
170 {
171 if ((wd->horizontal) &&
172 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
173 (_item_multi_select_down(wd)))
174 || (_item_single_select_down(wd))))
175 {
176 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
177 return EINA_TRUE;
178 }
179 else if ((!wd->horizontal) &&
180 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
181 (_item_multi_select_right(wd)))
182 || (_item_single_select_right(wd))))
183 {
184 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
185 return EINA_TRUE;
186 }
187 else
188 x += step_x;
189 }
190 else if ((!strcmp(ev->keyname, "Up")) ||
191 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
192 {
193 if ((wd->horizontal) &&
194 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
195 (_item_multi_select_left(wd)))
196 || (_item_single_select_left(wd))))
197 {
198 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
199 return EINA_TRUE;
200 }
201 else if ((!wd->horizontal) &&
202 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
203 (_item_multi_select_up(wd)))
204 || (_item_single_select_up(wd))))
205 {
206 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
207 return EINA_TRUE;
208 }
209 else
210 y -= step_y;
211 }
212 else if ((!strcmp(ev->keyname, "Down")) ||
213 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
214 {
215 if ((wd->horizontal) &&
216 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
217 (_item_multi_select_right(wd)))
218 || (_item_single_select_right(wd))))
219 {
220 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
221 return EINA_TRUE;
222 }
223 else if ((!wd->horizontal) &&
224 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
225 (_item_multi_select_down(wd)))
226 || (_item_single_select_down(wd))))
227 {
228 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
229 return EINA_TRUE;
230 }
231 else
232 y += step_y;
233 }
234 else if ((!strcmp(ev->keyname, "Home")) ||
235 ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
236 {
237 it = elm_gengrid_first_item_get(obj);
238 elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
239 elm_gengrid_item_selected_set(it, EINA_TRUE);
240 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
241 return EINA_TRUE;
242 }
243 else if ((!strcmp(ev->keyname, "End")) ||
244 ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
245 {
246 it = elm_gengrid_last_item_get(obj);
247 elm_gengrid_item_bring_in(it, ELM_GENGRID_ITEM_SCROLLTO_IN);
248 elm_gengrid_item_selected_set(it, EINA_TRUE);
249 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
250 return EINA_TRUE;
251 }
252 else if ((!strcmp(ev->keyname, "Prior")) ||
253 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
254 {
255 if (wd->horizontal)
256 {
257 if (page_x < 0)
258 x -= -(page_x * v_w) / 100;
259 else
260 x -= page_x;
261 }
262 else
263 {
264 if (page_y < 0)
265 y -= -(page_y * v_h) / 100;
266 else
267 y -= page_y;
268 }
269 }
270 else if ((!strcmp(ev->keyname, "Next")) ||
271 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
272 {
273 if (wd->horizontal)
274 {
275 if (page_x < 0)
276 x += -(page_x * v_w) / 100;
277 else
278 x += page_x;
279 }
280 else
281 {
282 if (page_y < 0)
283 y += -(page_y * v_h) / 100;
284 else
285 y += page_y;
286 }
287 }
288 else if (!strcmp(ev->keyname, "Escape"))
289 {
290 if (!_deselect_all_items(wd)) return EINA_FALSE;
291 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
292 return EINA_TRUE;
293 }
294 else if (((!strcmp(ev->keyname, "Return")) ||
295 (!strcmp(ev->keyname, "KP_Enter")) ||
296 (!strcmp(ev->keyname, "space")))
297 && (!wd->multi) && (wd->selected))
298 {
299 it = elm_gengrid_selected_item_get(obj);
300 evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
301 }
302 else return EINA_FALSE;
303
304 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
305 elm_smart_scroller_child_pos_set(wd->scr, x, y);
306 return EINA_TRUE;
307}
308
309static Eina_Bool
310_deselect_all_items(Widget_Data *wd)
311{
312 if (!wd->selected) return EINA_FALSE;
313 while (wd->selected)
314 elm_gengrid_item_selected_set((Elm_Object_Item *) wd->selected->data,
315 EINA_FALSE);
316
317 return EINA_TRUE;
318}
319
320static Eina_Bool
321_item_multi_select_left(Widget_Data *wd)
322{
323 if (!wd->selected) return EINA_FALSE;
324
325 Elm_Object_Item *prev =
326 elm_gengrid_item_prev_get(wd->last_selected_item);
327 if (!prev) return EINA_TRUE;
328 if (elm_gengrid_item_selected_get(prev))
329 {
330 elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
331 wd->last_selected_item = prev;
332 elm_gengrid_item_show(wd->last_selected_item, ELM_GENGRID_ITEM_SCROLLTO_IN);
333 }
334 else
335 {
336 elm_gengrid_item_selected_set(prev, EINA_TRUE);
337 elm_gengrid_item_show(prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
338 }
339
340 return EINA_TRUE;
341}
342
343static Eina_Bool
344_item_multi_select_right(Widget_Data *wd)
345{
346 if (!wd->selected) return EINA_FALSE;
347
348 Elm_Object_Item *next =
349 elm_gengrid_item_next_get(wd->last_selected_item);
350 if (!next) return EINA_TRUE;
351 if (elm_gengrid_item_selected_get(next))
352 {
353 elm_gengrid_item_selected_set(wd->last_selected_item, EINA_FALSE);
354 wd->last_selected_item = next;
355 elm_gengrid_item_show(wd->last_selected_item, ELM_GENGRID_ITEM_SCROLLTO_IN);
356 }
357 else
358 {
359 elm_gengrid_item_selected_set(next, EINA_TRUE);
360 elm_gengrid_item_show(next, ELM_GENGRID_ITEM_SCROLLTO_IN);
361 }
362
363 return EINA_TRUE;
364}
365
366static Eina_Bool
367_item_multi_select_up(Widget_Data *wd)
368{
369 unsigned int i;
370 Eina_Bool r = EINA_TRUE;
371
372 if (!wd->selected) return EINA_FALSE;
373
374 for (i = 0; (r) && (i < wd->nmax); i++)
375 r &= _item_multi_select_left(wd);
376
377 return r;
378}
379
380static Eina_Bool
381_item_multi_select_down(Widget_Data *wd)
382{
383 unsigned int i;
384 Eina_Bool r = EINA_TRUE;
385
386 if (!wd->selected) return EINA_FALSE;
387
388 for (i = 0; (r) && (i < wd->nmax); i++)
389 r &= _item_multi_select_right(wd);
390
391 return r;
392}
393
394static Eina_Bool
395_item_single_select_up(Widget_Data *wd)
396{
397 unsigned int i;
398
399 Elm_Gen_Item *prev;
400
401 if (!wd->selected)
402 {
403 prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
404 while ((prev) && (prev->generation < wd->generation))
405 prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
406 elm_gengrid_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
407 elm_gengrid_item_show((Elm_Object_Item *) prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
408 return EINA_TRUE;
409 }
410 else
411 prev = (Elm_Gen_Item *) elm_gengrid_item_prev_get(wd->last_selected_item);
412
413 if (!prev) return EINA_FALSE;
414
415 for (i = 1; i < wd->nmax; i++)
416 {
417 Elm_Object_Item *tmp =
418 elm_gengrid_item_prev_get((Elm_Object_Item *) prev);
419 if (!tmp) return EINA_FALSE;
420 prev = (Elm_Gen_Item *) tmp;
421 }
422
423 _deselect_all_items(wd);
424
425 elm_gengrid_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
426 elm_gengrid_item_show((Elm_Object_Item *) prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
427 return EINA_TRUE;
428}
429
430static Eina_Bool
431_item_single_select_down(Widget_Data *wd)
432{
433 unsigned int i;
434
435 Elm_Gen_Item *next;
436
437 if (!wd->selected)
438 {
439 next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
440 while ((next) && (next->generation < wd->generation))
441 next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
442 elm_gengrid_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
443 elm_gengrid_item_show((Elm_Object_Item *) next, ELM_GENGRID_ITEM_SCROLLTO_IN);
444 return EINA_TRUE;
445 }
446 else
447 next = (Elm_Gen_Item *) elm_gengrid_item_next_get(wd->last_selected_item);
448
449 if (!next) return EINA_FALSE;
450
451 for (i = 1; i < wd->nmax; i++)
452 {
453 Elm_Object_Item *tmp =
454 elm_gengrid_item_next_get((Elm_Object_Item *) next);
455 if (!tmp) return EINA_FALSE;
456 next = (Elm_Gen_Item *) tmp;
457 }
458
459 _deselect_all_items(wd);
460
461 elm_gengrid_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
462 elm_gengrid_item_show((Elm_Object_Item *) next, ELM_GENGRID_ITEM_SCROLLTO_IN);
463 return EINA_TRUE;
464}
465
466static Eina_Bool
467_item_single_select_left(Widget_Data *wd)
468{
469 Elm_Gen_Item *prev;
470 if (!wd->selected)
471 {
472 prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
473 while ((prev) && (prev->generation < wd->generation))
474 prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
475 }
476 else
477 prev = (Elm_Gen_Item *) elm_gengrid_item_prev_get(wd->last_selected_item);
478
479 if (!prev) return EINA_FALSE;
480
481 _deselect_all_items(wd);
482
483 elm_gengrid_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
484 elm_gengrid_item_show((Elm_Object_Item *) prev, ELM_GENGRID_ITEM_SCROLLTO_IN);
485 return EINA_TRUE;
486}
487
488static Eina_Bool
489_item_single_select_right(Widget_Data *wd)
490{
491 Elm_Gen_Item *next;
492 if (!wd->selected)
493 {
494 next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
495 while ((next) && (next->generation < wd->generation))
496 next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
497 }
498 else
499 next = (Elm_Gen_Item *) elm_gengrid_item_next_get(wd->last_selected_item);
500
501 if (!next) return EINA_FALSE;
502
503 _deselect_all_items(wd);
504
505 elm_gengrid_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
506 elm_gengrid_item_show((Elm_Object_Item *) next, ELM_GENGRID_ITEM_SCROLLTO_IN);
507 return EINA_TRUE;
508}
509
510static void
511_on_focus_hook(void *data __UNUSED__,
512 Evas_Object *obj)
513{
514 Widget_Data *wd = elm_widget_data_get(obj);
515 if (!wd) return;
516 if (elm_widget_focus_get(obj))
517 {
518 edje_object_signal_emit(wd->obj, "elm,action,focus", "elm");
519 evas_object_focus_set(wd->obj, EINA_TRUE);
520 if ((wd->selected) && (!wd->last_selected_item))
521 wd->last_selected_item = eina_list_data_get(wd->selected);
522 }
523 else
524 {
525 edje_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
526 evas_object_focus_set(wd->obj, EINA_FALSE);
527 }
528}
529
530static void
531_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
532{
533 Widget_Data *wd = elm_widget_data_get(obj);
534 Elm_Gen_Item *it;
535 if (!wd) return;
536 elm_smart_scroller_mirrored_set(wd->scr, rtl);
537 if (!wd->items) return;
538 it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
539
540 while (it)
541 {
542 edje_object_mirrored_set(VIEW(it), rtl);
543 elm_gengrid_item_update((Elm_Object_Item *)it);
544 it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
545 }
546}
547
548static void
549_theme_hook(Evas_Object *obj)
550{
551 Widget_Data *wd = elm_widget_data_get(obj);
552 if (!wd) return;
553 _elm_widget_mirrored_reload(obj);
554 _mirrored_set(obj, elm_widget_mirrored_get(obj));
555 elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
556 elm_widget_style_get(obj));
557}
558
559static void
560_del_pre_hook(Evas_Object *obj)
561{
562 Widget_Data *wd = elm_widget_data_get(obj);
563 if (!wd) return;
564 elm_gengrid_clear(obj);
565 evas_object_del(wd->pan_smart);
566 wd->pan_smart = NULL;
567}
568
569static void
570_del_hook(Evas_Object *obj)
571{
572 Widget_Data *wd = elm_widget_data_get(obj);
573 if (wd->calc_job) ecore_job_del(wd->calc_job);
574 free(wd);
575}
576
577static void
578_signal_emit_hook(Evas_Object *obj,
579 const char *emission,
580 const char *source)
581{
582 Widget_Data *wd = elm_widget_data_get(obj);
583 if (!wd) return;
584 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
585 emission, source);
586}
587
588static void
589_signal_callback_add_hook(Evas_Object *obj,
590 const char *emission,
591 const char *source,
592 Edje_Signal_Cb func_cb,
593 void *data)
594{
595 Widget_Data *wd = elm_widget_data_get(obj);
596 if (!wd) return;
597 edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
598 emission, source, func_cb, data);
599}
600
601static void
602_signal_callback_del_hook(Evas_Object *obj,
603 const char *emission,
604 const char *source,
605 Edje_Signal_Cb func_cb,
606 void *data)
607{
608 Widget_Data *wd = elm_widget_data_get(obj);
609 if (!wd) return;
610 edje_object_signal_callback_del_full(elm_smart_scroller_edje_object_get(wd->scr),
611 emission, source, func_cb, data);
612}
613
614static void
615_mouse_move(void *data,
616 Evas *evas __UNUSED__,
617 Evas_Object *obj,
618 void *event_info)
619{
620 Elm_Gen_Item *it = data;
621 Evas_Event_Mouse_Move *ev = event_info;
622 Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
623 Evas_Coord ox, oy, ow, oh, it_scrl_x, it_scrl_y;
624
625 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
626 {
627 if (!it->wd->on_hold)
628 {
629 it->wd->on_hold = EINA_TRUE;
630 if (!it->wd->wasselected)
631 _item_unselect(it);
632 }
633 }
634 if ((it->dragging) && (it->down))
635 {
636 if (it->long_timer)
637 {
638 ecore_timer_del(it->long_timer);
639 it->long_timer = NULL;
640 }
641 evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
642 return;
643 }
644 if ((!it->down) || (it->wd->longpressed))
645 {
646 if (it->long_timer)
647 {
648 ecore_timer_del(it->long_timer);
649 it->long_timer = NULL;
650 }
651 if ((it->wd->reorder_mode) && (it->wd->reorder_it))
652 {
653 evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
654
655 it_scrl_x = ev->cur.canvas.x - it->wd->reorder_it->dx;
656 it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
657
658 if (it_scrl_x < ox) it->wd->reorder_item_x = ox;
659 else if (it_scrl_x + it->wd->item_width > ox + ow)
660 it->wd->reorder_item_x = ox + ow - it->wd->item_width;
661 else it->wd->reorder_item_x = it_scrl_x;
662
663 if (it_scrl_y < oy) it->wd->reorder_item_y = oy;
664 else if (it_scrl_y + it->wd->item_height > oy + oh)
665 it->wd->reorder_item_y = oy + oh - it->wd->item_height;
666 else it->wd->reorder_item_y = it_scrl_y;
667
668 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
669 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
670 }
671 return;
672 }
673 if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
674 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
675 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
676 x = ev->cur.canvas.x - x;
677 y = ev->cur.canvas.y - y;
678 dx = x - it->dx;
679 adx = dx;
680 if (adx < 0) adx = -dx;
681 dy = y - it->dy;
682 ady = dy;
683 if (ady < 0) ady = -dy;
684 minw /= 2;
685 minh /= 2;
686 if ((adx > minw) || (ady > minh))
687 {
688 const char *left_drag, *right_drag;
689 if (!elm_widget_mirrored_get(WIDGET(it)))
690 {
691 left_drag = SIG_DRAG_START_LEFT;
692 right_drag = SIG_DRAG_START_RIGHT;
693 }
694 else
695 {
696 left_drag = SIG_DRAG_START_RIGHT;
697 right_drag = SIG_DRAG_START_LEFT;
698 }
699
700 it->dragging = 1;
701 if (it->long_timer)
702 {
703 ecore_timer_del(it->long_timer);
704 it->long_timer = NULL;
705 }
706 if (!it->wd->wasselected)
707 _item_unselect(it);
708 if (dy < 0)
709 {
710 if (ady > adx)
711 evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_START_UP,
712 it);
713 else
714 {
715 if (dx < 0)
716 evas_object_smart_callback_call(WIDGET(it),
717 left_drag, it);
718 }
719 }
720 else
721 {
722 if (ady > adx)
723 evas_object_smart_callback_call(WIDGET(it),
724 SIG_DRAG_START_DOWN, it);
725 else
726 {
727 if (dx < 0)
728 evas_object_smart_callback_call(WIDGET(it),
729 left_drag, it);
730 else
731 evas_object_smart_callback_call(WIDGET(it),
732 right_drag, it);
733 }
734 }
735 }
736}
737
738static Eina_Bool
739_long_press(void *data)
740{
741 Elm_Gen_Item *it = data;
742
743 it->long_timer = NULL;
744 if (elm_widget_item_disabled_get(it)|| (it->dragging))
745 return ECORE_CALLBACK_CANCEL;
746 it->wd->longpressed = EINA_TRUE;
747 evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
748 if (it->wd->reorder_mode)
749 {
750 it->wd->reorder_it = it;
751 evas_object_raise(VIEW(it));
752 elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
753 elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
754 edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
755 }
756 return ECORE_CALLBACK_CANCEL;
757}
758
759static void
760_mouse_down(void *data,
761 Evas *evas __UNUSED__,
762 Evas_Object *obj,
763 void *event_info)
764{
765 Elm_Gen_Item *it = data;
766 Evas_Event_Mouse_Down *ev = event_info;
767 Evas_Coord x, y;
768
769 if (ev->button != 1) return;
770 it->down = 1;
771 it->dragging = 0;
772 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
773 it->dx = ev->canvas.x - x;
774 it->dy = ev->canvas.y - y;
775 it->wd->longpressed = EINA_FALSE;
776 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
777 else it->wd->on_hold = EINA_FALSE;
778 if (it->wd->on_hold) return;
779 it->wd->wasselected = it->selected;
780 _item_highlight(it);
781 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
782 {
783 evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
784 evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
785 }
786 if (it->long_timer) ecore_timer_del(it->long_timer);
787 if (it->realized)
788 it->long_timer = ecore_timer_add(_elm_config->longpress_timeout,
789 _long_press, it);
790 else
791 it->long_timer = NULL;
792}
793
794static void
795_mouse_up(void *data,
796 Evas *evas __UNUSED__,
797 Evas_Object *obj __UNUSED__,
798 void *event_info)
799{
800 Elm_Gen_Item *it = data;
801 Evas_Event_Mouse_Up *ev = event_info;
802 Eina_Bool dragged = EINA_FALSE;
803
804 if (ev->button != 1) return;
805 it->down = EINA_FALSE;
806 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
807 else it->wd->on_hold = EINA_FALSE;
808 if (it->long_timer)
809 {
810 ecore_timer_del(it->long_timer);
811 it->long_timer = NULL;
812 }
813 if (it->dragging)
814 {
815 it->dragging = EINA_FALSE;
816 evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
817 dragged = EINA_TRUE;
818 }
819 if (it->wd->on_hold)
820 {
821 it->wd->longpressed = EINA_FALSE;
822 it->wd->on_hold = EINA_FALSE;
823 return;
824 }
825 if ((it->wd->reorder_mode) && (it->wd->reorder_it))
826 {
827 evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it->wd->reorder_it);
828 it->wd->reorder_it = NULL;
829 it->wd->move_effect_enabled = EINA_FALSE;
830 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
831 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
832
833 elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
834 elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
835 edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
836 }
837 if (it->wd->longpressed)
838 {
839 it->wd->longpressed = EINA_FALSE;
840 if (!it->wd->wasselected) _item_unselect(it);
841 it->wd->wasselected = EINA_FALSE;
842 return;
843 }
844 if (dragged)
845 {
846 if (it->want_unrealize)
847 _elm_genlist_item_unrealize(it, EINA_FALSE);
848 }
849 if (elm_widget_item_disabled_get(it) || (dragged)) return;
850 if (it->wd->multi)
851 {
852 if (!it->selected)
853 {
854 _item_highlight(it);
855 it->sel_cb(it);
856 }
857 else _item_unselect(it);
858 }
859 else
860 {
861 if (!it->selected)
862 {
863 while (it->wd->selected)
864 _item_unselect(it->wd->selected->data);
865 }
866 else
867 {
868 const Eina_List *l, *l_next;
869 Elm_Gen_Item *item2;
870
871 EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, item2)
872 if (item2 != it) _item_unselect(item2);
873 }
874 _item_highlight(it);
875 it->sel_cb(it);
876 }
877}
878
879static void
880_item_highlight(Elm_Gen_Item *it)
881{
882 if ((it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
883 (!it->wd->highlight) || (it->highlighted) ||
884 (it->generation < it->wd->generation)) return;
885 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
886 it->highlighted = EINA_TRUE;
887}
888
889static void
890_elm_gengrid_item_index_update(Elm_Gen_Item *it)
891{
892 if (it->position_update)
893 {
894 evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
895 it->position_update = EINA_FALSE;
896 }
897}
898
899static void
900_item_realize(Elm_Gen_Item *it)
901{
902 char buf[1024];
903 char style[1024];
904
905 if ((it->realized) || (it->generation < it->wd->generation)) return;
906 VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
907 edje_object_scale_set(VIEW(it), elm_widget_scale_get(WIDGET(it)) *
908 _elm_config->scale);
909 edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(WIDGET(it)));
910 evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
911 elm_widget_sub_object_add(WIDGET(it), VIEW(it));
912 snprintf(style, sizeof(style), "item/%s",
913 it->itc->item_style ? it->itc->item_style : "default");
914 _elm_theme_object_set(WIDGET(it), VIEW(it), "gengrid", style,
915 elm_widget_style_get(WIDGET(it)));
916 it->spacer =
917 evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
918 evas_object_color_set(it->spacer, 0, 0, 0, 0);
919 elm_widget_sub_object_add(WIDGET(it), it->spacer);
920 evas_object_size_hint_min_set(it->spacer, 2 * _elm_config->scale, 1);
921 edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
922
923 if (it->itc->func.text_get)
924 {
925 const Eina_List *l;
926 const char *key;
927
928 it->texts =
929 elm_widget_stringlist_get(edje_object_data_get(VIEW(it),
930 "texts"));
931 EINA_LIST_FOREACH(it->texts, l, key)
932 {
933 char *s = it->itc->func.text_get
934 ((void *)it->base.data, WIDGET(it), key);
935 if (s)
936 {
937 edje_object_part_text_escaped_set(VIEW(it), key, s);
938 free(s);
939 }
940 }
941 }
942
943 if (it->itc->func.content_get)
944 {
945 const Eina_List *l;
946 const char *key;
947 Evas_Object *ic = NULL;
948
949 it->contents =
950 elm_widget_stringlist_get(edje_object_data_get(VIEW(it),
951 "contents"));
952 EINA_LIST_FOREACH(it->contents, l, key)
953 {
954 if (it->itc->func.content_get)
955 ic = it->itc->func.content_get
956 ((void *)it->base.data, WIDGET(it), key);
957 if (ic)
958 {
959 it->content_objs = eina_list_append(it->content_objs, ic);
960 edje_object_part_swallow(VIEW(it), key, ic);
961 evas_object_show(ic);
962 elm_widget_sub_object_add(WIDGET(it), ic);
963 }
964 }
965 }
966
967 if (it->itc->func.state_get)
968 {
969 const Eina_List *l;
970 const char *key;
971
972 it->states =
973 elm_widget_stringlist_get(edje_object_data_get(VIEW(it),
974 "states"));
975 EINA_LIST_FOREACH(it->states, l, key)
976 {
977 Eina_Bool on = it->itc->func.state_get
978 ((void *)it->base.data, WIDGET(it), l->data);
979 if (on)
980 {
981 snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
982 edje_object_signal_emit(VIEW(it), buf, "elm");
983 }
984 }
985 }
986
987 if (it->group)
988 {
989 if ((!it->wd->group_item_width) && (!it->wd->group_item_height))
990 {
991 edje_object_size_min_restricted_calc(VIEW(it),
992 &it->wd->group_item_width,
993 &it->wd->group_item_height,
994 it->wd->group_item_width,
995 it->wd->group_item_height);
996 }
997 }
998 else
999 {
1000 if ((!it->wd->item_width) && (!it->wd->item_height))
1001 {
1002 edje_object_size_min_restricted_calc(VIEW(it),
1003 &it->wd->item_width,
1004 &it->wd->item_height,
1005 it->wd->item_width,
1006 it->wd->item_height);
1007 elm_coords_finger_size_adjust(1, &it->wd->item_width,
1008 1, &it->wd->item_height);
1009 }
1010
1011 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1012 _mouse_down, it);
1013 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1014 _mouse_up, it);
1015 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1016 _mouse_move, it);
1017
1018 _elm_gengrid_item_index_update(it);
1019
1020 if (it->selected)
1021 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
1022 if (elm_widget_item_disabled_get(it))
1023 edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
1024 }
1025 evas_object_show(VIEW(it));
1026
1027 if (it->tooltip.content_cb)
1028 {
1029 elm_widget_item_tooltip_content_cb_set(it,
1030 it->tooltip.content_cb,
1031 it->tooltip.data, NULL);
1032 elm_widget_item_tooltip_style_set(it, it->tooltip.style);
1033 elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
1034 }
1035
1036 if (it->mouse_cursor)
1037 elm_widget_item_cursor_set(it, it->mouse_cursor);
1038
1039 it->realized = EINA_TRUE;
1040 it->want_unrealize = EINA_FALSE;
1041}
1042
1043static void
1044_item_unrealize_cb(Elm_Gen_Item *it)
1045{
1046 evas_object_del(VIEW(it));
1047 VIEW(it) = NULL;
1048 evas_object_del(it->spacer);
1049 it->spacer = NULL;
1050}
1051
1052static Eina_Bool
1053_reorder_item_move_animator_cb(void *data)
1054{
1055 Elm_Gen_Item *it = data;
1056 double tt, t;
1057 Evas_Coord dx, dy;
1058
1059 tt = REORDER_EFFECT_TIME;
1060 t = ((0.0 > (t = ecore_loop_time_get()-it->item->moving_effect_start_time)) ? 0.0 : t);
1061 dx = ((it->item->tx - it->item->ox) / 10) * _elm_config->scale;
1062 dy = ((it->item->ty - it->item->oy) / 10) * _elm_config->scale;
1063
1064 if (t <= tt)
1065 {
1066 it->item->rx += (1 * sin((t / tt) * (M_PI / 2)) * dx);
1067 it->item->ry += (1 * sin((t / tt) * (M_PI / 2)) * dy);
1068 }
1069 else
1070 {
1071 it->item->rx += dx;
1072 it->item->ry += dy;
1073 }
1074
1075 if ((((dx > 0) && (it->item->rx >= it->item->tx)) || ((dx <= 0) && (it->item->rx <= it->item->tx))) &&
1076 (((dy > 0) && (it->item->ry >= it->item->ty)) || ((dy <= 0) && (it->item->ry <= it->item->ty))))
1077 {
1078 evas_object_move(VIEW(it), it->item->tx, it->item->ty);
1079 if (it->group)
1080 {
1081 Evas_Coord vw, vh;
1082 evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &vw, &vh);
1083 if (it->wd->horizontal)
1084 evas_object_resize(VIEW(it), it->wd->group_item_width, vh);
1085 else
1086 evas_object_resize(VIEW(it), vw, it->wd->group_item_height);
1087 }
1088 else
1089 evas_object_resize(VIEW(it), it->wd->item_width, it->wd->item_height);
1090 it->item->moving = EINA_FALSE;
1091 it->item->item_reorder_move_animator = NULL;
1092 return ECORE_CALLBACK_CANCEL;
1093 }
1094
1095 evas_object_move(VIEW(it), it->item->rx, it->item->ry);
1096 if (it->group)
1097 {
1098 Evas_Coord vw, vh;
1099 evas_object_geometry_get(it->wd->pan_smart, NULL, NULL, &vw, &vh);
1100 if (it->wd->horizontal)
1101 evas_object_resize(VIEW(it), it->wd->group_item_width, vh);
1102 else
1103 evas_object_resize(VIEW(it), vw, it->wd->group_item_height);
1104 }
1105 else
1106 evas_object_resize(VIEW(it), it->wd->item_width, it->wd->item_height);
1107
1108 return ECORE_CALLBACK_RENEW;
1109}
1110
1111static void
1112_group_item_place(Pan *sd)
1113{
1114 Evas_Coord iw, ih, vw, vh;
1115 Eina_List *l;
1116 Eina_Bool was_realized;
1117 Elm_Gen_Item *it;
1118 evas_object_geometry_get(sd->wd->pan_smart, NULL, NULL, &vw, &vh);
1119 if (sd->wd->horizontal)
1120 {
1121 iw = sd->wd->group_item_width;
1122 ih = vh;
1123 }
1124 else
1125 {
1126 iw = vw;
1127 ih = sd->wd->group_item_height;
1128 }
1129 EINA_LIST_FOREACH(sd->wd->group_items, l, it)
1130 {
1131 was_realized = it->realized;
1132 if (it->item->group_realized)
1133 {
1134 _item_realize(it);
1135 if (!was_realized)
1136 evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1137 evas_object_move(VIEW(it), it->item->gx, it->item->gy);
1138 evas_object_resize(VIEW(it), iw, ih);
1139 evas_object_raise(VIEW(it));
1140 }
1141 else
1142 _elm_genlist_item_unrealize(it, EINA_FALSE);
1143 }
1144}
1145
1146
1147static void
1148_item_place(Elm_Gen_Item *it,
1149 Evas_Coord cx,
1150 Evas_Coord cy)
1151{
1152 Evas_Coord x, y, ox, oy, cvx, cvy, cvw, cvh, iw, ih, ww;
1153 Evas_Coord tch, tcw, alignw = 0, alignh = 0, vw, vh;
1154 Eina_Bool reorder_item_move_forward = EINA_FALSE;
1155 long items_count;
1156 it->x = cx;
1157 it->y = cy;
1158 evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &vw, &vh);
1159
1160 /* Preload rows/columns at each side of the Gengrid */
1161 cvx = ox - PRELOAD * it->wd->item_width;
1162 cvy = oy - PRELOAD * it->wd->item_height;
1163 cvw = vw + 2 * PRELOAD * it->wd->item_width;
1164 cvh = vh + 2 * PRELOAD * it->wd->item_height;
1165
1166 alignh = 0;
1167 alignw = 0;
1168
1169 items_count = it->wd->item_count - eina_list_count(it->wd->group_items) + it->wd->items_lost;
1170 if (it->wd->horizontal)
1171 {
1172 int columns, items_visible = 0, items_row;
1173
1174 if (it->wd->item_height > 0)
1175 items_visible = vh / it->wd->item_height;
1176 if (items_visible < 1)
1177 items_visible = 1;
1178
1179 columns = items_count / items_visible;
1180 if (items_count % items_visible)
1181 columns++;
1182
1183 tcw = (it->wd->item_width * columns) + (it->wd->group_item_width * eina_list_count(it->wd->group_items));
1184 alignw = (vw - tcw) * it->wd->align_x;
1185
1186 items_row = items_visible;
1187 if ((unsigned int)items_row > it->wd->item_count)
1188 items_row = it->wd->item_count;
1189 if (it->wd->filled
1190 && (unsigned int)it->wd->nmax > (unsigned int)it->wd->item_count)
1191 tch = it->wd->nmax * it->wd->item_height;
1192 else
1193 tch = items_row * it->wd->item_height;
1194 alignh = (vh - tch) * it->wd->align_y;
1195 }
1196 else
1197 {
1198 unsigned int rows, items_visible = 0, items_col;
1199
1200 if (it->wd->item_width > 0)
1201 items_visible = vw / it->wd->item_width;
1202 if (items_visible < 1)
1203 items_visible = 1;
1204
1205 rows = items_count / items_visible;
1206 if (items_count % items_visible)
1207 rows++;
1208
1209 tch = (it->wd->item_height * rows) + (it->wd->group_item_height * eina_list_count(it->wd->group_items));
1210 alignh = (vh - tch) * it->wd->align_y;
1211
1212 items_col = items_visible;
1213 if (items_col > it->wd->item_count)
1214 items_col = it->wd->item_count;
1215 if (it->wd->filled
1216 && (unsigned int)it->wd->nmax > (unsigned int)it->wd->item_count)
1217 tcw = it->wd->nmax * it->wd->item_width;
1218 else
1219 tcw = items_col * it->wd->item_width;
1220 alignw = (vw - tcw) * it->wd->align_x;
1221 }
1222
1223 if (it->group)
1224 {
1225 if (it->wd->horizontal)
1226 {
1227 x = (((cx - it->item->prev_group) * it->wd->item_width) + (it->item->prev_group * it->wd->group_item_width)) - it->wd->pan_x + ox + alignw;
1228 y = oy;
1229 iw = it->wd->group_item_width;
1230 ih = vh;
1231 }
1232 else
1233 {
1234 x = ox;
1235 y = (((cy - it->item->prev_group) * it->wd->item_height) + (it->item->prev_group * it->wd->group_item_height)) - it->wd->pan_y + oy + alignh;
1236 iw = vw;
1237 ih = it->wd->group_item_height;
1238 }
1239 it->item->gx = x;
1240 it->item->gy = y;
1241 }
1242 else
1243 {
1244 if (it->wd->horizontal)
1245 {
1246 x = (((cx - it->item->prev_group) * it->wd->item_width) + (it->item->prev_group * it->wd->group_item_width)) - it->wd->pan_x + ox + alignw;
1247 y = (cy * it->wd->item_height) - it->wd->pan_y + oy + alignh;
1248 }
1249 else
1250 {
1251 x = (cx * it->wd->item_width) - it->wd->pan_x + ox + alignw;
1252 y = (((cy - it->item->prev_group) * it->wd->item_height) + (it->item->prev_group * it->wd->group_item_height)) - it->wd->pan_y + oy + alignh;
1253 }
1254 if (elm_widget_mirrored_get(WIDGET(it)))
1255 { /* Switch items side and componsate for pan_x when in RTL mode */
1256 evas_object_geometry_get(WIDGET(it), NULL, NULL, &ww, NULL);
1257 x = ww - x - it->wd->item_width - it->wd->pan_x - it->wd->pan_x;
1258 }
1259 iw = it->wd->item_width;
1260 ih = it->wd->item_height;
1261 }
1262
1263 Eina_Bool was_realized = it->realized;
1264 if (ELM_RECTS_INTERSECT(x, y, iw, ih, cvx, cvy, cvw, cvh))
1265 {
1266 _item_realize(it);
1267 if (!was_realized)
1268 evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
1269 if (it->parent)
1270 {
1271 if (it->wd->horizontal)
1272 {
1273 if (it->parent->item->gx < ox)
1274 {
1275 it->parent->item->gx = x + it->wd->item_width - it->wd->group_item_width;
1276 if (it->parent->item->gx > ox)
1277 it->parent->item->gx = ox;
1278 }
1279 it->parent->item->group_realized = EINA_TRUE;
1280 }
1281 else
1282 {
1283 if (it->parent->item->gy < oy)
1284 {
1285 it->parent->item->gy = y + it->wd->item_height - it->wd->group_item_height;
1286 if (it->parent->item->gy > oy)
1287 it->parent->item->gy = oy;
1288 }
1289 it->parent->item->group_realized = EINA_TRUE;
1290 }
1291 }
1292 if (it->wd->reorder_mode)
1293 {
1294 if (it->wd->reorder_it)
1295 {
1296 if (it->item->moving) return;
1297
1298 if (!it->wd->move_effect_enabled)
1299 {
1300 it->item->ox = x;
1301 it->item->oy = y;
1302 }
1303 if (it->wd->reorder_it == it)
1304 {
1305 evas_object_move(VIEW(it),
1306 it->wd->reorder_item_x, it->wd->reorder_item_y);
1307 evas_object_resize(VIEW(it), iw, ih);
1308 return;
1309 }
1310 else
1311 {
1312 if (it->wd->move_effect_enabled)
1313 {
1314 if ((it->item->ox != x) || (it->item->oy != y))
1315 {
1316 if (((it->wd->old_pan_x == it->wd->pan_x) && (it->wd->old_pan_y == it->wd->pan_y)) ||
1317 ((it->wd->old_pan_x != it->wd->pan_x) && !(it->item->ox - it->wd->pan_x + it->wd->old_pan_x == x)) ||
1318 ((it->wd->old_pan_y != it->wd->pan_y) && !(it->item->oy - it->wd->pan_y + it->wd->old_pan_y == y)))
1319 {
1320 it->item->tx = x;
1321 it->item->ty = y;
1322 it->item->rx = it->item->ox;
1323 it->item->ry = it->item->oy;
1324 it->item->moving = EINA_TRUE;
1325 it->item->moving_effect_start_time = ecore_loop_time_get();
1326 it->item->item_reorder_move_animator = ecore_animator_add(_reorder_item_move_animator_cb, it);
1327 return;
1328 }
1329 }
1330 }
1331
1332 /* need fix here */
1333 Evas_Coord nx, ny, nw, nh;
1334 if (it->group)
1335 {
1336 if (it->wd->horizontal)
1337 {
1338 nx = x + (it->wd->group_item_width / 2);
1339 ny = y;
1340 nw = 1;
1341 nh = vh;
1342 }
1343 else
1344 {
1345 nx = x;
1346 ny = y + (it->wd->group_item_height / 2);
1347 nw = vw;
1348 nh = 1;
1349 }
1350 }
1351 else
1352 {
1353 nx = x + (it->wd->item_width / 2);
1354 ny = y + (it->wd->item_height / 2);
1355 nw = 1;
1356 nh = 1;
1357 }
1358
1359 if ( ELM_RECTS_INTERSECT(it->wd->reorder_item_x, it->wd->reorder_item_y,
1360 it->wd->item_width, it->wd->item_height,
1361 nx, ny, nw, nh))
1362 {
1363 if (it->wd->horizontal)
1364 {
1365 if ((it->wd->nmax * it->wd->reorder_it->x + it->wd->reorder_it->y) >
1366 (it->wd->nmax * it->x + it->y))
1367 reorder_item_move_forward = EINA_TRUE;
1368 }
1369 else
1370 {
1371 if ((it->wd->nmax * it->wd->reorder_it->y + it->wd->reorder_it->x) >
1372 (it->wd->nmax * it->y + it->x))
1373 reorder_item_move_forward = EINA_TRUE;
1374 }
1375
1376 it->wd->items = eina_inlist_remove(it->wd->items,
1377 EINA_INLIST_GET(it->wd->reorder_it));
1378 if (reorder_item_move_forward)
1379 it->wd->items = eina_inlist_prepend_relative(it->wd->items,
1380 EINA_INLIST_GET(it->wd->reorder_it),
1381 EINA_INLIST_GET(it));
1382 else
1383 it->wd->items = eina_inlist_append_relative(it->wd->items,
1384 EINA_INLIST_GET(it->wd->reorder_it),
1385 EINA_INLIST_GET(it));
1386
1387 it->wd->reorder_item_changed = EINA_TRUE;
1388 it->wd->move_effect_enabled = EINA_TRUE;
1389 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1390 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1391
1392 return;
1393 }
1394 }
1395 }
1396 else if (it->item->item_reorder_move_animator)
1397 {
1398 ecore_animator_del(it->item->item_reorder_move_animator);
1399 it->item->item_reorder_move_animator = NULL;
1400 it->item->moving = EINA_FALSE;
1401 }
1402 }
1403 if (!it->group)
1404 {
1405 evas_object_move(VIEW(it), x, y);
1406 evas_object_resize(VIEW(it), iw, ih);
1407 }
1408 else
1409 it->item->group_realized = EINA_TRUE;
1410 }
1411 else
1412 {
1413 if (!it->group)
1414 _elm_genlist_item_unrealize(it, EINA_FALSE);
1415 else
1416 it->item->group_realized = EINA_FALSE;
1417 }
1418}
1419
1420static void
1421_item_position_update(Eina_Inlist *list, int idx)
1422{
1423 Elm_Gen_Item *it;
1424
1425 EINA_INLIST_FOREACH(list, it)
1426 {
1427 it->position = idx++;
1428 it->position_update = EINA_TRUE;
1429 }
1430}
1431
1432static void
1433_item_del(Elm_Gen_Item *it)
1434{
1435 Evas_Object *obj = WIDGET(it);
1436
1437 evas_event_freeze(evas_object_evas_get(obj));
1438 it->wd->selected = eina_list_remove(it->wd->selected, it);
1439 if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
1440 _elm_genlist_item_del_serious(it);
1441 elm_gengrid_item_class_unref((Elm_Gengrid_Item_Class *)it->itc);
1442 evas_event_thaw(evas_object_evas_get(obj));
1443 evas_event_thaw_eval(evas_object_evas_get(obj));
1444}
1445
1446static void
1447_item_unselect(Elm_Gen_Item *it)
1448{
1449 if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
1450 edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
1451 it->highlighted = EINA_FALSE;
1452 if (it->selected)
1453 {
1454 it->selected = EINA_FALSE;
1455 it->wd->selected = eina_list_remove(it->wd->selected, it);
1456 evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
1457 }
1458}
1459
1460static void
1461_calc_job(void *data)
1462{
1463 Widget_Data *wd = data;
1464 Evas_Coord minw = 0, minh = 0, nmax = 0, cvw, cvh;
1465 Elm_Gen_Item *it, *group_item = NULL;
1466 int count_group = 0;
1467 long count = 0;
1468 wd->items_lost = 0;
1469
1470 evas_object_geometry_get(wd->pan_smart, NULL, NULL, &cvw, &cvh);
1471 if ((cvw != 0) || (cvh != 0))
1472 {
1473 if ((wd->horizontal) && (wd->item_height > 0))
1474 nmax = cvh / wd->item_height;
1475 else if (wd->item_width > 0)
1476 nmax = cvw / wd->item_width;
1477
1478 if (nmax < 1)
1479 nmax = 1;
1480
1481 EINA_INLIST_FOREACH(wd->items, it)
1482 {
1483 if (it->item->prev_group != count_group)
1484 it->item->prev_group = count_group;
1485 if (it->group)
1486 {
1487 count = count % nmax;
1488 if (count)
1489 wd->items_lost += nmax - count;
1490 //printf("%d items and I lost %d\n", count, wd->items_lost);
1491 count_group++;
1492 if (count) count = 0;
1493 group_item = it;
1494 }
1495 else
1496 {
1497 if (it->parent != group_item)
1498 it->parent = group_item;
1499 count++;
1500 }
1501 }
1502 count = wd->item_count + wd->items_lost - count_group;
1503 if (wd->horizontal)
1504 {
1505 minw = (ceil(count / (float)nmax) * wd->item_width) + (count_group * wd->group_item_width);
1506 minh = nmax * wd->item_height;
1507 }
1508 else
1509 {
1510 minw = nmax * wd->item_width;
1511 minh = (ceil(count / (float)nmax) * wd->item_height) + (count_group * wd->group_item_height);
1512 }
1513
1514 if ((minw != wd->minw) || (minh != wd->minh))
1515 {
1516 wd->minh = minh;
1517 wd->minw = minw;
1518 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
1519 }
1520
1521 wd->nmax = nmax;
1522 evas_object_smart_changed(wd->pan_smart);
1523 }
1524 wd->calc_job = NULL;
1525}
1526
1527static void
1528_pan_add(Evas_Object *obj)
1529{
1530 Pan *sd;
1531 Evas_Object_Smart_Clipped_Data *cd;
1532
1533 _pan_sc.add(obj);
1534 cd = evas_object_smart_data_get(obj);
1535 sd = ELM_NEW(Pan);
1536 if (!sd) return;
1537 sd->__clipped_data = *cd;
1538 free(cd);
1539 evas_object_smart_data_set(obj, sd);
1540}
1541
1542static void
1543_pan_del(Evas_Object *obj)
1544{
1545 Pan *sd = evas_object_smart_data_get(obj);
1546
1547 if (!sd) return;
1548 _pan_sc.del(obj);
1549}
1550
1551static void
1552_pan_set(Evas_Object *obj,
1553 Evas_Coord x,
1554 Evas_Coord y)
1555{
1556 Pan *sd = evas_object_smart_data_get(obj);
1557 if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
1558 sd->wd->pan_x = x;
1559 sd->wd->pan_y = y;
1560 evas_object_smart_changed(obj);
1561}
1562
1563static void
1564_pan_get(Evas_Object *obj,
1565 Evas_Coord *x,
1566 Evas_Coord *y)
1567{
1568 Pan *sd = evas_object_smart_data_get(obj);
1569 if (x) *x = sd->wd->pan_x;
1570 if (y) *y = sd->wd->pan_y;
1571}
1572
1573static void
1574_pan_child_size_get(Evas_Object *obj,
1575 Evas_Coord *w,
1576 Evas_Coord *h)
1577{
1578 Pan *sd = evas_object_smart_data_get(obj);
1579 if (w) *w = sd->wd->minw;
1580 if (h) *h = sd->wd->minh;
1581}
1582
1583static void
1584_pan_max_get(Evas_Object *obj,
1585 Evas_Coord *x,
1586 Evas_Coord *y)
1587{
1588 Pan *sd = evas_object_smart_data_get(obj);
1589 Evas_Coord ow, oh;
1590
1591 if (!sd) return;
1592 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1593 if (x)
1594 *x = (ow < sd->wd->minw) ? sd->wd->minw - ow : 0;
1595 if (y)
1596 *y = (oh < sd->wd->minh) ? sd->wd->minh - oh : 0;
1597}
1598
1599static void
1600_pan_min_get(Evas_Object *obj,
1601 Evas_Coord *x,
1602 Evas_Coord *y)
1603{
1604 Pan *sd = evas_object_smart_data_get(obj);
1605 Evas_Coord mx = 0, my = 0;
1606
1607 if (!sd) return;
1608 _pan_max_get(obj, &mx, &my);
1609 if (x)
1610 *x = -mx * sd->wd->align_x;
1611 if (y)
1612 *y = -my * sd->wd->align_y;
1613}
1614
1615static void
1616_pan_resize(Evas_Object *obj,
1617 Evas_Coord w,
1618 Evas_Coord h)
1619{
1620 Pan *sd = evas_object_smart_data_get(obj);
1621 Evas_Coord ow, oh;
1622
1623 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
1624 if ((ow == w) && (oh == h)) return;
1625 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1626 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1627}
1628
1629static void
1630_pan_calculate(Evas_Object *obj)
1631{
1632 Pan *sd = evas_object_smart_data_get(obj);
1633 Evas_Coord cx = 0, cy = 0;
1634 Elm_Gen_Item *it;
1635
1636 if (!sd) return;
1637 if (!sd->wd->nmax) return;
1638
1639 sd->wd->reorder_item_changed = EINA_FALSE;
1640
1641 EINA_INLIST_FOREACH(sd->wd->items, it)
1642 {
1643 if (it->group)
1644 {
1645 if (sd->wd->horizontal)
1646 {
1647 if (cy)
1648 {
1649 cx++;
1650 cy = 0;
1651 }
1652 }
1653 else
1654 {
1655 if (cx)
1656 {
1657 cx = 0;
1658 cy++;
1659 }
1660 }
1661 }
1662 _item_place(it, cx, cy);
1663 if (sd->wd->reorder_item_changed) return;
1664 if (it->group)
1665 {
1666 if (sd->wd->horizontal)
1667 {
1668 cx++;
1669 cy = 0;
1670 }
1671 else
1672 {
1673 cx = 0;
1674 cy++;
1675 }
1676 }
1677 else
1678 {
1679 if (sd->wd->horizontal)
1680 {
1681 cy = (cy + 1) % sd->wd->nmax;
1682 if (!cy) cx++;
1683 }
1684 else
1685 {
1686 cx = (cx + 1) % sd->wd->nmax;
1687 if (!cx) cy++;
1688 }
1689 }
1690 }
1691 _group_item_place(sd);
1692
1693
1694 if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
1695 {
1696 if (!sd->wd->reorder_item_changed)
1697 {
1698 sd->wd->old_pan_x = sd->wd->pan_x;
1699 sd->wd->old_pan_y = sd->wd->pan_y;
1700 }
1701 sd->wd->move_effect_enabled = EINA_FALSE;
1702 }
1703 evas_object_smart_callback_call(sd->wd->obj, SIG_CHANGED, NULL);
1704}
1705
1706static void
1707_pan_move(Evas_Object *obj,
1708 Evas_Coord x __UNUSED__,
1709 Evas_Coord y __UNUSED__)
1710{
1711 Pan *sd = evas_object_smart_data_get(obj);
1712 if (!sd) return;
1713 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
1714 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
1715}
1716
1717static void
1718_hold_on(void *data __UNUSED__,
1719 Evas_Object *obj,
1720 void *event_info __UNUSED__)
1721{
1722 Widget_Data *wd = elm_widget_data_get(obj);
1723 if (!wd) return;
1724 elm_smart_scroller_hold_set(wd->scr, 1);
1725}
1726
1727static void
1728_hold_off(void *data __UNUSED__,
1729 Evas_Object *obj,
1730 void *event_info __UNUSED__)
1731{
1732 Widget_Data *wd = elm_widget_data_get(obj);
1733 if (!wd) return;
1734 elm_smart_scroller_hold_set(wd->scr, 0);
1735}
1736
1737static void
1738_freeze_on(void *data __UNUSED__,
1739 Evas_Object *obj,
1740 void *event_info __UNUSED__)
1741{
1742 Widget_Data *wd = elm_widget_data_get(obj);
1743 if (!wd) return;
1744 elm_smart_scroller_freeze_set(wd->scr, 1);
1745}
1746
1747static void
1748_freeze_off(void *data __UNUSED__,
1749 Evas_Object *obj,
1750 void *event_info __UNUSED__)
1751{
1752 Widget_Data *wd = elm_widget_data_get(obj);
1753 if (!wd) return;
1754 elm_smart_scroller_freeze_set(wd->scr, 0);
1755}
1756
1757static void
1758_scr_anim_start(void *data,
1759 Evas_Object *obj __UNUSED__,
1760 void *event_info __UNUSED__)
1761{
1762 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
1763}
1764
1765static void
1766_scr_anim_stop(void *data,
1767 Evas_Object *obj __UNUSED__,
1768 void *event_info __UNUSED__)
1769{
1770 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
1771}
1772
1773static void
1774_scr_drag_start(void *data,
1775 Evas_Object *obj __UNUSED__,
1776 void *event_info __UNUSED__)
1777{
1778 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
1779}
1780
1781static void
1782_scr_drag_stop(void *data,
1783 Evas_Object *obj __UNUSED__,
1784 void *event_info __UNUSED__)
1785{
1786 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
1787}
1788
1789static void
1790_edge_left(void *data,
1791 Evas_Object *scr __UNUSED__,
1792 void *event_info __UNUSED__)
1793{
1794 evas_object_smart_callback_call(data, SIG_EDGE_LEFT, NULL);
1795}
1796
1797static void
1798_edge_right(void *data,
1799 Evas_Object *scr __UNUSED__,
1800 void *event_info __UNUSED__)
1801{
1802 evas_object_smart_callback_call(data, SIG_EDGE_RIGHT, NULL);
1803}
1804
1805static void
1806_edge_top(void *data,
1807 Evas_Object *scr __UNUSED__,
1808 void *event_info __UNUSED__)
1809{
1810 evas_object_smart_callback_call(data, SIG_EDGE_TOP, NULL);
1811}
1812
1813static void
1814_edge_bottom(void *data,
1815 Evas_Object *scr __UNUSED__,
1816 void *event_info __UNUSED__)
1817{
1818 evas_object_smart_callback_call(data, SIG_EDGE_BOTTOM, NULL);
1819}
1820
1821static void
1822_scr_scroll(void *data,
1823 Evas_Object *obj __UNUSED__,
1824 void *event_info __UNUSED__)
1825{
1826 evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
1827}
1828
1829static int
1830_elm_gengrid_item_compare(const void *data, const void *data1)
1831{
1832 Elm_Gen_Item *it, *item1;
1833 it = ELM_GEN_ITEM_FROM_INLIST(data);
1834 item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
1835 return it->wd->item_compare_cb(it, item1);
1836}
1837
1838static void
1839_item_disable_hook(Elm_Object_Item *it)
1840{
1841 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
1842
1843 if (_it->generation < _it->wd->generation) return;
1844
1845 if (_it->realized)
1846 {
1847 if (elm_widget_item_disabled_get(_it))
1848 edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
1849 else
1850 edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
1851 }
1852}
1853
1854static void
1855_item_del_pre_hook(Elm_Object_Item *it)
1856{
1857 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
1858 if ((_it->relcount > 0) || (_it->walking > 0))
1859 {
1860 _elm_genlist_item_del_notserious(_it);
1861 return;
1862 }
1863
1864 _item_del(_it);
1865}
1866
1867static Elm_Gen_Item *
1868_item_new(Widget_Data *wd,
1869 const Elm_Gengrid_Item_Class *itc,
1870 const void *data,
1871 Evas_Smart_Cb func,
1872 const void *func_data)
1873{
1874 Elm_Gen_Item *it;
1875
1876 it = _elm_genlist_item_new(wd, itc, data, NULL, func, func_data);
1877 if (!it) return NULL;
1878 elm_widget_item_disable_hook_set(it, _item_disable_hook);
1879 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1880 elm_gengrid_item_class_ref((Elm_Gengrid_Item_Class *)itc);
1881 it->item = ELM_NEW(Elm_Gen_Item_Type);
1882 wd->item_count++;
1883 it->group = it->itc->item_style && (!strcmp(it->itc->item_style, "group_index"));
1884 ELM_GEN_ITEM_SETUP(it);
1885
1886 return it;
1887}
1888
1889EAPI Evas_Object *
1890elm_gengrid_add(Evas_Object *parent)
1891{
1892 Evas_Object *obj;
1893 Evas *e;
1894 Widget_Data *wd;
1895 static Evas_Smart *smart = NULL;
1896 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1897
1898 if (!smart)
1899 {
1900 static Evas_Smart_Class sc;
1901
1902 evas_object_smart_clipped_smart_set(&_pan_sc);
1903 sc = _pan_sc;
1904 sc.name = "elm_gengrid_pan";
1905 sc.version = EVAS_SMART_CLASS_VERSION;
1906 sc.add = _pan_add;
1907 sc.del = _pan_del;
1908 sc.resize = _pan_resize;
1909 sc.move = _pan_move;
1910 sc.calculate = _pan_calculate;
1911 if (!(smart = evas_smart_class_new(&sc))) return NULL;
1912 }
1913
1914 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1915
1916 ELM_SET_WIDTYPE(widtype, "gengrid");
1917 ELM_GEN_SETUP(wd);
1918 elm_widget_type_set(obj, "gengrid");
1919 elm_widget_sub_object_add(parent, obj);
1920 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1921 elm_widget_data_set(obj, wd);
1922 elm_widget_del_hook_set(obj, _del_hook);
1923 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1924 elm_widget_theme_hook_set(obj, _theme_hook);
1925 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1926 elm_widget_can_focus_set(obj, EINA_TRUE);
1927 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
1928 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
1929 elm_widget_event_hook_set(obj, _event_hook);
1930
1931 wd->generation = 1;
1932 wd->scr = elm_smart_scroller_add(e);
1933 elm_smart_scroller_widget_set(wd->scr, obj);
1934 elm_smart_scroller_object_theme_set(obj, wd->scr, "gengrid", "base",
1935 "default");
1936 elm_smart_scroller_bounce_allow_set(wd->scr, bounce,
1937 _elm_config->thumbscroll_bounce_enable);
1938 elm_widget_resize_object_set(obj, wd->scr);
1939
1940 evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
1941 evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
1942 evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
1943 evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
1944 evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
1945 evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
1946 evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
1947 evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom,
1948 obj);
1949 evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
1950
1951 wd->obj = obj;
1952 wd->align_x = 0.5;
1953 wd->align_y = 0.5;
1954 wd->h_bounce = bounce;
1955 wd->v_bounce = bounce;
1956 wd->highlight = EINA_TRUE;
1957
1958 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1959 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1960 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1961 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1962
1963 wd->pan_smart = evas_object_smart_add(e, smart);
1964 wd->pan = evas_object_smart_data_get(wd->pan_smart);
1965 wd->pan->wd = wd;
1966
1967 elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
1968 _pan_set, _pan_get, _pan_max_get,
1969 _pan_min_get, _pan_child_size_get);
1970
1971 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1972
1973 _mirrored_set(obj, elm_widget_mirrored_get(obj));
1974 return obj;
1975}
1976
1977EAPI void
1978elm_gengrid_item_size_set(Evas_Object *obj,
1979 Evas_Coord w,
1980 Evas_Coord h)
1981{
1982 ELM_CHECK_WIDTYPE(obj, widtype);
1983 Widget_Data *wd = elm_widget_data_get(obj);
1984 if (!wd) return;
1985 if ((wd->item_width == w) && (wd->item_height == h)) return;
1986 wd->item_width = w;
1987 wd->item_height = h;
1988 if (wd->calc_job) ecore_job_del(wd->calc_job);
1989 wd->calc_job = ecore_job_add(_calc_job, wd);
1990}
1991
1992EAPI void
1993elm_gengrid_item_size_get(const Evas_Object *obj,
1994 Evas_Coord *w,
1995 Evas_Coord *h)
1996{
1997 ELM_CHECK_WIDTYPE(obj, widtype);
1998 Widget_Data *wd = elm_widget_data_get(obj);
1999 if (!wd) return;
2000 if (w) *w = wd->item_width;
2001 if (h) *h = wd->item_height;
2002}
2003
2004EAPI void
2005elm_gengrid_group_item_size_set(Evas_Object *obj,
2006 Evas_Coord w,
2007 Evas_Coord h)
2008{
2009 ELM_CHECK_WIDTYPE(obj, widtype);
2010 Widget_Data *wd = elm_widget_data_get(obj);
2011 if (!wd) return;
2012 if ((wd->group_item_width == w) && (wd->group_item_height == h)) return;
2013 wd->group_item_width = w;
2014 wd->group_item_height = h;
2015 if (wd->calc_job) ecore_job_del(wd->calc_job);
2016 wd->calc_job = ecore_job_add(_calc_job, wd);
2017}
2018
2019EAPI void
2020elm_gengrid_group_item_size_get(const Evas_Object *obj,
2021 Evas_Coord *w,
2022 Evas_Coord *h)
2023{
2024 ELM_CHECK_WIDTYPE(obj, widtype);
2025 Widget_Data *wd = elm_widget_data_get(obj);
2026 if (!wd) return;
2027 if (w) *w = wd->group_item_width;
2028 if (h) *h = wd->group_item_height;
2029}
2030
2031EAPI void
2032elm_gengrid_align_set(Evas_Object *obj,
2033 double align_x,
2034 double align_y)
2035{
2036 ELM_CHECK_WIDTYPE(obj, widtype);
2037
2038 Widget_Data *wd = elm_widget_data_get(obj);
2039 double old_h = wd->align_x, old_y = wd->align_y;
2040
2041 if (align_x > 1.0)
2042 align_x = 1.0;
2043 else if (align_x < 0.0)
2044 align_x = 0.0;
2045 wd->align_x = align_x;
2046
2047 if (align_y > 1.0)
2048 align_y = 1.0;
2049 else if (align_y < 0.0)
2050 align_y = 0.0;
2051 wd->align_y = align_y;
2052
2053 if ((old_h != wd->align_x) || (old_y != wd->align_y))
2054 evas_object_smart_calculate(wd->pan_smart);
2055}
2056
2057EAPI void
2058elm_gengrid_align_get(const Evas_Object *obj,
2059 double *align_x,
2060 double *align_y)
2061{
2062 ELM_CHECK_WIDTYPE(obj, widtype);
2063 Widget_Data *wd = elm_widget_data_get(obj);
2064 if (align_x) *align_x = wd->align_x;
2065 if (align_y) *align_y = wd->align_y;
2066}
2067
2068EAPI Elm_Object_Item *
2069elm_gengrid_item_append(Evas_Object *obj,
2070 const Elm_Gengrid_Item_Class *itc,
2071 const void *data,
2072 Evas_Smart_Cb func,
2073 const void *func_data)
2074{
2075 Elm_Gen_Item *it;
2076 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2077 Widget_Data *wd = elm_widget_data_get(obj);
2078 if (!wd) return NULL;
2079
2080 it = _item_new(wd, itc, data, func, func_data);
2081 if (!it) return NULL;
2082 wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
2083 it->position = eina_inlist_count(wd->items);
2084 it->position_update = EINA_TRUE;
2085
2086 if (it->group)
2087 wd->group_items = eina_list_prepend(wd->group_items, it);
2088
2089 if (wd->calc_job) ecore_job_del(wd->calc_job);
2090 wd->calc_job = ecore_job_add(_calc_job, wd);
2091
2092 return (Elm_Object_Item *)it;
2093}
2094
2095EAPI Elm_Object_Item *
2096elm_gengrid_item_prepend(Evas_Object *obj,
2097 const Elm_Gengrid_Item_Class *itc,
2098 const void *data,
2099 Evas_Smart_Cb func,
2100 const void *func_data)
2101{
2102 Elm_Gen_Item *it;
2103 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2104 Widget_Data *wd = elm_widget_data_get(obj);
2105 if (!wd) return NULL;
2106
2107 it = _item_new(wd, itc, data, func, func_data);
2108 if (!it) return NULL;
2109 wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
2110 _item_position_update(wd->items, 0);
2111
2112 if (it->group)
2113 wd->group_items = eina_list_append(wd->group_items, it);
2114
2115 if (wd->calc_job) ecore_job_del(wd->calc_job);
2116 wd->calc_job = ecore_job_add(_calc_job, wd);
2117
2118 return (Elm_Object_Item *)it;
2119}
2120
2121EAPI Elm_Object_Item *
2122elm_gengrid_item_insert_before(Evas_Object *obj,
2123 const Elm_Gengrid_Item_Class *itc,
2124 const void *data,
2125 Elm_Object_Item *relative,
2126 Evas_Smart_Cb func,
2127 const void *func_data)
2128{
2129 Elm_Gen_Item *it;
2130 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2131 ELM_OBJ_ITEM_CHECK_OR_RETURN(relative, NULL);
2132 Widget_Data *wd = elm_widget_data_get(obj);
2133 if (!wd) return NULL;
2134
2135 it = _item_new(wd, itc, data, func, func_data);
2136 if (!it) return NULL;
2137 wd->items = eina_inlist_prepend_relative
2138 (wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET((Elm_Gen_Item *) relative));
2139 Eina_Inlist *tmp = eina_inlist_find(wd->items, EINA_INLIST_GET(it));
2140 _item_position_update(tmp, ((Elm_Gen_Item *)relative)->position);
2141
2142 if (it->group)
2143 wd->group_items = eina_list_append_relative(wd->group_items, it, ((Elm_Gen_Item *) relative)->parent);
2144
2145 if (wd->calc_job) ecore_job_del(wd->calc_job);
2146 wd->calc_job = ecore_job_add(_calc_job, wd);
2147
2148 return (Elm_Object_Item *)it;
2149}
2150
2151EAPI Elm_Object_Item *
2152elm_gengrid_item_insert_after(Evas_Object *obj,
2153 const Elm_Gengrid_Item_Class *itc,
2154 const void *data,
2155 Elm_Object_Item *relative,
2156 Evas_Smart_Cb func,
2157 const void *func_data)
2158{
2159 Elm_Gen_Item *it;
2160 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2161 ELM_OBJ_ITEM_CHECK_OR_RETURN(relative, NULL);
2162 Widget_Data *wd = elm_widget_data_get(obj);
2163 if (!wd) return NULL;
2164
2165 it = _item_new(wd, itc, data, func, func_data);
2166 if (!it) return NULL;
2167 wd->items = eina_inlist_append_relative
2168 (wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET((Elm_Gen_Item *) relative));
2169 Eina_Inlist *tmp = eina_inlist_find(wd->items, EINA_INLIST_GET(it));
2170 _item_position_update(tmp, ((Elm_Gen_Item *)relative)->position+1);
2171
2172 if (it->group)
2173 wd->group_items = eina_list_prepend_relative(wd->group_items, it, ((Elm_Gen_Item *) relative)->parent);
2174
2175 if (wd->calc_job) ecore_job_del(wd->calc_job);
2176 wd->calc_job = ecore_job_add(_calc_job, wd);
2177
2178 return (Elm_Object_Item *)it;
2179}
2180
2181EAPI Elm_Object_Item *
2182elm_gengrid_item_sorted_insert(Evas_Object *obj,
2183 const Elm_Gengrid_Item_Class *itc,
2184 const void *data,
2185 Eina_Compare_Cb comp,
2186 Evas_Smart_Cb func,
2187 const void *func_data)
2188{
2189 Elm_Gen_Item *it;
2190 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2191 Widget_Data *wd = elm_widget_data_get(obj);
2192 if (!wd) return NULL;
2193
2194 it = _item_new(wd, itc, data, func, func_data);
2195 if (!it) return NULL;
2196
2197 if (!wd->state)
2198 wd->state = eina_inlist_sorted_state_new();
2199
2200 wd->item_compare_cb = comp;
2201 wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
2202 _elm_gengrid_item_compare, wd->state);
2203 _item_position_update(wd->items, 0);
2204
2205 if (wd->calc_job) ecore_job_del(wd->calc_job);
2206 wd->calc_job = ecore_job_add(_calc_job, wd);
2207
2208 return (Elm_Object_Item *)it;
2209}
2210
2211EAPI void
2212elm_gengrid_horizontal_set(Evas_Object *obj,
2213 Eina_Bool horizontal)
2214{
2215 ELM_CHECK_WIDTYPE(obj, widtype);
2216 Widget_Data *wd = elm_widget_data_get(obj);
2217 if (!wd) return;
2218 horizontal = !!horizontal;
2219 if (horizontal == wd->horizontal) return;
2220 wd->horizontal = horizontal;
2221
2222 /* Update the items to conform to the new layout */
2223 if (wd->calc_job) ecore_job_del(wd->calc_job);
2224 wd->calc_job = ecore_job_add(_calc_job, wd);
2225}
2226
2227EAPI Eina_Bool
2228elm_gengrid_horizontal_get(const Evas_Object *obj)
2229{
2230 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2231 Widget_Data *wd = elm_widget_data_get(obj);
2232 if (!wd) return EINA_FALSE;
2233 return wd->horizontal;
2234}
2235
2236EAPI void
2237elm_gengrid_clear(Evas_Object *obj)
2238{
2239 elm_genlist_clear(obj);
2240}
2241
2242EINA_DEPRECATED EAPI const Evas_Object *
2243elm_gengrid_item_object_get(const Elm_Object_Item *it)
2244{
2245 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
2246 return VIEW(it);
2247}
2248
2249EAPI void
2250elm_gengrid_item_update(Elm_Object_Item *it)
2251{
2252 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2253 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2254 if (!_it->realized) return;
2255 if (_it->want_unrealize) return;
2256 _elm_genlist_item_unrealize(_it, EINA_FALSE);
2257 _item_realize(_it);
2258 _item_place(_it, _it->x, _it->y);
2259}
2260
2261EAPI const Elm_Gengrid_Item_Class *
2262elm_gengrid_item_item_class_get(const Elm_Object_Item *it)
2263{
2264 return (Elm_Gengrid_Item_Class *)elm_genlist_item_item_class_get(it);
2265}
2266
2267EAPI void
2268elm_gengrid_item_item_class_update(Elm_Object_Item *it,
2269 const Elm_Gengrid_Item_Class *itc)
2270{
2271 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2272 EINA_SAFETY_ON_NULL_RETURN(itc);
2273 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2274 if (_it->generation < _it->wd->generation) return;
2275 _it->itc = itc;
2276 elm_gengrid_item_update(it);
2277}
2278
2279EAPI void
2280elm_gengrid_item_pos_get(const Elm_Object_Item *it,
2281 unsigned int *x,
2282 unsigned int *y)
2283{
2284 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2285 if (x) *x = ((Elm_Gen_Item *)it)->x;
2286 if (y) *y = ((Elm_Gen_Item *)it)->y;
2287}
2288
2289EAPI void
2290elm_gengrid_multi_select_set(Evas_Object *obj,
2291 Eina_Bool multi)
2292{
2293 ELM_CHECK_WIDTYPE(obj, widtype);
2294 Widget_Data *wd = elm_widget_data_get(obj);
2295 if (!wd) return;
2296 wd->multi = !!multi;
2297}
2298
2299EAPI Eina_Bool
2300elm_gengrid_multi_select_get(const Evas_Object *obj)
2301{
2302 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2303 Widget_Data *wd = elm_widget_data_get(obj);
2304 if (!wd) return EINA_FALSE;
2305 return wd->multi;
2306}
2307
2308EAPI Elm_Object_Item *
2309elm_gengrid_selected_item_get(const Evas_Object *obj)
2310{
2311 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2312 Widget_Data *wd = elm_widget_data_get(obj);
2313 if (!wd) return NULL;
2314 if (wd->selected) return wd->selected->data;
2315 return NULL;
2316}
2317
2318EAPI const Eina_List *
2319elm_gengrid_selected_items_get(const Evas_Object *obj)
2320{
2321 return elm_genlist_selected_items_get(obj);
2322}
2323
2324EAPI void
2325elm_gengrid_item_selected_set(Elm_Object_Item *it,
2326 Eina_Bool selected)
2327{
2328 elm_genlist_item_selected_set(it, selected);
2329}
2330
2331EAPI Eina_Bool
2332elm_gengrid_item_selected_get(const Elm_Object_Item *it)
2333{
2334 return elm_genlist_item_selected_get(it);
2335}
2336
2337EAPI Eina_List *
2338elm_gengrid_realized_items_get(const Evas_Object *obj)
2339{
2340 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2341 Widget_Data *wd = elm_widget_data_get(obj);
2342 Eina_List *list = NULL;
2343 Elm_Gen_Item *it;
2344
2345 EINA_INLIST_FOREACH(wd->items, it)
2346 {
2347 if (it->realized) list = eina_list_append(list, (Elm_Object_Item *)it);
2348 }
2349 return list;
2350}
2351
2352EAPI void
2353elm_gengrid_realized_items_update(Evas_Object *obj)
2354{
2355 ELM_CHECK_WIDTYPE(obj, widtype);
2356
2357 Eina_List *list, *l;
2358 Elm_Object_Item *it;
2359
2360 list = elm_gengrid_realized_items_get(obj);
2361 EINA_LIST_FOREACH(list, l, it)
2362 elm_gengrid_item_update(it);
2363}
2364
2365static Evas_Object *
2366_elm_gengrid_item_label_create(void *data,
2367 Evas_Object *obj __UNUSED__,
2368 Evas_Object *tooltip,
2369 void *it __UNUSED__)
2370{
2371 Evas_Object *label = elm_label_add(tooltip);
2372 if (!label)
2373 return NULL;
2374 elm_object_style_set(label, "tooltip");
2375 elm_object_text_set(label, data);
2376 return label;
2377}
2378
2379static void
2380_elm_gengrid_item_label_del_cb(void *data,
2381 Evas_Object *obj __UNUSED__,
2382 void *event_info __UNUSED__)
2383{
2384 eina_stringshare_del(data);
2385}
2386
2387EAPI void
2388elm_gengrid_item_tooltip_text_set(Elm_Object_Item *it,
2389 const char *text)
2390{
2391 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2392 text = eina_stringshare_add(text);
2393 elm_gengrid_item_tooltip_content_cb_set(it, _elm_gengrid_item_label_create,
2394 text,
2395 _elm_gengrid_item_label_del_cb);
2396}
2397
2398EAPI void
2399elm_gengrid_item_tooltip_content_cb_set(Elm_Object_Item *it,
2400 Elm_Tooltip_Item_Content_Cb func,
2401 const void *data,
2402 Evas_Smart_Cb del_cb)
2403{
2404 ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
2405 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2406
2407 if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
2408 return;
2409
2410 if (_it->tooltip.del_cb)
2411 _it->tooltip.del_cb((void *)_it->tooltip.data, WIDGET(_it), _it);
2412 _it->tooltip.content_cb = func;
2413 _it->tooltip.data = data;
2414 _it->tooltip.del_cb = del_cb;
2415 if (VIEW(_it))
2416 {
2417 elm_widget_item_tooltip_content_cb_set(_it,
2418 _it->tooltip.content_cb,
2419 _it->tooltip.data, NULL);
2420 elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
2421 elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
2422 }
2423
2424 return;
2425
2426error:
2427 if (del_cb) del_cb((void *)data, NULL, NULL);
2428}
2429
2430EAPI void
2431elm_gengrid_item_tooltip_unset(Elm_Object_Item *it)
2432{
2433 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2434 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2435
2436 if ((VIEW(_it)) && (_it->tooltip.content_cb))
2437 elm_widget_item_tooltip_unset(_it);
2438
2439 if (_it->tooltip.del_cb)
2440 _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
2441 _it->tooltip.del_cb = NULL;
2442 _it->tooltip.content_cb = NULL;
2443 _it->tooltip.data = NULL;
2444 _it->tooltip.free_size = EINA_FALSE;
2445 if (_it->tooltip.style)
2446 elm_gengrid_item_tooltip_style_set(it, NULL);
2447}
2448
2449EAPI void
2450elm_gengrid_item_tooltip_style_set(Elm_Object_Item *it,
2451 const char *style)
2452{
2453 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2454 eina_stringshare_replace(&((Elm_Gen_Item *)it)->tooltip.style, style);
2455 if (VIEW(it)) elm_widget_item_tooltip_style_set(it, style);
2456}
2457
2458EAPI const char *
2459elm_gengrid_item_tooltip_style_get(const Elm_Object_Item *it)
2460{
2461 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
2462 return ((Elm_Gen_Item *)it)->tooltip.style;
2463}
2464
2465EAPI Eina_Bool
2466elm_gengrid_item_tooltip_window_mode_set(Elm_Object_Item *it, Eina_Bool disable)
2467{
2468 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2469 ((Elm_Gen_Item *)it)->tooltip.free_size = disable;
2470 if (VIEW(it)) return elm_widget_item_tooltip_window_mode_set(it, disable);
2471 return EINA_TRUE;
2472}
2473
2474EAPI Eina_Bool
2475elm_gengrid_item_tooltip_window_mode_get(const Elm_Object_Item *it)
2476{
2477 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
2478 return ((Elm_Gen_Item *)it)->tooltip.free_size;
2479}
2480
2481EAPI void
2482elm_gengrid_item_cursor_set(Elm_Object_Item *it,
2483 const char *cursor)
2484{
2485 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2486 eina_stringshare_replace(&((Elm_Gen_Item *)it)->mouse_cursor, cursor);
2487 if (VIEW(it)) elm_widget_item_cursor_set(it, cursor);
2488}
2489
2490EAPI const char *
2491elm_gengrid_item_cursor_get(const Elm_Object_Item *it)
2492{
2493 return elm_widget_item_cursor_get(it);
2494}
2495
2496EAPI void
2497elm_gengrid_item_cursor_unset(Elm_Object_Item *it)
2498{
2499 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2500 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2501 if (!_it->mouse_cursor)
2502 return;
2503
2504 if (VIEW(_it))
2505 elm_widget_item_cursor_unset(_it);
2506
2507 eina_stringshare_del(_it->mouse_cursor);
2508 _it->mouse_cursor = NULL;
2509}
2510
2511EAPI void
2512elm_gengrid_item_cursor_style_set(Elm_Object_Item *it,
2513 const char *style)
2514{
2515 elm_widget_item_cursor_style_set(it, style);
2516}
2517
2518EAPI const char *
2519elm_gengrid_item_cursor_style_get(const Elm_Object_Item *it)
2520{
2521 return elm_widget_item_cursor_style_get(it);
2522}
2523
2524EAPI void
2525elm_gengrid_item_cursor_engine_only_set(Elm_Object_Item *it,
2526 Eina_Bool engine_only)
2527{
2528 elm_widget_item_cursor_engine_only_set(it, engine_only);
2529}
2530
2531EAPI Eina_Bool
2532elm_gengrid_item_cursor_engine_only_get(const Elm_Object_Item *it)
2533{
2534 return elm_widget_item_cursor_engine_only_get(it);
2535}
2536
2537EAPI void
2538elm_gengrid_reorder_mode_set(Evas_Object *obj,
2539 Eina_Bool reorder_mode)
2540{
2541 ELM_CHECK_WIDTYPE(obj, widtype);
2542 Widget_Data *wd = elm_widget_data_get(obj);
2543 if (!wd) return;
2544 wd->reorder_mode = !!reorder_mode;
2545}
2546
2547EAPI Eina_Bool
2548elm_gengrid_reorder_mode_get(const Evas_Object *obj)
2549{
2550 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2551 Widget_Data *wd = elm_widget_data_get(obj);
2552 if (!wd) return EINA_FALSE;
2553 return wd->reorder_mode;
2554}
2555
2556EAPI void
2557elm_gengrid_bounce_set(Evas_Object *obj,
2558 Eina_Bool h_bounce,
2559 Eina_Bool v_bounce)
2560{
2561 elm_genlist_bounce_set(obj, h_bounce, v_bounce);
2562}
2563
2564EAPI void
2565elm_gengrid_bounce_get(const Evas_Object *obj,
2566 Eina_Bool *h_bounce,
2567 Eina_Bool *v_bounce)
2568{
2569 elm_genlist_bounce_get(obj, h_bounce, v_bounce);
2570}
2571
2572EAPI void
2573elm_gengrid_page_relative_set(Evas_Object *obj,
2574 double h_pagerel,
2575 double v_pagerel)
2576{
2577 _elm_genlist_page_relative_set(obj, h_pagerel, v_pagerel);
2578}
2579
2580EAPI void
2581elm_gengrid_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel)
2582{
2583 _elm_genlist_page_relative_get(obj, h_pagerel, v_pagerel);
2584}
2585
2586EAPI void
2587elm_gengrid_page_size_set(Evas_Object *obj,
2588 Evas_Coord h_pagesize,
2589 Evas_Coord v_pagesize)
2590{
2591 _elm_genlist_page_size_set(obj, h_pagesize, v_pagesize);
2592}
2593
2594EAPI void
2595elm_gengrid_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
2596{
2597 _elm_genlist_current_page_get(obj, h_pagenumber, v_pagenumber);
2598}
2599
2600EAPI void
2601elm_gengrid_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
2602{
2603 _elm_genlist_last_page_get(obj, h_pagenumber, v_pagenumber);
2604}
2605
2606EAPI void
2607elm_gengrid_page_show(const Evas_Object *obj, int h_pagenumber, int v_pagenumber)
2608{
2609 _elm_genlist_page_show(obj, h_pagenumber, v_pagenumber);
2610}
2611
2612EAPI void
2613elm_gengrid_page_bring_in(const Evas_Object *obj, int h_pagenumber, int v_pagenumber)
2614{
2615 _elm_genlist_page_bring_in(obj, h_pagenumber, v_pagenumber);
2616}
2617
2618EAPI void
2619elm_gengrid_scroller_policy_set(Evas_Object *obj,
2620 Elm_Scroller_Policy policy_h,
2621 Elm_Scroller_Policy policy_v)
2622{
2623 ELM_CHECK_WIDTYPE(obj, widtype);
2624 Widget_Data *wd = elm_widget_data_get(obj);
2625 if ((!wd) || (!wd->scr)) return;
2626 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
2627 (policy_v >= ELM_SCROLLER_POLICY_LAST))
2628 return;
2629 elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
2630}
2631
2632EAPI void
2633elm_gengrid_scroller_policy_get(const Evas_Object *obj,
2634 Elm_Scroller_Policy *policy_h,
2635 Elm_Scroller_Policy *policy_v)
2636{
2637 ELM_CHECK_WIDTYPE(obj, widtype);
2638 Widget_Data *wd = elm_widget_data_get(obj);
2639 Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
2640 if ((!wd) || (!wd->scr)) return;
2641 elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
2642 if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
2643 if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
2644}
2645
2646EAPI Elm_Object_Item *
2647elm_gengrid_first_item_get(const Evas_Object *obj)
2648{
2649 return elm_genlist_first_item_get(obj);
2650}
2651
2652EAPI Elm_Object_Item *
2653elm_gengrid_last_item_get(const Evas_Object *obj)
2654{
2655 return elm_genlist_last_item_get(obj);
2656}
2657
2658EAPI Elm_Object_Item *
2659elm_gengrid_item_next_get(const Elm_Object_Item *it)
2660{
2661 return elm_genlist_item_next_get(it);
2662}
2663
2664EAPI Elm_Object_Item *
2665elm_gengrid_item_prev_get(const Elm_Object_Item *it)
2666{
2667 return elm_genlist_item_prev_get(it);
2668}
2669
2670EAPI void
2671elm_gengrid_item_show(Elm_Object_Item *it, Elm_Gengrid_Item_Scrollto_Type type)
2672{
2673 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2674 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2675 Widget_Data *wd = _it->wd;
2676 Evas_Coord minx = 0, miny = 0;
2677
2678 if ((_it->generation < _it->wd->generation)) return;
2679 _pan_min_get(wd->pan_smart, &minx, &miny);
2680
2681 if (type==ELM_GENGRID_ITEM_SCROLLTO_IN)
2682 {
2683 //TODO : type based handling like genlist
2684 }
2685
2686 if (wd->horizontal)
2687 elm_smart_scroller_region_bring_in(_it->wd->scr,
2688 ((_it->x - _it->item->prev_group) * wd->item_width) + (_it->item->prev_group * _it->wd->group_item_width) + minx,
2689 _it->y * wd->item_height + miny,
2690 _it->wd->item_width,
2691 _it->wd->item_height);
2692 else
2693 elm_smart_scroller_region_bring_in(_it->wd->scr,
2694 _it->x * wd->item_width + minx,
2695 ((_it->y - _it->item->prev_group) * wd->item_height) + (_it->item->prev_group * _it->wd->group_item_height) + miny,
2696 _it->wd->item_width,
2697 _it->wd->item_height);
2698}
2699
2700EAPI void
2701elm_gengrid_item_bring_in(Elm_Object_Item *it, Elm_Gengrid_Item_Scrollto_Type type)
2702{
2703 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2704 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2705
2706 if (_it->generation < _it->wd->generation) return;
2707
2708 Evas_Coord minx = 0, miny = 0;
2709 Widget_Data *wd = _it->wd;
2710 _pan_min_get(wd->pan_smart, &minx, &miny);
2711
2712 if (type==ELM_GENGRID_ITEM_SCROLLTO_IN)
2713 {
2714 //TODO : type based handling like genlist
2715 }
2716
2717 if (wd->horizontal)
2718 elm_smart_scroller_region_bring_in(_it->wd->scr,
2719 ((_it->x - _it->item->prev_group) * wd->item_width) + (_it->item->prev_group * _it->wd->group_item_width) + minx,
2720 _it->y * wd->item_height + miny,
2721 _it->wd->item_width,
2722 _it->wd->item_height);
2723 else
2724 elm_smart_scroller_region_bring_in(_it->wd->scr,
2725 _it->x * wd->item_width + minx,
2726 ((_it->y - _it->item->prev_group)* wd->item_height) + (_it->item->prev_group * _it->wd->group_item_height) + miny,
2727 _it->wd->item_width,
2728 _it->wd->item_height);
2729}
2730
2731EAPI void
2732elm_gengrid_filled_set(Evas_Object *obj, Eina_Bool fill)
2733{
2734 ELM_CHECK_WIDTYPE(obj, widtype);
2735 Widget_Data *wd = elm_widget_data_get(obj);
2736 if (!wd) return;
2737 fill = !!fill;
2738 if (wd->filled != fill)
2739 wd->filled = fill;
2740}
2741
2742EAPI Eina_Bool
2743elm_gengrid_filled_get(const Evas_Object *obj)
2744{
2745 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2746 Widget_Data *wd = elm_widget_data_get(obj);
2747 if (!wd) return EINA_FALSE;
2748 return wd->filled;
2749}
2750
2751EAPI unsigned int
2752elm_gengrid_items_count(const Evas_Object *obj)
2753{
2754 ELM_CHECK_WIDTYPE(obj, widtype) 0;
2755 Widget_Data *wd = elm_widget_data_get(obj);
2756 if (!wd) return 0;
2757 return wd->item_count;
2758}
2759
2760EAPI Elm_Gengrid_Item_Class *
2761elm_gengrid_item_class_new(void)
2762{
2763 Elm_Gengrid_Item_Class *itc;
2764
2765 itc = calloc(1, sizeof(Elm_Gengrid_Item_Class));
2766 if (!itc)
2767 return NULL;
2768 itc->version = CLASS_ALLOCATED;
2769 itc->refcount = 1;
2770 itc->delete_me = EINA_FALSE;
2771
2772 return itc;
2773}
2774
2775EAPI void
2776elm_gengrid_item_class_free(Elm_Gengrid_Item_Class *itc)
2777{
2778 if (itc && (itc->version == CLASS_ALLOCATED))
2779 {
2780 if (!itc->delete_me) itc->delete_me = EINA_TRUE;
2781 if (itc->refcount > 0) elm_gengrid_item_class_unref(itc);
2782 else
2783 {
2784 itc->version = 0;
2785 free(itc);
2786 }
2787 }
2788}
2789
2790EAPI void
2791elm_gengrid_item_class_ref(Elm_Gengrid_Item_Class *itc)
2792{
2793 if (itc && (itc->version == CLASS_ALLOCATED))
2794 {
2795 itc->refcount++;
2796 if (itc->refcount == 0) itc->refcount--;
2797 }
2798}
2799
2800EAPI void
2801elm_gengrid_item_class_unref(Elm_Gengrid_Item_Class *itc)
2802{
2803 if (itc && (itc->version == CLASS_ALLOCATED))
2804 {
2805 if (itc->refcount > 0) itc->refcount--;
2806 if (itc->delete_me && (!itc->refcount))
2807 elm_gengrid_item_class_free(itc);
2808 }
2809}
2810
2811EAPI void
2812elm_gengrid_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
2813{
2814 elm_genlist_select_mode_set(obj, mode);
2815}
2816
2817EAPI Elm_Object_Select_Mode
2818elm_gengrid_select_mode_get(const Evas_Object *obj)
2819{
2820 return elm_genlist_select_mode_get(obj);
2821}
2822
2823EAPI void
2824elm_gengrid_highlight_mode_set(Evas_Object *obj,
2825 Eina_Bool highlight)
2826{
2827 elm_genlist_highlight_mode_set(obj, highlight);
2828}
2829
2830EAPI Eina_Bool
2831elm_gengrid_highlight_mode_get(const Evas_Object *obj)
2832{
2833 return elm_genlist_highlight_mode_get(obj);
2834}
2835
2836EAPI int
2837elm_gengrid_item_index_get(const Elm_Object_Item *it)
2838{
2839 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
2840 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2841
2842 return _it->position;
2843}
2844
2845EAPI void
2846elm_gengrid_item_select_mode_set(Elm_Object_Item *it,
2847 Elm_Object_Select_Mode mode)
2848{
2849 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
2850 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2851 if (!_it) return;
2852 if (_it->generation < _it->wd->generation) return;
2853 if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
2854 return;
2855 if (_it->select_mode != mode)
2856 _it->select_mode = mode;
2857
2858 if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2859 elm_gengrid_item_update(it);
2860}
2861
2862EAPI Elm_Object_Select_Mode
2863elm_gengrid_item_select_mode_get(const Elm_Object_Item *it)
2864{
2865 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
2866 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
2867 if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
2868 return _it->select_mode;
2869}
diff --git a/libraries/elementary/src/lib/elm_gengrid.h b/libraries/elementary/src/lib/elm_gengrid.h
new file mode 100644
index 0000000..c88232a
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_gengrid.h
@@ -0,0 +1,1615 @@
1/**
2 * @defgroup Gengrid Gengrid (Generic grid)
3 * @ingroup Elementary
4 *
5 * This widget aims to position objects in a grid layout while
6 * actually creating and rendering only the visible ones, using the
7 * same idea as the @ref Genlist "genlist": the user defines a @b
8 * class for each item, specifying functions that will be called at
9 * object creation, deletion, etc. When those items are selected by
10 * the user, a callback function is issued. Users may interact with
11 * a gengrid via the mouse (by clicking on items to select them and
12 * clicking on the grid's viewport and swiping to pan the whole
13 * view) or via the keyboard, navigating through item with the
14 * arrow keys.
15 *
16 * @section Gengrid_Layouts Gengrid layouts
17 *
18 * Gengrid may layout its items in one of two possible layouts:
19 * - horizontal or
20 * - vertical.
21 *
22 * When in "horizontal mode", items will be placed in @b columns,
23 * from top to bottom and, when the space for a column is filled,
24 * another one is started on the right, thus expanding the grid
25 * horizontally, making for horizontal scrolling. When in "vertical
26 * mode" , though, items will be placed in @b rows, from left to
27 * right and, when the space for a row is filled, another one is
28 * started below, thus expanding the grid vertically (and making
29 * for vertical scrolling).
30 *
31 * @section Gengrid_Items Gengrid items
32 *
33 * An item in a gengrid can have 0 or more texts (they can be
34 * regular text or textblock Evas objects - that's up to the style
35 * to determine), 0 or more contents (which are simply objects
36 * swallowed into the gengrid item's theming Edje object) and 0 or
37 * more <b>boolean states</b>, which have the behavior left to the
38 * user to define. The Edje part names for each of these properties
39 * will be looked up, in the theme file for the gengrid, under the
40 * Edje (string) data items named @c "texts", @c "contents" and @c
41 * "states", respectively. For each of those properties, if more
42 * than one part is provided, they must have names listed separated
43 * by spaces in the data fields. For the default gengrid item
44 * theme, we have @b one text part (@c "elm.text"), @b two content
45 * parts (@c "elm.swalllow.icon" and @c "elm.swallow.end") and @b
46 * no state parts.
47 *
48 * A gengrid item may be at one of several styles. Elementary
49 * provides one by default - "default", but this can be extended by
50 * system or application custom themes/overlays/extensions (see
51 * @ref Theme "themes" for more details).
52 *
53 * @section Gengrid_Item_Class Gengrid item classes
54 *
55 * In order to have the ability to add and delete items on the fly,
56 * gengrid implements a class (callback) system where the
57 * application provides a structure with information about that
58 * type of item (gengrid may contain multiple different items with
59 * different classes, states and styles). Gengrid will call the
60 * functions in this struct (methods) when an item is "realized"
61 * (i.e., created dynamically, while the user is scrolling the
62 * grid). All objects will simply be deleted when no longer needed
63 * with evas_object_del(). The #Elm_GenGrid_Item_Class structure
64 * contains the following members:
65 * - @c item_style - This is a constant string and simply defines
66 * the name of the item style. It @b must be specified and the
67 * default should be @c "default".
68 * - @c func.text_get - This function is called when an item
69 * object is actually created. The @c data parameter will point to
70 * the same data passed to elm_gengrid_item_append() and related
71 * item creation functions. The @c obj parameter is the gengrid
72 * object itself, while the @c part one is the name string of one
73 * of the existing text parts in the Edje group implementing the
74 * item's theme. This function @b must return a strdup'()ed string,
75 * as the caller will free() it when done. See
76 * #Elm_Gengrid_Item_Text_Get_Cb.
77 * - @c func.content_get - This function is called when an item object
78 * is actually created. The @c data parameter will point to the
79 * same data passed to elm_gengrid_item_append() and related item
80 * creation functions. The @c obj parameter is the gengrid object
81 * itself, while the @c part one is the name string of one of the
82 * existing (content) swallow parts in the Edje group implementing the
83 * item's theme. It must return @c NULL, when no content is desired,
84 * or a valid object handle, otherwise. The object will be deleted
85 * by the gengrid on its deletion or when the item is "unrealized".
86 * See #Elm_Gengrid_Item_Content_Get_Cb.
87 * - @c func.state_get - This function is called when an item
88 * object is actually created. The @c data parameter will point to
89 * the same data passed to elm_gengrid_item_append() and related
90 * item creation functions. The @c obj parameter is the gengrid
91 * object itself, while the @c part one is the name string of one
92 * of the state parts in the Edje group implementing the item's
93 * theme. Return @c EINA_FALSE for false/off or @c EINA_TRUE for
94 * true/on. Gengrids will emit a signal to its theming Edje object
95 * with @c "elm,state,xxx,active" and @c "elm" as "emission" and
96 * "source" arguments, respectively, when the state is true (the
97 * default is false), where @c xxx is the name of the (state) part.
98 * See #Elm_Gengrid_Item_State_Get_Cb.
99 * - @c func.del - This is called when elm_object_item_del() is
100 * called on an item or elm_gengrid_clear() is called on the
101 * gengrid. This is intended for use when gengrid items are
102 * deleted, so any data attached to the item (e.g. its data
103 * parameter on creation) can be deleted. See #Elm_Gengrid_Item_Del_Cb.
104 *
105 * @section Gengrid_Usage_Hints Usage hints
106 *
107 * If the user wants to have multiple items selected at the same
108 * time, elm_gengrid_multi_select_set() will permit it. If the
109 * gengrid is single-selection only (the default), then
110 * elm_gengrid_select_item_get() will return the selected item or
111 * @c NULL, if none is selected. If the gengrid is under
112 * multi-selection, then elm_gengrid_selected_items_get() will
113 * return a list (that is only valid as long as no items are
114 * modified (added, deleted, selected or unselected) of child items
115 * on a gengrid.
116 *
117 * If an item changes (internal (boolean) state, text or content
118 * changes), then use elm_gengrid_item_update() to have gengrid
119 * update the item with the new state. A gengrid will re-"realize"
120 * the item, thus calling the functions in the
121 * #Elm_Gengrid_Item_Class set for that item.
122 *
123 * To programmatically (un)select an item, use
124 * elm_gengrid_item_selected_set(). To get its selected state use
125 * elm_gengrid_item_selected_get(). To make an item disabled
126 * (unable to be selected and appear differently) use
127 * elm_object_item_disabled_set() to set this and
128 * elm_object_item_disabled_get() to get the disabled state.
129 *
130 * Grid cells will only have their selection smart callbacks called
131 * when firstly getting selected. Any further clicks will do
132 * nothing, unless you enable the "always select mode", with
133 * elm_gengrid_select_mode_set() as ELM_OBJECT_SELECT_MODE_ALWAYS,
134 * thus making every click to issue selection callbacks.
135 * elm_gengrid_select_mode_set() as ELM_OBJECT_SELECT_MODE_NONE will
136 * turn off the ability to select items entirely in the widget and
137 * they will neither appear selected nor call the selection smart
138 * callbacks.
139 *
140 * Remember that you can create new styles and add your own theme
141 * augmentation per application with elm_theme_extension_add(). If
142 * you absolutely must have a specific style that overrides any
143 * theme the user or system sets up you can use
144 * elm_theme_overlay_add() to add such a file.
145 *
146 * @section Gengrid_Smart_Events Gengrid smart events
147 *
148 * Smart events that you can add callbacks for are:
149 * - @c "activated" - The user has double-clicked or pressed
150 * (enter|return|spacebar) on an item. The @c event_info parameter
151 * is the gengrid item that was activated.
152 * - @c "clicked,double" - The user has double-clicked an item.
153 * The @c event_info parameter is the gengrid item that was double-clicked.
154 * - @c "longpressed" - This is called when the item is pressed for a certain
155 * amount of time. By default it's 1 second.
156 * - @c "selected" - The user has made an item selected. The
157 * @c event_info parameter is the gengrid item that was selected.
158 * - @c "unselected" - The user has made an item unselected. The
159 * @c event_info parameter is the gengrid item that was unselected.
160 * - @c "realized" - This is called when the item in the gengrid
161 * has its implementing Evas object instantiated, de facto. @c
162 * event_info is the gengrid item that was created. The object
163 * may be deleted at any time, so it is highly advised to the
164 * caller @b not to use the object pointer returned from
165 * elm_gengrid_item_object_get(), because it may point to freed
166 * objects.
167 * - @c "unrealized" - This is called when the implementing Evas
168 * object for this item is deleted. @c event_info is the gengrid
169 * item that was deleted.
170 * - @c "changed" - Called when an item is added, removed, resized
171 * or moved and when the gengrid is resized or gets "horizontal"
172 * property changes.
173 * - @c "scroll,anim,start" - This is called when scrolling animation has
174 * started.
175 * - @c "scroll,anim,stop" - This is called when scrolling animation has
176 * stopped.
177 * - @c "drag,start,up" - Called when the item in the gengrid has
178 * been dragged (not scrolled) up.
179 * - @c "drag,start,down" - Called when the item in the gengrid has
180 * been dragged (not scrolled) down.
181 * - @c "drag,start,left" - Called when the item in the gengrid has
182 * been dragged (not scrolled) left.
183 * - @c "drag,start,right" - Called when the item in the gengrid has
184 * been dragged (not scrolled) right.
185 * - @c "drag,stop" - Called when the item in the gengrid has
186 * stopped being dragged.
187 * - @c "drag" - Called when the item in the gengrid is being
188 * dragged.
189 * - @c "scroll" - called when the content has been scrolled
190 * (moved).
191 * - @c "scroll,drag,start" - called when dragging the content has
192 * started.
193 * - @c "scroll,drag,stop" - called when dragging the content has
194 * stopped.
195 * - @c "edge,top" - This is called when the gengrid is scrolled until
196 * the top edge.
197 * - @c "edge,bottom" - This is called when the gengrid is scrolled
198 * until the bottom edge.
199 * - @c "edge,left" - This is called when the gengrid is scrolled
200 * until the left edge.
201 * - @c "edge,right" - This is called when the gengrid is scrolled
202 * until the right edge.
203 *
204 * Supported elm_object common APIs
205 * @li elm_object_signal_emit()
206 *
207 * Supported elm_object_item common APIs
208 * @li elm_object_item_part_content_get()
209 * @li elm_object_item_part_content_set()
210 * @li elm_object_item_part_content_unset()
211 * @li elm_object_item_part_text_set()
212 * @li elm_object_item_part_text_get()
213 * @li elm_object_item_disabled_set()
214 * @li elm_object_item_disabled_get()
215 *
216 * List of gengrid examples:
217 * @li @ref gengrid_example
218 */
219
220/**
221 * @addtogroup Gengrid
222 * @{
223 */
224
225#define ELM_GENGRID_ITEM_CLASS_VERSION ELM_GEN_ITEM_CLASS_VERSION
226#define ELM_GENGRID_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_HEADER
227
228/**
229 * Defines where to position the item in the genlist.
230 *
231 * @ingroup Genlist
232 */
233typedef enum
234{
235 ELM_GENGRID_ITEM_SCROLLTO_NONE = 0, /**< no scrollto */
236 ELM_GENGRID_ITEM_SCROLLTO_IN = (1 << 0), /**< to the nearest viewport */
237 ELM_GENGRID_ITEM_SCROLLTO_TOP = (1 << 1), /**< to the top of viewport */
238 ELM_GENGRID_ITEM_SCROLLTO_MIDDLE = (1 << 2) /**< to the middle of viewport */
239} Elm_Gengrid_Item_Scrollto_Type;
240
241
242/**
243 * @see Elm_Gen_Item_Class
244 */
245typedef Elm_Gen_Item_Class Elm_Gengrid_Item_Class;
246
247/**
248 * @see Elm_Gen_Item_Text_Get_Cb
249 */
250typedef Elm_Gen_Item_Text_Get_Cb Elm_Gengrid_Item_Text_Get_Cb;
251
252/**
253 * @see Elm_Gen_Item_Content_Get_Cb
254 */
255typedef Elm_Gen_Item_Content_Get_Cb Elm_Gengrid_Item_Content_Get_Cb;
256
257/**
258 * @see Elm_Gen_Item_State_Get_Cb
259 */
260typedef Elm_Gen_Item_State_Get_Cb Elm_Gengrid_Item_State_Get_Cb;
261
262/**
263 * @see Elm_Gen_Item_Del_Cb
264 */
265typedef Elm_Gen_Item_Del_Cb Elm_Gengrid_Item_Del_Cb;
266
267/**
268 * Add a new gengrid widget to the given parent Elementary
269 * (container) object
270 *
271 * @param parent The parent object
272 * @return a new gengrid widget handle or @c NULL, on errors
273 *
274 * This function inserts a new gengrid widget on the canvas.
275 *
276 * @see elm_gengrid_item_size_set()
277 * @see elm_gengrid_group_item_size_set()
278 * @see elm_gengrid_horizontal_set()
279 * @see elm_gengrid_item_append()
280 * @see elm_object_item_del()
281 * @see elm_gengrid_clear()
282 *
283 * @ingroup Gengrid
284 */
285EAPI Evas_Object *elm_gengrid_add(Evas_Object *parent);
286
287/**
288 * Remove all items from a given gengrid widget
289 *
290 * @param obj The gengrid object.
291 *
292 * This removes (and deletes) all items in @p obj, leaving it
293 * empty.
294 *
295 * @see elm_object_item_del(), to remove just one item.
296 *
297 * @ingroup Gengrid
298 */
299EAPI void elm_gengrid_clear(Evas_Object *obj);
300
301/**
302 * Enable or disable multi-selection in a given gengrid widget
303 *
304 * @param obj The gengrid object.
305 * @param multi @c EINA_TRUE, to enable multi-selection,
306 * @c EINA_FALSE to disable it.
307 *
308 * Multi-selection is the ability to have @b more than one
309 * item selected, on a given gengrid, simultaneously. When it is
310 * enabled, a sequence of clicks on different items will make them
311 * all selected, progressively. A click on an already selected item
312 * will unselect it. If interacting via the keyboard,
313 * multi-selection is enabled while holding the "Shift" key.
314 *
315 * @note By default, multi-selection is @b disabled on gengrids
316 *
317 * @see elm_gengrid_multi_select_get()
318 *
319 * @ingroup Gengrid
320 */
321EAPI void elm_gengrid_multi_select_set(Evas_Object *obj, Eina_Bool multi);
322
323/**
324 * Get whether multi-selection is enabled or disabled for a given
325 * gengrid widget
326 *
327 * @param obj The gengrid object.
328 * @return @c EINA_TRUE, if multi-selection is enabled, @c
329 * EINA_FALSE otherwise
330 *
331 * @see elm_gengrid_multi_select_set() for more details
332 *
333 * @ingroup Gengrid
334 */
335EAPI Eina_Bool elm_gengrid_multi_select_get(const Evas_Object *obj);
336
337/**
338 * Set the direction in which a given gengrid widget will expand while
339 * placing its items.
340 *
341 * @param obj The gengrid object.
342 * @param horizontal @c EINA_TRUE to make the gengrid expand
343 * horizontally, @c EINA_FALSE to expand vertically.
344 *
345 * When in "horizontal mode" (@c EINA_TRUE), items will be placed
346 * in @b columns, from top to bottom and, when the space for a
347 * column is filled, another one is started on the right, thus
348 * expanding the grid horizontally. When in "vertical mode"
349 * (@c EINA_FALSE), though, items will be placed in @b rows, from left
350 * to right and, when the space for a row is filled, another one is
351 * started below, thus expanding the grid vertically.
352 *
353 * @see elm_gengrid_horizontal_get()
354 *
355 * @ingroup Gengrid
356 */
357EAPI void elm_gengrid_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
358
359/**
360 * Get for what direction a given gengrid widget will expand while
361 * placing its items.
362 *
363 * @param obj The gengrid object.
364 * @return @c EINA_TRUE, if @p obj is set to expand horizontally,
365 * @c EINA_FALSE if it's set to expand vertically.
366 *
367 * @see elm_gengrid_horizontal_set() for more details
368 *
369 * @ingroup Gengrid
370 */
371EAPI Eina_Bool elm_gengrid_horizontal_get(const Evas_Object *obj);
372
373/**
374 * Enable or disable bouncing effect for a given gengrid widget
375 *
376 * @param obj The gengrid object
377 * @param h_bounce @c EINA_TRUE, to enable @b horizontal bouncing,
378 * @c EINA_FALSE to disable it
379 * @param v_bounce @c EINA_TRUE, to enable @b vertical bouncing,
380 * @c EINA_FALSE to disable it
381 *
382 * The bouncing effect occurs whenever one reaches the gengrid's
383 * edge's while panning it -- it will scroll past its limits a
384 * little bit and return to the edge again, in a animated for,
385 * automatically.
386 *
387 * @note By default, gengrids have bouncing enabled on both axis
388 *
389 * @see elm_gengrid_bounce_get()
390 *
391 * @ingroup Gengrid
392 */
393EAPI void elm_gengrid_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
394
395/**
396 * Get whether bouncing effects are enabled or disabled, for a
397 * given gengrid widget, on each axis
398 *
399 * @param obj The gengrid object
400 * @param h_bounce Pointer to a variable where to store the
401 * horizontal bouncing flag.
402 * @param v_bounce Pointer to a variable where to store the
403 * vertical bouncing flag.
404 *
405 * @see elm_gengrid_bounce_set() for more details
406 *
407 * @ingroup Gengrid
408 */
409EAPI void elm_gengrid_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
410
411/**
412 * Append a new item in a given gengrid widget.
413 *
414 * @param obj The gengrid object.
415 * @param gic The item class for the item.
416 * @param data The item data.
417 * @param func Convenience function called when the item is
418 * selected.
419 * @param func_data Data to be passed to @p func.
420 * @return A handle to the item added or @c NULL, on errors.
421 *
422 * This adds an item to the beginning of the gengrid.
423 *
424 * @see elm_gengrid_item_prepend()
425 * @see elm_gengrid_item_insert_before()
426 * @see elm_gengrid_item_insert_after()
427 * @see elm_object_item_del()
428 *
429 * @ingroup Gengrid
430 */
431EAPI Elm_Object_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);
432
433/**
434 * Prepend a new item in a given gengrid widget.
435 *
436 * @param obj The gengrid object.
437 * @param gic The item class for the item.
438 * @param data The item data.
439 * @param func Convenience function called when the item is
440 * selected.
441 * @param func_data Data to be passed to @p func.
442 * @return A handle to the item added or @c NULL, on errors.
443 *
444 * This adds an item to the end of the gengrid.
445 *
446 * @see elm_gengrid_item_append()
447 * @see elm_gengrid_item_insert_before()
448 * @see elm_gengrid_item_insert_after()
449 * @see elm_object_item_del()
450 *
451 * @ingroup Gengrid
452 */
453EAPI Elm_Object_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);
454
455/**
456 * Insert an item before another in a gengrid widget
457 *
458 * @param obj The gengrid object.
459 * @param gic The item class for the item.
460 * @param data The item data.
461 * @param relative The item to place this new one before.
462 * @param func Convenience function called when the item is
463 * selected.
464 * @param func_data Data to be passed to @p func.
465 * @return A handle to the item added or @c NULL, on errors.
466 *
467 * This inserts an item before another in the gengrid.
468 *
469 * @see elm_gengrid_item_append()
470 * @see elm_gengrid_item_prepend()
471 * @see elm_gengrid_item_insert_after()
472 * @see elm_object_item_del()
473 *
474 * @ingroup Gengrid
475 */
476EAPI Elm_Object_Item *elm_gengrid_item_insert_before(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Elm_Object_Item *relative, Evas_Smart_Cb func, const void *func_data);
477
478/**
479 * Insert an item after another in a gengrid widget
480 *
481 * @param obj The gengrid object.
482 * @param gic The item class for the item.
483 * @param data The item data.
484 * @param relative The item to place this new one after.
485 * @param func Convenience function called when the item is
486 * selected.
487 * @param func_data Data to be passed to @p func.
488 * @return A handle to the item added or @c NULL, on errors.
489 *
490 * This inserts an item after another in the gengrid.
491 *
492 * @see elm_gengrid_item_append()
493 * @see elm_gengrid_item_prepend()
494 * @see elm_gengrid_item_insert_after()
495 * @see elm_object_item_del()
496 *
497 * @ingroup Gengrid
498 */
499EAPI Elm_Object_Item *elm_gengrid_item_insert_after(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Elm_Object_Item *relative, Evas_Smart_Cb func, const void *func_data);
500
501/**
502 * Insert an item in a gengrid widget using a user-defined sort function.
503 *
504 * @param obj The gengrid object.
505 * @param gic The item class for the item.
506 * @param data The item data.
507 * @param comp User defined comparison function that defines the sort order
508 * based on Elm_Gen_Item and its data param.
509 * @param func Convenience function called when the item is selected.
510 * @param func_data Data to be passed to @p func.
511 * @return A handle to the item added or @c NULL, on errors.
512 *
513 * This inserts an item in the gengrid based on user defined comparison
514 * function. The two arguments passed to the function @p func are gengrid
515 * item handles to compare.
516 *
517 * @see elm_gengrid_item_append()
518 * @see elm_gengrid_item_prepend()
519 * @see elm_gengrid_item_insert_after()
520 * @see elm_object_item_del()
521 *
522 * @ingroup Gengrid
523 */
524EAPI Elm_Object_Item *elm_gengrid_item_sorted_insert(Evas_Object *obj, const Elm_Gengrid_Item_Class *gic, const void *data, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data);
525
526/**
527 * Get the selected item in a given gengrid widget
528 *
529 * @param obj The gengrid object.
530 * @return The selected item's handle or @c NULL, if none is
531 * selected at the moment (and on errors)
532 *
533 * This returns the selected item in @p obj. If multi selection is
534 * enabled on @p obj (@see elm_gengrid_multi_select_set()), only
535 * the first item in the list is selected, which might not be very
536 * useful. For that case, see elm_gengrid_selected_items_get().
537 *
538 * @ingroup Gengrid
539 */
540EAPI Elm_Object_Item *elm_gengrid_selected_item_get(const Evas_Object *obj);
541
542/**
543 * Get <b>a list</b> of selected items in a given gengrid
544 *
545 * @param obj The gengrid object.
546 * @return The list of selected items or @c NULL, if none is
547 * selected at the moment (and on errors)
548 *
549 * This returns a list of the selected items, in the order that
550 * they appear in the grid. This list is only valid as long as no
551 * more items are selected or unselected (or unselected implicitly
552 * by deletion). The list contains #Gengrid item pointers as
553 * data, naturally.
554 *
555 * @see elm_gengrid_selected_item_get()
556 *
557 * @ingroup Gengrid
558 */
559EAPI const Eina_List *elm_gengrid_selected_items_get(const Evas_Object *obj);
560
561/**
562 * Get a list of realized items in gengrid
563 *
564 * @param obj The gengrid object
565 * @return The list of realized items, nor NULL if none are realized.
566 *
567 * This returns a list of the realized items in the gengrid. The list
568 * contains gengrid item pointers. The list must be freed by the
569 * caller when done with eina_list_free(). The item pointers in the
570 * list are only valid so long as those items are not deleted or the
571 * gengrid is not deleted.
572 *
573 * @see elm_gengrid_realized_items_update()
574 *
575 * @ingroup Gengrid
576 */
577EAPI Eina_List *elm_gengrid_realized_items_get(const Evas_Object *obj);
578
579/**
580 * Update the contents of all realized items.
581 *
582 * @param obj The gengrid object.
583 *
584 * This updates all realized items by calling all the item class functions again
585 * to get the contents, texts and states. Use this when the original
586 * item data has changed and the changes are desired to be reflected.
587 *
588 * To update just one item, use elm_gengrid_item_update().
589 *
590 * @see elm_gengrid_realized_items_get()
591 * @see elm_gengrid_item_update()
592 *
593 * @ingroup Gengrid
594 */
595EAPI void elm_gengrid_realized_items_update(Evas_Object *obj);
596
597/**
598 * Get the first item in a given gengrid widget
599 *
600 * @param obj The gengrid object
601 * @return The first item's handle or @c NULL, if there are no
602 * items in @p obj (and on errors)
603 *
604 * This returns the first item in the @p obj's internal list of
605 * items.
606 *
607 * @see elm_gengrid_last_item_get()
608 *
609 * @ingroup Gengrid
610 */
611EAPI Elm_Object_Item *elm_gengrid_first_item_get(const Evas_Object *obj);
612
613/**
614 * Get the last item in a given gengrid widget
615 *
616 * @param obj The gengrid object
617 * @return The last item's handle or @c NULL, if there are no
618 * items in @p obj (and on errors)
619 *
620 * This returns the last item in the @p obj's internal list of
621 * items.
622 *
623 * @see elm_gengrid_first_item_get()
624 *
625 * @ingroup Gengrid
626 */
627EAPI Elm_Object_Item *elm_gengrid_last_item_get(const Evas_Object *obj);
628
629/**
630 * Set the scrollbar policy
631 *
632 * @param obj The gengrid object
633 * @param policy_h Horizontal scrollbar policy.
634 * @param policy_v Vertical scrollbar policy.
635 *
636 * This sets the scrollbar visibility policy for the given gengrid
637 * scroller. #ELM_SCROLLER_POLICY_AUTO means the scrollbar is
638 * made visible if it is needed, and otherwise kept hidden.
639 * #ELM_SCROLLER_POLICY_ON turns it on all the time, and
640 * #ELM_SCROLLER_POLICY_OFF always keeps it off. This applies
641 * respectively for the horizontal and vertical scrollbars. Default is
642 * #ELM_SCROLLER_POLICY_AUTO
643 *
644 * @see elm_gengrid_scroller_policy_get()
645 *
646 * @ingroup Gengrid
647 */
648EAPI void elm_gengrid_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
649
650/**
651 * Get the scrollbar policy
652 *
653 * @param obj The gengrid object
654 * @param policy_h Pointer to store the horizontal scrollbar policy.
655 * @param policy_v Pointer to store the vertical scrollbar policy.
656 *
657 * @see elm_gengrid_scroller_policy_set()
658 *
659 * @ingroup Gengrid
660 */
661EAPI void elm_gengrid_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
662
663/**
664 * Get the @b next item in a gengrid widget's internal list of items,
665 * given a handle to one of those items.
666 *
667 * @param it The gengrid item to fetch next from
668 * @return The item after @p item, or @c NULL if there's none (and
669 * on errors)
670 *
671 * This returns the item placed after the @p item, on the container
672 * gengrid.
673 *
674 * @see elm_gengrid_item_prev_get()
675 *
676 * @ingroup Gengrid
677 */
678EAPI Elm_Object_Item *elm_gengrid_item_next_get(const Elm_Object_Item *it);
679
680/**
681 * Get the @b previous item in a gengrid widget's internal list of items,
682 * given a handle to one of those items.
683 *
684 * @param it The gengrid item to fetch previous from
685 * @return The item before @p item, or @c NULL if there's none (and
686 * on errors)
687 *
688 * This returns the item placed before the @p item, on the container
689 * gengrid.
690 *
691 * @see elm_gengrid_item_next_get()
692 *
693 * @ingroup Gengrid
694 */
695EAPI Elm_Object_Item *elm_gengrid_item_prev_get(const Elm_Object_Item *it);
696
697/**
698 * Set whether a given gengrid item is selected or not
699 *
700 * @param it The gengrid item
701 * @param selected Use @c EINA_TRUE, to make it selected, @c
702 * EINA_FALSE to make it unselected
703 *
704 * This sets the selected state of an item. If multi-selection is
705 * not enabled on the containing gengrid and @p selected is @c
706 * EINA_TRUE, any other previously selected items will get
707 * unselected in favor of this new one.
708 *
709 * @see elm_gengrid_item_selected_get()
710 *
711 * @ingroup Gengrid
712 */
713EAPI void elm_gengrid_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
714
715/**
716 * Get whether a given gengrid item is selected or not
717 *
718 * @param it The gengrid item
719 * @return @c EINA_TRUE, if it's selected, @c EINA_FALSE otherwise
720 *
721 * This API returns EINA_TRUE for all the items selected in multi-select mode as well.
722 *
723 * @see elm_gengrid_item_selected_set() for more details
724 *
725 * @ingroup Gengrid
726 */
727EAPI Eina_Bool elm_gengrid_item_selected_get(const Elm_Object_Item *it);
728
729/**
730 * Show the portion of a gengrid's internal grid containing a given
731 * item, @b immediately.
732 *
733 * @param it The item to display
734 * @param type Where to position the item in the viewport.
735 *
736 * This causes gengrid to @b redraw its viewport's contents to the
737 * region containing the given @p item item, if it is not fully
738 * visible.
739 *
740 * @see elm_gengrid_item_bring_in()
741 *
742 * @ingroup Gengrid
743 */
744EAPI void elm_gengrid_item_show(Elm_Object_Item *it, Elm_Gengrid_Item_Scrollto_Type type);
745
746/**
747 * Animatedly bring in, to the visible area of a gengrid, a given
748 * item on it.
749 *
750 * @param it The gengrid item to display
751 * @param type Where to position the item in the viewport.
752 *
753 * This causes gengrid to jump to the given @p item and show
754 * it (by scrolling), if it is not fully visible. This will use
755 * animation to do so and take a period of time to complete.
756 *
757 * @see elm_gengrid_item_show()
758 *
759 * @ingroup Gengrid
760 */
761EAPI void elm_gengrid_item_bring_in(Elm_Object_Item *it, Elm_Gengrid_Item_Scrollto_Type type);
762
763/**
764 * Update the contents of a given gengrid item
765 *
766 * @param it The gengrid item
767 *
768 * This updates an item by calling all the item class functions
769 * again to get the contents, texts and states. Use this when the
770 * original item data has changed and you want the changes to be
771 * reflected.
772 *
773 * @ingroup Gengrid
774 */
775EAPI void elm_gengrid_item_update(Elm_Object_Item *it);
776
777/**
778 * Update the item class of a gengrid item.
779 *
780 * This sets another class of the item, changing the way that it is
781 * displayed. After changing the item class, elm_gengrid_item_update() is
782 * called on the item @p it.
783 *
784 * @param it The gengrid item
785 * @param gic The gengrid item class describing the function pointers and the item style.
786 *
787 * @ingroup Gengrid
788 */
789EAPI void elm_gengrid_item_item_class_update(Elm_Object_Item *it, const Elm_Gengrid_Item_Class *gic);
790
791/**
792 * Get the Gengrid Item class for the given Gengrid Item.
793 *
794 * @param it The gengrid item
795 *
796 * This returns the Gengrid_Item_Class for the given item. It can be used to examine
797 * the function pointers and item_style.
798 *
799 * @ingroup Gengrid
800 */
801EAPI const Elm_Gengrid_Item_Class *elm_gengrid_item_item_class_get(const Elm_Object_Item *it);
802
803/**
804 * Get the index of the item. It is only valid once displayed.
805 *
806 * @param it a gengrid item
807 * @return the position inside the list of item.
808 *
809 * @ingroup Gengrid
810 */
811EAPI int elm_gengrid_item_index_get(const Elm_Object_Item *it);
812
813/**
814 * Return how many items are currently in a list
815 *
816 * @param obj The list
817 * @return The total number of list items in the list
818 *
819 * This behavior is O(1) and includes items which may or may not be realized.
820 *
821 * @ingroup Gengrid
822 */
823EAPI unsigned int elm_gengrid_items_count(const Evas_Object *obj);
824
825/**
826 * Add a new gengrid item class in a given gengrid widget.
827 *
828 * @return New allocated a gengrid item class.
829 *
830 * This adds gengrid item class for the gengrid widget. When adding an item,
831 * gengrid_item_{append, prepend, insert} function needs item class of the item.
832 * Given callback parameters are used at retrieving {text, content} of
833 * added item. Set as NULL if it's not used.
834 * If there's no available memory, return can be NULL.
835 *
836 * @see elm_gengrid_item_class_free()
837 * @see elm_gengrid_item_append()
838 *
839 * @ingroup Gengrid
840 */
841EAPI Elm_Gengrid_Item_Class *elm_gengrid_item_class_new(void);
842
843/**
844 * Remove an item class in a given gengrid widget.
845 *
846 * @param itc The itc to be removed.
847 *
848 * This removes item class from the gengrid widget.
849 * Whenever it has no more references to it, item class is going to be freed.
850 * Otherwise it just decreases its reference count.
851 *
852 * @see elm_gengrid_item_class_new()
853 * @see elm_gengrid_item_class_ref()
854 * @see elm_gengrid_item_class_unref()
855 *
856 * @ingroup Gengrid
857 */
858EAPI void elm_gengrid_item_class_free(Elm_Gengrid_Item_Class *itc);
859
860/**
861 * Increments object reference count for the item class.
862 *
863 * @param itc The given item class object to reference
864 *
865 * This API just increases its reference count for item class management.
866 *
867 * @see elm_gengrid_item_class_unref()
868 *
869 * @ingroup Gengrid
870 */
871EAPI void elm_gengrid_item_class_ref(Elm_Gengrid_Item_Class *itc);
872
873/**
874 * Decrements object reference count for the item class.
875 *
876 * @param itc The given item class object to reference
877 *
878 * This API just decreases its reference count for item class management.
879 * Reference count can't be less than 0.
880 *
881 * @see elm_gengrid_item_class_ref()
882 * @see elm_gengrid_item_class_free()
883 *
884 * @ingroup Gengrid
885 */
886EAPI void elm_gengrid_item_class_unref(Elm_Gengrid_Item_Class *itc);
887
888/**
889 * Set the text to be shown in a given gengrid item's tooltips.
890 *
891 * @param it The gengrid item
892 * @param text The text to set in the content
893 *
894 * This call will setup the text to be used as tooltip to that item
895 * (analogous to elm_object_tooltip_text_set(), but being item
896 * tooltips with higher precedence than object tooltips). It can
897 * have only one tooltip at a time, so any previous tooltip data
898 * will get removed.
899 *
900 * In order to set a content or something else as a tooltip, look at
901 * elm_gengrid_item_tooltip_content_cb_set().
902 *
903 * @ingroup Gengrid
904 */
905EAPI void elm_gengrid_item_tooltip_text_set(Elm_Object_Item *it, const char *text);
906
907/**
908 * Set the content to be shown in a given gengrid item's tooltip
909 *
910 * @param it The gengrid item.
911 * @param func The function returning the tooltip contents.
912 * @param data What to provide to @a func as callback data/context.
913 * @param del_cb Called when data is not needed anymore, either when
914 * another callback replaces @p func, the tooltip is unset with
915 * elm_gengrid_item_tooltip_unset() or the owner @p item
916 * dies. This callback receives as its first parameter the
917 * given @p data, being @c event_info the item handle.
918 *
919 * This call will setup the tooltip's contents to @p item
920 * (analogous to elm_object_tooltip_content_cb_set(), but being
921 * item tooltips with higher precedence than object tooltips). It
922 * can have only one tooltip at a time, so any previous tooltip
923 * content will get removed. @p func (with @p data) will be called
924 * every time Elementary needs to show the tooltip and it should
925 * return a valid Evas object, which will be fully managed by the
926 * tooltip system, getting deleted when the tooltip is gone.
927 *
928 * In order to set just a text as a tooltip, look at
929 * elm_gengrid_item_tooltip_text_set().
930 *
931 * @ingroup Gengrid
932 */
933EAPI void elm_gengrid_item_tooltip_content_cb_set(Elm_Object_Item *it, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
934
935/**
936 * Unset a tooltip from a given gengrid item
937 *
938 * @param it gengrid item to remove a previously set tooltip from.
939 *
940 * This call removes any tooltip set on @p item. The callback
941 * provided as @c del_cb to
942 * elm_gengrid_item_tooltip_content_cb_set() will be called to
943 * notify it is not used anymore (and have resources cleaned, if
944 * need be).
945 *
946 * @see elm_gengrid_item_tooltip_content_cb_set()
947 *
948 * @ingroup Gengrid
949 */
950EAPI void elm_gengrid_item_tooltip_unset(Elm_Object_Item *it);
951
952/**
953 * Set a different @b style for a given gengrid item's tooltip.
954 *
955 * @param it gengrid item with tooltip set
956 * @param style the <b>theme style</b> to use on tooltips (e.g. @c
957 * "default", @c "transparent", etc)
958 *
959 * Tooltips can have <b>alternate styles</b> to be displayed on,
960 * which are defined by the theme set on Elementary. This function
961 * works analogously as elm_object_tooltip_style_set(), but here
962 * applied only to gengrid item objects. The default style for
963 * tooltips is @c "default".
964 *
965 * @note before you set a style you should define a tooltip with
966 * elm_gengrid_item_tooltip_content_cb_set() or
967 * elm_gengrid_item_tooltip_text_set()
968 *
969 * @see elm_gengrid_item_tooltip_style_get()
970 *
971 * @ingroup Gengrid
972 */
973EAPI void elm_gengrid_item_tooltip_style_set(Elm_Object_Item *it, const char *style);
974
975/**
976 * Get the style set a given gengrid item's tooltip.
977 *
978 * @param it gengrid item with tooltip already set on.
979 * @return style the theme style in use, which defaults to
980 * "default". If the object does not have a tooltip set,
981 * then @c NULL is returned.
982 *
983 * @see elm_gengrid_item_tooltip_style_set() for more details
984 *
985 * @ingroup Gengrid
986 */
987EAPI const char *elm_gengrid_item_tooltip_style_get(const Elm_Object_Item *it);
988
989/**
990 * @brief Disable size restrictions on an object's tooltip
991 * @param it The tooltip's anchor object
992 * @param disable If EINA_TRUE, size restrictions are disabled
993 * @return EINA_FALSE on failure, EINA_TRUE on success
994 *
995 * This function allows a tooltip to expand beyond its parent window's canvas.
996 * It will instead be limited only by the size of the display.
997 */
998EAPI Eina_Bool elm_gengrid_item_tooltip_window_mode_set(Elm_Object_Item *it, Eina_Bool disable);
999
1000/**
1001 * @brief Retrieve size restriction state of an object's tooltip
1002 * @param it The tooltip's anchor object
1003 * @return If EINA_TRUE, size restrictions are disabled
1004 *
1005 * This function returns whether a tooltip is allowed to expand beyond
1006 * its parent window's canvas.
1007 * It will instead be limited only by the size of the display.
1008 */
1009EAPI Eina_Bool elm_gengrid_item_tooltip_window_mode_get(const Elm_Object_Item *it);
1010
1011/**
1012 * Set the type of mouse pointer/cursor decoration to be shown,
1013 * when the mouse pointer is over the given gengrid widget item
1014 *
1015 * @param it gengrid item to customize cursor on
1016 * @param cursor the cursor type's name
1017 *
1018 * This function works analogously as elm_object_cursor_set(), but
1019 * here the cursor's changing area is restricted to the item's
1020 * area, and not the whole widget's. Note that that item cursors
1021 * have precedence over widget cursors, so that a mouse over @p
1022 * item will always show cursor @p type.
1023 *
1024 * If this function is called twice for an object, a previously set
1025 * cursor will be unset on the second call.
1026 *
1027 * @see elm_object_cursor_set()
1028 * @see elm_gengrid_item_cursor_get()
1029 * @see elm_gengrid_item_cursor_unset()
1030 *
1031 * @ingroup Gengrid
1032 */
1033EAPI void elm_gengrid_item_cursor_set(Elm_Object_Item *it, const char *cursor);
1034
1035/**
1036 * Get the type of mouse pointer/cursor decoration set to be shown,
1037 * when the mouse pointer is over the given gengrid widget item
1038 *
1039 * @param it gengrid item with custom cursor set
1040 * @return the cursor type's name or @c NULL, if no custom cursors
1041 * were set to @p item (and on errors)
1042 *
1043 * @see elm_object_cursor_get()
1044 * @see elm_gengrid_item_cursor_set() for more details
1045 * @see elm_gengrid_item_cursor_unset()
1046 *
1047 * @ingroup Gengrid
1048 */
1049EAPI const char *elm_gengrid_item_cursor_get(const Elm_Object_Item *it);
1050
1051/**
1052 * Unset any custom mouse pointer/cursor decoration set to be
1053 * shown, when the mouse pointer is over the given gengrid widget
1054 * item, thus making it show the @b default cursor again.
1055 *
1056 * @param it a gengrid item
1057 *
1058 * Use this call to undo any custom settings on this item's cursor
1059 * decoration, bringing it back to defaults (no custom style set).
1060 *
1061 * @see elm_object_cursor_unset()
1062 * @see elm_gengrid_item_cursor_set() for more details
1063 *
1064 * @ingroup Gengrid
1065 */
1066EAPI void elm_gengrid_item_cursor_unset(Elm_Object_Item *it);
1067
1068/**
1069 * Set a different @b style for a given custom cursor set for a
1070 * gengrid item.
1071 *
1072 * @param it gengrid item with custom cursor set
1073 * @param style the <b>theme style</b> to use (e.g. @c "default",
1074 * @c "transparent", etc)
1075 *
1076 * This function only makes sense when one is using custom mouse
1077 * cursor decorations <b>defined in a theme file</b> , which can
1078 * have, given a cursor name/type, <b>alternate styles</b> on
1079 * it. It works analogously as elm_object_cursor_style_set(), but
1080 * here applied only to gengrid item objects.
1081 *
1082 * @warning Before you set a cursor style you should have defined a
1083 * custom cursor previously on the item, with
1084 * elm_gengrid_item_cursor_set()
1085 *
1086 * @see elm_gengrid_item_cursor_engine_only_set()
1087 * @see elm_gengrid_item_cursor_style_get()
1088 *
1089 * @ingroup Gengrid
1090 */
1091EAPI void elm_gengrid_item_cursor_style_set(Elm_Object_Item *it, const char *style);
1092
1093/**
1094 * Get the current @b style set for a given gengrid item's custom
1095 * cursor
1096 *
1097 * @param it gengrid item with custom cursor set.
1098 * @return style the cursor style in use. If the object does not
1099 * have a cursor set, then @c NULL is returned.
1100 *
1101 * @see elm_gengrid_item_cursor_style_set() for more details
1102 *
1103 * @ingroup Gengrid
1104 */
1105EAPI const char *elm_gengrid_item_cursor_style_get(const Elm_Object_Item *it);
1106
1107/**
1108 * Set if the (custom) cursor for a given gengrid item should be
1109 * searched in its theme, also, or should only rely on the
1110 * rendering engine.
1111 *
1112 * @param it item with custom (custom) cursor already set on
1113 * @param engine_only Use @c EINA_TRUE to have cursors looked for
1114 * only on those provided by the rendering engine, @c EINA_FALSE to
1115 * have them searched on the widget's theme, as well.
1116 *
1117 * @note This call is of use only if you've set a custom cursor
1118 * for gengrid items, with elm_gengrid_item_cursor_set().
1119 *
1120 * @note By default, cursors will only be looked for between those
1121 * provided by the rendering engine.
1122 *
1123 * @ingroup Gengrid
1124 */
1125EAPI void elm_gengrid_item_cursor_engine_only_set(Elm_Object_Item *it, Eina_Bool engine_only);
1126
1127/**
1128 * Get if the (custom) cursor for a given gengrid item is being
1129 * searched in its theme, also, or is only relying on the rendering
1130 * engine.
1131 *
1132 * @param it a gengrid item
1133 * @return @c EINA_TRUE, if cursors are being looked for only on
1134 * those provided by the rendering engine, @c EINA_FALSE if they
1135 * are being searched on the widget's theme, as well.
1136 *
1137 * @see elm_gengrid_item_cursor_engine_only_set(), for more details
1138 *
1139 * @ingroup Gengrid
1140 */
1141EAPI Eina_Bool elm_gengrid_item_cursor_engine_only_get(const Elm_Object_Item *it);
1142
1143/**
1144 * Set the size for the items of a given gengrid widget
1145 *
1146 * @param obj The gengrid object.
1147 * @param w The items' width.
1148 * @param h The items' height;
1149 *
1150 * A gengrid, after creation, has still no information on the size
1151 * to give to each of its cells. So, you most probably will end up
1152 * with squares one @ref Fingers "finger" wide, the default
1153 * size. Use this function to force a custom size for you items,
1154 * making them as big as you wish.
1155 *
1156 * @see elm_gengrid_item_size_get()
1157 *
1158 * @ingroup Gengrid
1159 */
1160EAPI void elm_gengrid_item_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
1161
1162/**
1163 * Get the size set for the items of a given gengrid widget
1164 *
1165 * @param obj The gengrid object.
1166 * @param w Pointer to a variable where to store the items' width.
1167 * @param h Pointer to a variable where to store the items' height.
1168 *
1169 * @note Use @c NULL pointers on the size values you're not
1170 * interested in: they'll be ignored by the function.
1171 *
1172 * @see elm_gengrid_item_size_get() for more details
1173 *
1174 * @ingroup Gengrid
1175 */
1176EAPI void elm_gengrid_item_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
1177
1178/**
1179 * Set the size for the group items of a given gengrid widget
1180 *
1181 * @param obj The gengrid object.
1182 * @param w The group items' width.
1183 * @param h The group items' height;
1184 *
1185 * A gengrid, after creation, has still no information on the size
1186 * to give to each of its cells. So, you most probably will end up
1187 * with squares one @ref Fingers "finger" wide, the default
1188 * size. Use this function to force a custom size for you group items,
1189 * making them as big as you wish.
1190 *
1191 * @see elm_gengrid_group_item_size_get()
1192 *
1193 * @ingroup Gengrid
1194 */
1195EAPI void elm_gengrid_group_item_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
1196
1197/**
1198 * Get the size set for the group items of a given gengrid widget
1199 *
1200 * @param obj The gengrid object.
1201 * @param w Pointer to a variable where to store the group items' width.
1202 * @param h Pointer to a variable where to store the group items' height.
1203 *
1204 * @note Use @c NULL pointers on the size values you're not
1205 * interested in: they'll be ignored by the function.
1206 *
1207 * @see elm_gengrid_group_item_size_get() for more details
1208 *
1209 * @ingroup Gengrid
1210 */
1211EAPI void elm_gengrid_group_item_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
1212
1213/**
1214 * Set the items grid's alignment within a given gengrid widget
1215 *
1216 * @param obj The gengrid object.
1217 * @param align_x Alignment in the horizontal axis (0 <= align_x <= 1).
1218 * @param align_y Alignment in the vertical axis (0 <= align_y <= 1).
1219 *
1220 * This sets the alignment of the whole grid of items of a gengrid
1221 * within its given viewport. By default, those values are both
1222 * 0.5, meaning that the gengrid will have its items grid placed
1223 * exactly in the middle of its viewport.
1224 *
1225 * @note If given alignment values are out of the cited ranges,
1226 * they'll be changed to the nearest boundary values on the valid
1227 * ranges.
1228 *
1229 * @see elm_gengrid_align_get()
1230 *
1231 * @ingroup Gengrid
1232 */
1233EAPI void elm_gengrid_align_set(Evas_Object *obj, double align_x, double align_y);
1234
1235/**
1236 * Get the items grid's alignment values within a given gengrid
1237 * widget
1238 *
1239 * @param obj The gengrid object.
1240 * @param align_x Pointer to a variable where to store the
1241 * horizontal alignment.
1242 * @param align_y Pointer to a variable where to store the vertical
1243 * alignment.
1244 *
1245 * @note Use @c NULL pointers on the alignment values you're not
1246 * interested in: they'll be ignored by the function.
1247 *
1248 * @see elm_gengrid_align_set() for more details
1249 *
1250 * @ingroup Gengrid
1251 */
1252EAPI void elm_gengrid_align_get(const Evas_Object *obj, double *align_x, double *align_y);
1253
1254/**
1255 * Set whether a given gengrid widget is or not able have items
1256 * @b reordered
1257 *
1258 * @param obj The gengrid object
1259 * @param reorder_mode Use @c EINA_TRUE to turn reordering on,
1260 * @c EINA_FALSE to turn it off
1261 *
1262 * If a gengrid is set to allow reordering, a click held for more
1263 * than 0.5 over a given item will highlight it specially,
1264 * signaling the gengrid has entered the reordering state. From
1265 * that time on, the user will be able to, while still holding the
1266 * mouse button down, move the item freely in the gengrid's
1267 * viewport, replacing to said item to the locations it goes to.
1268 * The replacements will be animated and, whenever the user
1269 * releases the mouse button, the item being replaced gets a new
1270 * definitive place in the grid.
1271 *
1272 * @see elm_gengrid_reorder_mode_get()
1273 *
1274 * @ingroup Gengrid
1275 */
1276EAPI void elm_gengrid_reorder_mode_set(Evas_Object *obj, Eina_Bool reorder_mode);
1277
1278/**
1279 * Get whether a given gengrid widget is or not able have items
1280 * @b reordered
1281 *
1282 * @param obj The gengrid object
1283 * @return @c EINA_TRUE, if reordering is on, @c EINA_FALSE if it's
1284 * off
1285 *
1286 * @see elm_gengrid_reorder_mode_set() for more details
1287 *
1288 * @ingroup Gengrid
1289 */
1290EAPI Eina_Bool elm_gengrid_reorder_mode_get(const Evas_Object *obj);
1291
1292
1293/**
1294 * Set a given gengrid widget's scrolling page size, relative to
1295 * its viewport size.
1296 *
1297 * @param obj The gengrid object
1298 * @param h_pagerel The horizontal page (relative) size
1299 * @param v_pagerel The vertical page (relative) size
1300 *
1301 * The gengrid's scroller is capable of binding scrolling by the
1302 * user to "pages". It means that, while scrolling and, specially
1303 * after releasing the mouse button, the grid will @b snap to the
1304 * nearest displaying page's area. When page sizes are set, the
1305 * grid's continuous content area is split into (equal) page sized
1306 * pieces.
1307 *
1308 * This function sets the size of a page <b>relatively to the
1309 * viewport dimensions</b> of the gengrid, for each axis. A value
1310 * @c 1.0 means "the exact viewport's size", in that axis, while @c
1311 * 0.0 turns paging off in that axis. Likewise, @c 0.5 means "half
1312 * a viewport". Sane usable values are, than, between @c 0.0 and @c
1313 * 1.0. Values beyond those will make it behave behave
1314 * inconsistently. If you only want one axis to snap to pages, use
1315 * the value @c 0.0 for the other one.
1316 *
1317 * There is a function setting page size values in @b absolute
1318 * values, too -- elm_gengrid_page_size_set(). Naturally, its use
1319 * is mutually exclusive to this one.
1320 *
1321 * @see elm_gengrid_page_relative_get()
1322 *
1323 * @ingroup Gengrid
1324 */
1325EAPI void elm_gengrid_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel);
1326
1327/**
1328 * Get a given gengrid widget's scrolling page size, relative to
1329 * its viewport size.
1330 *
1331 * @param obj The gengrid object
1332 * @param h_pagerel Pointer to a variable where to store the
1333 * horizontal page (relative) size
1334 * @param v_pagerel Pointer to a variable where to store the
1335 * vertical page (relative) size
1336 *
1337 * @see elm_gengrid_page_relative_set() for more details
1338 *
1339 * @ingroup Gengrid
1340 */
1341EAPI void elm_gengrid_page_relative_get(const Evas_Object *obj, double *h_pagerel, double *v_pagerel);
1342
1343/**
1344 * Set a given gengrid widget's scrolling page size
1345 *
1346 * @param obj The gengrid object
1347 * @param h_pagesize The horizontal page size, in pixels
1348 * @param v_pagesize The vertical page size, in pixels
1349 *
1350 * The gengrid's scroller is capable of binding scrolling by the
1351 * user to "pages". It means that, while scrolling and, specially
1352 * after releasing the mouse button, the grid will @b snap to the
1353 * nearest displaying page's area. When page sizes are set, the
1354 * grid's continuous content area is split into (equal) page sized
1355 * pieces.
1356 *
1357 * This function sets the size of a page of the gengrid, in pixels,
1358 * for each axis. Sane usable values are, between @c 0 and the
1359 * dimensions of @p obj, for each axis. Values beyond those will
1360 * make it behave behave inconsistently. If you only want one axis
1361 * to snap to pages, use the value @c 0 for the other one.
1362 *
1363 * There is a function setting page size values in @b relative
1364 * values, too -- elm_gengrid_page_relative_set(). Naturally, its
1365 * use is mutually exclusive to this one.
1366 *
1367 * @ingroup Gengrid
1368 */
1369EAPI void elm_gengrid_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize);
1370
1371/**
1372 * @brief Get gengrid current page number.
1373 *
1374 * @param obj The gengrid object
1375 * @param h_pagenumber The horizontal page number
1376 * @param v_pagenumber The vertical page number
1377 *
1378 * The page number starts from 0. 0 is the first page.
1379 * Current page means the page which meet the top-left of the viewport.
1380 * If there are two or more pages in the viewport, it returns the number of page
1381 * which meet the top-left of the viewport.
1382 *
1383 * @see elm_gengrid_last_page_get()
1384 * @see elm_gengrid_page_show()
1385 * @see elm_gengrid_page_bring_in()
1386 */
1387EAPI void elm_gengrid_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
1388
1389/**
1390 * @brief Get gengrid last page number.
1391 *
1392 * @param obj The gengrid object
1393 * @param h_pagenumber The horizontal page number
1394 * @param v_pagenumber The vertical page number
1395 *
1396 * The page number starts from 0. 0 is the first page.
1397 * This returns the last page number among the pages.
1398 *
1399 * @see elm_gengrid_current_page_get()
1400 * @see elm_gengrid_page_show()
1401 * @see elm_gengrid_page_bring_in()
1402 */
1403EAPI void elm_gengrid_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
1404
1405/**
1406 * Show a specific virtual region within the gengrid content object by page number.
1407 *
1408 * @param obj The gengrid object
1409 * @param h_pagenumber The horizontal page number
1410 * @param v_pagenumber The vertical page number
1411 *
1412 * 0, 0 of the indicated page is located at the top-left of the viewport.
1413 * This will jump to the page directly without animation.
1414 *
1415 * Example of usage:
1416 *
1417 * @code
1418 * sc = elm_gengrid_add(win);
1419 * elm_gengrid_content_set(sc, content);
1420 * elm_gengrid_page_relative_set(sc, 1, 0);
1421 * elm_gengrid_current_page_get(sc, &h_page, &v_page);
1422 * elm_gengrid_page_show(sc, h_page + 1, v_page);
1423 * @endcode
1424 *
1425 * @see elm_gengrid_page_bring_in()
1426 */
1427EAPI void elm_gengrid_page_show(const Evas_Object *obj, int h_pagenumber, int v_pagenumber);
1428
1429/**
1430 * Show a specific virtual region within the gengrid content object by page number.
1431 *
1432 * @param obj The gengrid object
1433 * @param h_pagenumber The horizontal page number
1434 * @param v_pagenumber The vertical page number
1435 *
1436 * 0, 0 of the indicated page is located at the top-left of the viewport.
1437 * This will slide to the page with animation.
1438 *
1439 * Example of usage:
1440 *
1441 * @code
1442 * sc = elm_gengrid_add(win);
1443 * elm_gengrid_content_set(sc, content);
1444 * elm_gengrid_page_relative_set(sc, 1, 0);
1445 * elm_gengrid_last_page_get(sc, &h_page, &v_page);
1446 * elm_gengrid_page_bring_in(sc, h_page, v_page);
1447 * @endcode
1448 *
1449 * @see elm_gengrid_page_show()
1450 */
1451EAPI void elm_gengrid_page_bring_in(const Evas_Object *obj, int h_pagenumber, int v_pagenumber);
1452
1453/**
1454 * Get a given gengrid item's position, relative to the whole
1455 * gengrid's grid area.
1456 *
1457 * @param it The Gengrid item.
1458 * @param x Pointer to variable to store the item's <b>row number</b>.
1459 * @param y Pointer to variable to store the item's <b>column number</b>.
1460 *
1461 * This returns the "logical" position of the item within the
1462 * gengrid. For example, @c (0, 1) would stand for first row,
1463 * second column.
1464 *
1465 * @ingroup Gengrid
1466 */
1467EAPI void elm_gengrid_item_pos_get(const Elm_Object_Item *it, unsigned int *x, unsigned int *y);
1468
1469/**
1470 * Set how the items grid's filled within a given gengrid widget
1471 *
1472 * @param obj The gengrid object.
1473 * @param fill Filled if True
1474 *
1475 * This sets the fill state of the whole grid of items of a gengrid
1476 * within its given viewport. By default, this value is false, meaning
1477 * that if the first line of items grid's isn't filled, the items are
1478 * centered with the alignment
1479 *
1480 * @see elm_gengrid_filled_get()
1481 *
1482 * @ingroup Gengrid
1483 *
1484 */
1485EAPI void elm_gengrid_filled_set(Evas_Object *obj, Eina_Bool fill);
1486
1487/**
1488 * Get how the items grid's filled within a given gengrid widget
1489 *
1490 * @param obj The gengrid object.
1491 * @return @c EINA_TRUE, if filled is on, @c EINA_FALSE if it's
1492 * off
1493 *
1494 * @note Use @c NULL pointers on the alignment values you're not
1495 * interested in: they'll be ignored by the function.
1496 *
1497 * @see elm_gengrid_align_set() for more details
1498 *
1499 * @ingroup Gengrid
1500 */
1501EAPI Eina_Bool elm_gengrid_filled_get(const Evas_Object *obj);
1502
1503/**
1504 * Set the gengrid select mode.
1505 *
1506 * @param obj The gengrid object
1507 * @param mode The select mode
1508 *
1509 * elm_gengrid_select_mode_set() changes item select mode in the gengrid widget.
1510 * - ELM_OBJECT_SELECT_MODE_DEFAULT : Items will only call their selection func and
1511 * callback when first becoming selected. Any further clicks will
1512 * do nothing, unless you set always select mode.
1513 * - ELM_OBJECT_SELECT_MODE_ALWAYS : This means that, even if selected,
1514 * every click will make the selected callbacks be called.
1515 * - ELM_OBJECT_SELECT_MODE_NONE : This will turn off the ability to select items
1516 * entirely and they will neither appear selected nor call selected
1517 * callback functions.
1518 *
1519 * @see elm_gengrid_select_mode_get()
1520 *
1521 * @ingroup Gengrid
1522 */
1523EAPI void elm_gengrid_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode);
1524
1525/**
1526 * Get the gengrid select mode.
1527 *
1528 * @param obj The gengrid object
1529 * @return The select mode
1530 * (If getting mode is failed, it returns ELM_OBJECT_SELECT_MODE_MAX)
1531 *
1532 * @see elm_gengrid_select_mode_set()
1533 *
1534 * @ingroup Gengrid
1535 */
1536EAPI Elm_Object_Select_Mode elm_gengrid_select_mode_get(const Evas_Object *obj);
1537
1538/**
1539 * Set whether the gengrid items' should be highlighted when item selected.
1540 *
1541 * @param obj The gengrid object.
1542 * @param highlight @c EINA_TRUE to enable highlight or @c EINA_FALSE to
1543 * disable it.
1544 *
1545 * This will turn on/off the highlight effect when items are selected and
1546 * they will or will not be highlighted. The selected and clicked
1547 * callback functions will still be called.
1548 *
1549 * highlight is enabled by default.
1550 *
1551 * @see elm_gengrid_highlight_mode_get().
1552 *
1553 * @ingroup Gengrid
1554 */
1555
1556EAPI void elm_gengrid_highlight_mode_set(Evas_Object *obj, Eina_Bool highlight);
1557
1558/**
1559 * Get whether the gengrid items' should be highlighted when item selected.
1560 *
1561 * @param obj The gengrid object.
1562 * @return @c EINA_TRUE means items can be highlighted. @c EINA_FALSE indicates
1563 * they can't. If @p obj is @c NULL, @c EINA_FALSE is returned.
1564 *
1565 * @see elm_gengrid_highlight_mode_set() for details.
1566 *
1567 * @ingroup Gengrid
1568 */
1569
1570EAPI Eina_Bool elm_gengrid_highlight_mode_get(const Evas_Object *obj);
1571
1572/**
1573 * Set the gengrid item's select mode.
1574 *
1575 * @param it The gengrid item object
1576 * @param mode The select mode
1577 *
1578 * elm_gengrid_select_mode_set() changes item's select mode.
1579 * - ELM_OBJECT_SELECT_MODE_DEFAULT : The item will only call their selection func and
1580 * callback when first becoming selected. Any further clicks will
1581 * do nothing, unless you set always select mode.
1582 * - ELM_OBJECT_SELECT_MODE_ALWAYS : This means that, even if selected,
1583 * every click will make the selected callbacks be called.
1584 * - ELM_OBJECT_SELECT_MODE_NONE : This will turn off the ability to select the item
1585 * entirely and they will neither appear selected nor call selected
1586 * callback functions.
1587 * - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY : This will apply no-finger-size rule
1588 * with ELM_OBJECT_SELECT_MODE_NONE. No-finger-size rule makes an item can be
1589 * smaller than lower limit. Clickable objects should be bigger than
1590 * human touch point device (your finger) for some touch or
1591 * small screen devices. So it is enabled, the item can be shrink than
1592 * predefined finger-size value. And the item will be updated.
1593 *
1594 * @see elm_gengrid_item_select_mode_get()
1595 *
1596 * @ingroup Gengrid
1597 */
1598EAPI void elm_gengrid_item_select_mode_set(Elm_Object_Item *it, Elm_Object_Select_Mode mode);
1599
1600/**
1601 * Get the gengrid item's select mode.
1602 *
1603 * @param it The gengrid item object
1604 * @return The select mode
1605 * (If getting mode is failed, it returns ELM_OBJECT_SELECT_MODE_MAX)
1606 *
1607 * @see elm_gengrid_item_select_mode_set()
1608 *
1609 * @ingroup Gengrid
1610 */
1611EAPI Elm_Object_Select_Mode elm_gengrid_item_select_mode_get(const Elm_Object_Item *it);
1612
1613/**
1614 * @}
1615 */
diff --git a/libraries/elementary/src/lib/elm_genlist.c b/libraries/elementary/src/lib/elm_genlist.c
new file mode 100644
index 0000000..c8e5c69
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_genlist.c
@@ -0,0 +1,6231 @@
1#include <assert.h>
2#include <fnmatch.h>
3#include <Elementary.h>
4#include <Elementary_Cursor.h>
5#include "elm_priv.h"
6#include "els_scroller.h"
7#include "elm_gen_common.h"
8
9// internally allocated
10#define CLASS_ALLOCATED 0x3a70f11f
11
12#define MAX_ITEMS_PER_BLOCK 32
13#define REORDER_EFFECT_TIME 0.5
14
15#define ELM_GEN_SETUP(wd) \
16 (wd)->calc_cb = (Ecore_Cb)_calc_job; \
17 (wd)->clear_cb = (Ecore_Cb)_clear_cb; \
18 (wd)->sizing_cb = (Ecore_Cb)_sizing_eval
19
20#define ELM_GEN_ITEM_SETUP(it) \
21 (it)->del_cb = (Ecore_Cb)_item_del; \
22 (it)->highlight_cb = (Ecore_Cb)_item_highlight; \
23 (it)->unsel_cb = (Ecore_Cb)_item_unselect; \
24 (it)->unhighlight_cb = (Ecore_Cb)_item_unhighlight; \
25 (it)->unrealize_cb = (Ecore_Cb)_item_unrealize_cb
26
27#define ELM_GENLIST_CHECK_ITC_VER(itc) \
28 do \
29 { \
30 if (!itc) \
31 { \
32 ERR("Genlist_Item_Class(itc) is NULL"); \
33 return; \
34 } \
35 if ((itc->version != ELM_GENLIST_ITEM_CLASS_VERSION) && \
36 (itc->version != CLASS_ALLOCATED)) \
37 { \
38 ERR("Genlist_Item_Class version mismatched! current = (%d), required = (%d) or (%d)", itc->version, ELM_GENLIST_ITEM_CLASS_VERSION, CLASS_ALLOCATED); \
39 return; \
40 } \
41 } \
42 while (0)
43
44typedef struct _Item_Block Item_Block;
45typedef struct _Item_Cache Item_Cache;
46
47struct Elm_Gen_Item_Type
48{
49 Elm_Gen_Item *it;
50 Item_Block *block;
51 Eina_List *items;
52 Evas_Coord w, h, minw, minh;
53 Elm_Gen_Item *group_item;
54 Elm_Genlist_Item_Type type;
55 Eina_List *deco_it_texts, *deco_it_contents, *deco_it_states, *deco_it_content_objs;
56 Eina_List *deco_all_texts, *deco_all_contents, *deco_all_states, *deco_all_content_objs;
57 Eina_List *flip_contents, *flip_content_objs;
58 Ecore_Timer *swipe_timer;
59 Evas_Coord scrl_x, scrl_y, old_scrl_y;
60
61 Elm_Gen_Item *rel;
62 Evas_Object *deco_it_view;
63 int expanded_depth;
64 int order_num_in;
65
66 Eina_Bool before : 1;
67
68 Eina_Bool want_realize : 1;
69 Eina_Bool expanded : 1;
70 Eina_Bool mincalcd : 1;
71 Eina_Bool queued : 1;
72 Eina_Bool showme : 1;
73 Eina_Bool updateme : 1;
74 Eina_Bool nocache : 1; /* do not use cache for this item */
75 Eina_Bool nocache_once : 1; /* do not use cache for this item only once */
76 Eina_Bool stacking_even : 1;
77 Eina_Bool nostacking : 1;
78 Eina_Bool move_effect_enabled : 1;
79 Eina_Bool decorate_all_item_realized : 1;
80 Eina_Bool tree_effect_finished : 1; /* tree effect */
81 Eina_Bool tree_effect_hideme : 1; /* item hide for tree effect */
82};
83
84struct _Item_Block
85{
86 EINA_INLIST;
87 int count;
88 int num;
89 int reorder_offset;
90 Widget_Data *wd;
91 Eina_List *items;
92 Evas_Coord x, y, w, h, minw, minh;
93 int position;
94 int item_position_stamp;
95
96 Eina_Bool position_update : 1;
97 Eina_Bool want_unrealize : 1;
98 Eina_Bool realized : 1;
99 Eina_Bool changed : 1;
100 Eina_Bool updateme : 1;
101 Eina_Bool showme : 1;
102 Eina_Bool must_recalc : 1;
103};
104
105struct _Item_Cache
106{
107 EINA_INLIST;
108
109 Evas_Object *base_view, *spacer;
110
111 const char *item_style; // it->itc->item_style
112 Eina_Bool tree : 1; // it->group
113
114 Eina_Bool selected : 1; // it->selected
115 Eina_Bool disabled : 1; // it->disabled
116 Eina_Bool expanded : 1; // it->item->expanded
117};
118
119static const char *widtype = NULL;
120static void _item_cache_zero(Widget_Data *wd);
121static void _del_hook(Evas_Object *obj);
122static void _mirrored_set(Evas_Object *obj,
123 Eina_Bool rtl);
124static void _theme_hook(Evas_Object *obj);
125static void _show_region_hook(void *data,
126 Evas_Object *obj);
127static void _sizing_eval(Evas_Object *obj);
128static void _item_realize(Elm_Gen_Item *it,
129 int in,
130 Eina_Bool calc);
131static void _item_unrealize_cb(Elm_Gen_Item *it);
132static void _item_block_unrealize(Item_Block *itb);
133static void _calc_job(void *data);
134static void _on_focus_hook(void *data,
135 Evas_Object *obj);
136static Eina_Bool _item_multi_select_up(Widget_Data *wd);
137static Eina_Bool _item_multi_select_down(Widget_Data *wd);
138static Eina_Bool _item_single_select_up(Widget_Data *wd);
139static Eina_Bool _item_single_select_down(Widget_Data *wd);
140static Eina_Bool _event_hook(Evas_Object *obj,
141 Evas_Object *src,
142 Evas_Callback_Type type,
143 void *event_info);
144static void _signal_emit_hook(Evas_Object *obj,
145 const char *emission,
146 const char *source);
147static Eina_Bool _deselect_all_items(Widget_Data *wd);
148static void _pan_calculate(Evas_Object *obj);
149static void _pan_max_get(Evas_Object *obj,
150 Evas_Coord *x,
151 Evas_Coord *y);
152static void _item_position(Elm_Gen_Item *it,
153 Evas_Object *obj,
154 Evas_Coord it_x,
155 Evas_Coord it_y);
156static void _decorate_item_realize(Elm_Gen_Item *it);
157static void _decorate_item_unrealize(Elm_Gen_Item *it);
158static void _decorate_item_set(Elm_Gen_Item *it);
159static void _decorate_item_unset(Widget_Data *wd);
160static void _decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity);
161static void _decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on);
162static void _decorate_all_item_unrealize(Elm_Gen_Item *it);
163static void _group_items_recalc(void *data);
164static void _item_move_after(Elm_Gen_Item *it,
165 Elm_Gen_Item *after);
166static void _item_move_before(Elm_Gen_Item *it,
167 Elm_Gen_Item *before);
168static void _item_auto_scroll(Widget_Data *wd);
169static void _elm_genlist_clear(Evas_Object *obj,
170 Eina_Bool standby);
171static void _pan_child_size_get(Evas_Object *obj,
172 Evas_Coord *w,
173 Evas_Coord *h);
174static Evas_Object* _create_tray_alpha_bg(const Evas_Object *obj);
175static void _item_contract_emit(Elm_Gen_Item *it);
176static int _item_tree_effect_before(Elm_Gen_Item *it);
177static void _item_tree_effect(Widget_Data *wd, int y);
178static void _item_tree_effect_finish(Widget_Data *wd);
179static Eina_Bool _tree_effect_animator_cb(void *data);
180
181static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_VERSION;
182
183static const char SIG_ACTIVATED[] = "activated";
184static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
185static const char SIG_SELECTED[] = "selected";
186static const char SIG_UNSELECTED[] = "unselected";
187static const char SIG_EXPANDED[] = "expanded";
188static const char SIG_CONTRACTED[] = "contracted";
189static const char SIG_EXPAND_REQUEST[] = "expand,request";
190static const char SIG_CONTRACT_REQUEST[] = "contract,request";
191static const char SIG_REALIZED[] = "realized";
192static const char SIG_UNREALIZED[] = "unrealized";
193static const char SIG_DRAG_START_UP[] = "drag,start,up";
194static const char SIG_DRAG_START_DOWN[] = "drag,start,down";
195static const char SIG_DRAG_START_LEFT[] = "drag,start,left";
196static const char SIG_DRAG_START_RIGHT[] = "drag,start,right";
197static const char SIG_DRAG_STOP[] = "drag,stop";
198static const char SIG_DRAG[] = "drag";
199static const char SIG_LONGPRESSED[] = "longpressed";
200static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
201static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
202static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
203static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
204static const char SIG_EDGE_TOP[] = "edge,top";
205static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
206static const char SIG_EDGE_LEFT[] = "edge,left";
207static const char SIG_EDGE_RIGHT[] = "edge,right";
208static const char SIG_MULTI_SWIPE_LEFT[] = "multi,swipe,left";
209static const char SIG_MULTI_SWIPE_RIGHT[] = "multi,swipe,right";
210static const char SIG_MULTI_SWIPE_UP[] = "multi,swipe,up";
211static const char SIG_MULTI_SWIPE_DOWN[] = "multi,swipe,down";
212static const char SIG_MULTI_PINCH_OUT[] = "multi,pinch,out";
213static const char SIG_MULTI_PINCH_IN[] = "multi,pinch,in";
214static const char SIG_SWIPE[] = "swipe";
215static const char SIG_MOVED[] = "moved";
216static const char SIG_MOVED_AFTER[] = "moved,after";
217static const char SIG_MOVED_BEFORE[] = "moved,before";
218static const char SIG_INDEX_UPDATE[] = "index,update";
219static const char SIG_TREE_EFFECT_FINISHED [] = "tree,effect,finished";
220
221static const Evas_Smart_Cb_Description _signals[] = {
222 {SIG_CLICKED_DOUBLE, ""},
223 {SIG_ACTIVATED, ""},
224 {SIG_SELECTED, ""},
225 {SIG_UNSELECTED, ""},
226 {SIG_EXPANDED, ""},
227 {SIG_CONTRACTED, ""},
228 {SIG_EXPAND_REQUEST, ""},
229 {SIG_CONTRACT_REQUEST, ""},
230 {SIG_REALIZED, ""},
231 {SIG_UNREALIZED, ""},
232 {SIG_DRAG_START_UP, ""},
233 {SIG_DRAG_START_DOWN, ""},
234 {SIG_DRAG_START_LEFT, ""},
235 {SIG_DRAG_START_RIGHT, ""},
236 {SIG_DRAG_STOP, ""},
237 {SIG_DRAG, ""},
238 {SIG_LONGPRESSED, ""},
239 {SIG_SCROLL_ANIM_START, ""},
240 {SIG_SCROLL_ANIM_STOP, ""},
241 {SIG_SCROLL_DRAG_START, ""},
242 {SIG_SCROLL_DRAG_STOP, ""},
243 {SIG_EDGE_TOP, ""},
244 {SIG_EDGE_BOTTOM, ""},
245 {SIG_EDGE_LEFT, ""},
246 {SIG_EDGE_RIGHT, ""},
247 {SIG_MULTI_SWIPE_LEFT, ""},
248 {SIG_MULTI_SWIPE_RIGHT, ""},
249 {SIG_MULTI_SWIPE_UP, ""},
250 {SIG_MULTI_SWIPE_DOWN, ""},
251 {SIG_MULTI_PINCH_OUT, ""},
252 {SIG_MULTI_PINCH_IN, ""},
253 {SIG_SWIPE, ""},
254 {SIG_MOVED, ""},
255 {SIG_MOVED_AFTER, ""},
256 {SIG_MOVED_BEFORE, ""},
257 {SIG_TREE_EFFECT_FINISHED, ""},
258 {NULL, NULL}
259};
260
261/* TEMPORARY */
262#undef ELM_CHECK_WIDTYPE
263#define ELM_CHECK_WIDTYPE(obj, widtype) \
264 if ((!obj) || (!elm_genlist_type_check((obj), __func__))) return
265#undef ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN
266#define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...) \
267 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
268 ELM_CHECK_WIDTYPE(WIDGET((it)), widtype) __VA_ARGS__;
269
270static const char *_gengrid = NULL;
271static const char *_genlist = NULL;
272
273/* THIS FUNCTION IS HACKY AND TEMPORARY!!! */
274Eina_Bool
275elm_genlist_type_check(const Evas_Object *obj,
276 const char *func)
277{
278 const char *provided, *expected = "(unknown)";
279 static int abort_on_warn = -1;
280 provided = elm_widget_type_get(obj);
281 if (!_genlist) _genlist = eina_stringshare_add("genlist");
282 if (!_gengrid) _gengrid = eina_stringshare_add("gengrid");
283 if (EINA_LIKELY(provided == _genlist) || EINA_LIKELY(provided == _gengrid))
284 return EINA_TRUE;
285 if ((!provided) || (!provided[0]))
286 {
287 provided = evas_object_type_get(obj);
288 if ((!provided) || (!provided[0]))
289 provided = "(unknown)";
290 }
291 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
292 if (abort_on_warn == -1)
293 {
294 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
295 else abort_on_warn = 0;
296 }
297 if (abort_on_warn == 1) abort();
298 return EINA_FALSE;
299}
300
301static Eina_Bool
302_event_hook(Evas_Object *obj,
303 Evas_Object *src __UNUSED__,
304 Evas_Callback_Type type,
305 void *event_info)
306{
307 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
308 Evas_Event_Key_Down *ev = event_info;
309 Widget_Data *wd = elm_widget_data_get(obj);
310 Evas_Coord pan_max_x = 0, pan_max_y = 0;
311 if (!wd) return EINA_FALSE;
312 if (!wd->items) return EINA_FALSE;
313 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
314 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
315
316 Elm_Object_Item *it = NULL;
317 Evas_Coord x = 0;
318 Evas_Coord y = 0;
319 Evas_Coord step_x = 0;
320 Evas_Coord step_y = 0;
321 Evas_Coord v_w = 0;
322 Evas_Coord v_h = 0;
323 Evas_Coord page_x = 0;
324 Evas_Coord page_y = 0;
325
326 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
327 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
328 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
329 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
330
331 if ((!strcmp(ev->keyname, "Left")) ||
332 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
333 {
334 x -= step_x;
335 }
336 else if ((!strcmp(ev->keyname, "Right")) ||
337 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
338 {
339 x += step_x;
340 }
341 else if ((!strcmp(ev->keyname, "Up")) ||
342 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
343 {
344 if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
345 (_item_multi_select_up(wd)))
346 || (_item_single_select_up(wd)))
347 {
348 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
349 return EINA_TRUE;
350 }
351 else
352 y -= step_y;
353 }
354 else if ((!strcmp(ev->keyname, "Down")) ||
355 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
356 {
357 if (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
358 (_item_multi_select_down(wd)))
359 || (_item_single_select_down(wd)))
360 {
361 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
362 return EINA_TRUE;
363 }
364 else
365 y += step_y;
366 }
367 else if ((!strcmp(ev->keyname, "Home")) ||
368 ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
369 {
370 it = elm_genlist_first_item_get(obj);
371 elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
372 elm_genlist_item_selected_set(it, EINA_TRUE);
373 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
374 return EINA_TRUE;
375 }
376 else if ((!strcmp(ev->keyname, "End")) ||
377 ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
378 {
379 it = elm_genlist_last_item_get(obj);
380 elm_genlist_item_bring_in(it, ELM_GENLIST_ITEM_SCROLLTO_IN);
381 elm_genlist_item_selected_set(it, EINA_TRUE);
382 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
383 return EINA_TRUE;
384 }
385 else if ((!strcmp(ev->keyname, "Prior")) ||
386 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
387 {
388 if (page_y < 0)
389 y -= -(page_y * v_h) / 100;
390 else
391 y -= page_y;
392 }
393 else if ((!strcmp(ev->keyname, "Next")) ||
394 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
395 {
396 if (page_y < 0)
397 y += -(page_y * v_h) / 100;
398 else
399 y += page_y;
400 }
401 else if (!strcmp(ev->keyname, "Escape"))
402 {
403 if (!_deselect_all_items(wd)) return EINA_FALSE;
404 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
405 return EINA_TRUE;
406 }
407 else if (((!strcmp(ev->keyname, "Return")) ||
408 (!strcmp(ev->keyname, "KP_Enter")) ||
409 (!strcmp(ev->keyname, "space")))
410 && (!wd->multi) && (wd->selected))
411 {
412 it = elm_genlist_selected_item_get(obj);
413 elm_genlist_item_expanded_set(it,
414 !elm_genlist_item_expanded_get(it));
415 evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
416 }
417 else return EINA_FALSE;
418
419 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
420 _pan_max_get(wd->pan_smart, &pan_max_x, &pan_max_y);
421 if (x < 0) x = 0;
422 if (x > pan_max_x) x = pan_max_x;
423 if (y < 0) y = 0;
424 if (y > pan_max_y) y = pan_max_y;
425 elm_smart_scroller_child_pos_set(wd->scr, x, y);
426 return EINA_TRUE;
427}
428
429static Eina_Bool
430_deselect_all_items(Widget_Data *wd)
431{
432 if (!wd->selected) return EINA_FALSE;
433 while (wd->selected)
434 elm_genlist_item_selected_set(wd->selected->data, EINA_FALSE);
435
436 return EINA_TRUE;
437}
438
439static Eina_Bool
440_item_multi_select_up(Widget_Data *wd)
441{
442 if (!wd->selected) return EINA_FALSE;
443 if (!wd->multi) return EINA_FALSE;
444
445 Elm_Object_Item *prev = elm_genlist_item_prev_get(wd->last_selected_item);
446 if (!prev) return EINA_TRUE;
447
448 if (elm_genlist_item_selected_get(prev))
449 {
450 elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
451 wd->last_selected_item = prev;
452 elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
453 }
454 else
455 {
456 elm_genlist_item_selected_set(prev, EINA_TRUE);
457 elm_genlist_item_show(prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
458 }
459 return EINA_TRUE;
460}
461
462static Eina_Bool
463_item_multi_select_down(Widget_Data *wd)
464{
465 if (!wd->selected) return EINA_FALSE;
466 if (!wd->multi) return EINA_FALSE;
467
468 Elm_Object_Item *next;
469 next = elm_genlist_item_next_get(wd->last_selected_item);
470 if (!next) return EINA_TRUE;
471
472 if (elm_genlist_item_selected_get(next))
473 {
474 elm_genlist_item_selected_set(wd->last_selected_item, EINA_FALSE);
475 wd->last_selected_item = next;
476 elm_genlist_item_show(wd->last_selected_item, ELM_GENLIST_ITEM_SCROLLTO_IN);
477 }
478 else
479 {
480 elm_genlist_item_selected_set(next, EINA_TRUE);
481 elm_genlist_item_show(next, ELM_GENLIST_ITEM_SCROLLTO_IN);
482 }
483 return EINA_TRUE;
484}
485
486static Eina_Bool
487_item_single_select_up(Widget_Data *wd)
488{
489 Elm_Gen_Item *prev;
490 if (!wd->selected)
491 {
492 prev = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
493 while ((prev) && (prev->generation < wd->generation))
494 prev = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(prev)->prev);
495 }
496 else prev = (Elm_Gen_Item *) elm_genlist_item_prev_get(wd->last_selected_item);
497
498 if (!prev) return EINA_FALSE;
499
500 _deselect_all_items(wd);
501
502 elm_genlist_item_selected_set((Elm_Object_Item *) prev, EINA_TRUE);
503 elm_genlist_item_show((Elm_Object_Item *) prev, ELM_GENLIST_ITEM_SCROLLTO_IN);
504 return EINA_TRUE;
505}
506
507static Eina_Bool
508_item_single_select_down(Widget_Data *wd)
509{
510 Elm_Gen_Item *next;
511 if (!wd->selected)
512 {
513 next = ELM_GEN_ITEM_FROM_INLIST(wd->items);
514 while ((next) && (next->generation < wd->generation))
515 next = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(next)->next);
516 }
517 else next = (Elm_Gen_Item *) elm_genlist_item_next_get(wd->last_selected_item);
518
519 if (!next) return EINA_FALSE;
520
521 _deselect_all_items(wd);
522
523 elm_genlist_item_selected_set((Elm_Object_Item *) next, EINA_TRUE);
524 elm_genlist_item_show((Elm_Object_Item *) next, ELM_GENLIST_ITEM_SCROLLTO_IN);
525 return EINA_TRUE;
526}
527
528static void
529_on_focus_hook(void *data __UNUSED__,
530 Evas_Object *obj)
531{
532 Widget_Data *wd = elm_widget_data_get(obj);
533 if (!wd) return;
534 if (elm_widget_focus_get(obj))
535 {
536 elm_object_signal_emit(wd->obj, "elm,action,focus", "elm");
537 evas_object_focus_set(wd->obj, EINA_TRUE);
538 if ((wd->selected) && (!wd->last_selected_item))
539 wd->last_selected_item = eina_list_data_get(wd->selected);
540 }
541 else
542 {
543 elm_object_signal_emit(wd->obj, "elm,action,unfocus", "elm");
544 evas_object_focus_set(wd->obj, EINA_FALSE);
545 }
546}
547
548static void
549_del_hook(Evas_Object *obj)
550{
551 Widget_Data *wd = elm_widget_data_get(obj);
552 if (!wd) return;
553 _item_cache_zero(wd);
554 if (wd->calc_job) ecore_job_del(wd->calc_job);
555 if (wd->update_job) ecore_job_del(wd->update_job);
556 if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
557 if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
558 if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
559 if (wd->decorate_it_type) eina_stringshare_del(wd->decorate_it_type);
560 if (wd->scr_hold_timer) ecore_timer_del(wd->scr_hold_timer);
561 if (wd->tree_effect_animator) ecore_animator_del(wd->tree_effect_animator);
562 free(wd);
563}
564
565static void
566_del_pre_hook(Evas_Object *obj)
567{
568 Widget_Data *wd = elm_widget_data_get(obj);
569 if (!wd) return;
570 if (wd->decorate_all_mode) elm_genlist_decorate_mode_set(wd->obj, EINA_FALSE);
571 elm_genlist_clear(obj);
572 evas_object_del(wd->pan_smart);
573 wd->pan_smart = NULL;
574}
575
576static void
577_mirrored_set(Evas_Object *obj,
578 Eina_Bool rtl)
579{
580 Widget_Data *wd = elm_widget_data_get(obj);
581 if (!wd) return;
582 _item_cache_zero(wd);
583 elm_smart_scroller_mirrored_set(wd->scr, rtl);
584}
585
586static void
587_theme_hook(Evas_Object *obj)
588{
589 Widget_Data *wd = elm_widget_data_get(obj);
590 Item_Block *itb;
591 if (!wd) return;
592 evas_event_freeze(evas_object_evas_get(wd->obj));
593 _item_cache_zero(wd);
594 _elm_widget_mirrored_reload(obj);
595 _mirrored_set(obj, elm_widget_mirrored_get(obj));
596 elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
597 elm_widget_style_get(obj));
598 edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
599 wd->item_width = wd->item_height = 0;
600 wd->group_item_width = wd->group_item_height = 0;
601 wd->minw = wd->minh = wd->realminw = 0;
602 EINA_INLIST_FOREACH(wd->blocks, itb)
603 {
604 Eina_List *l;
605 Elm_Gen_Item *it;
606
607 if (itb->realized) _item_block_unrealize(itb);
608 EINA_LIST_FOREACH(itb->items, l, it)
609 it->item->mincalcd = EINA_FALSE;
610
611 itb->changed = EINA_TRUE;
612 }
613 if (wd->calc_job) ecore_job_del(wd->calc_job);
614 wd->calc_job = ecore_job_add(_calc_job, wd);
615 _sizing_eval(obj);
616 evas_event_thaw(evas_object_evas_get(wd->obj));
617 evas_event_thaw_eval(evas_object_evas_get(wd->obj));
618}
619
620static void
621_show_region_hook(void *data,
622 Evas_Object *obj)
623{
624 Widget_Data *wd = elm_widget_data_get(data);
625 Evas_Coord x, y, w, h;
626 if (!wd) return;
627 elm_widget_show_region_get(obj, &x, &y, &w, &h);
628 //x & y are screen coordinates, Add with pan coordinates
629 x += wd->pan_x;
630 y += wd->pan_y;
631 elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
632}
633
634static void
635_translate_hook(Evas_Object *obj)
636{
637 evas_object_smart_callback_call(obj, "language,changed", NULL);
638}
639
640static void
641_sizing_eval(Evas_Object *obj)
642{
643 Widget_Data *wd = elm_widget_data_get(obj);
644 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
645 Evas_Coord vmw = 0, vmh = 0;
646 if (!wd) return;
647
648 evas_object_size_hint_min_get(wd->scr, &minw, NULL);
649 evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
650
651 edje_object_size_min_calc
652 (elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
653
654 if (wd->mode == ELM_LIST_COMPRESS)
655 {
656 Evas_Coord vw, vh;
657
658 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
659 if ((vw != 0) && (vw != wd->prev_viewport_w))
660 {
661 Item_Block *itb;
662
663 wd->prev_viewport_w = vw;
664 EINA_INLIST_FOREACH(wd->blocks, itb)
665 {
666 itb->must_recalc = EINA_TRUE;
667 }
668 if (wd->calc_job) ecore_job_del(wd->calc_job);
669 wd->calc_job = ecore_job_add(_calc_job, wd);
670 }
671 minw = vmw;
672 minh = vmh;
673 }
674 else if (wd->mode == ELM_LIST_LIMIT)
675 {
676 maxw = -1;
677 minw = vmw + minw;
678 }
679 else
680 {
681 minw = vmw;
682 minh = vmh;
683 }
684
685 evas_object_size_hint_min_set(obj, minw, minh);
686 evas_object_size_hint_max_set(obj, maxw, maxh);
687}
688
689static void
690_signal_emit_hook(Evas_Object *obj,
691 const char *emission,
692 const char *source)
693{
694 Widget_Data *wd = elm_widget_data_get(obj);
695 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
696 emission, source);
697}
698
699static void
700_item_highlight(Elm_Gen_Item *it)
701{
702 const char *selectraise;
703 if ((it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
704 (!it->wd->highlight) ||
705 (it->generation < it->wd->generation) ||
706 (it->highlighted) || elm_widget_item_disabled_get(it) ||
707 (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) || (it->item->deco_it_view) ||
708 (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
709 return;
710 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
711 if (it->deco_all_view) edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
712 selectraise = edje_object_data_get(VIEW(it), "selectraise");
713 if ((selectraise) && (!strcmp(selectraise, "on")))
714 {
715 if (it->deco_all_view) evas_object_raise(it->deco_all_view);
716 else evas_object_raise(VIEW(it));
717 if ((it->item->group_item) && (it->item->group_item->realized))
718 evas_object_raise(it->item->VIEW(group_item));
719 }
720 it->highlighted = EINA_TRUE;
721}
722
723static void
724_item_unhighlight(Elm_Gen_Item *it)
725{
726 if ((it->generation < it->wd->generation) || (!it->highlighted)) return;
727 edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
728 if (it->deco_all_view) edje_object_signal_emit(it->deco_all_view, "elm,state,unselected", "elm");
729 if (!it->item->nostacking)
730 {
731 if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
732 {
733 if (it->deco_all_view) evas_object_lower(it->deco_all_view);
734 else evas_object_lower(VIEW(it));
735 }
736 else
737 {
738 if (it->deco_all_view) evas_object_raise(it->deco_all_view);
739 else evas_object_raise(VIEW(it));
740 }
741 }
742 it->highlighted = EINA_FALSE;
743}
744
745static void
746_item_block_position_update(Eina_Inlist *list, int idx)
747{
748 Item_Block *tmp;
749
750 EINA_INLIST_FOREACH(list, tmp)
751 {
752 tmp->position = idx++;
753 tmp->position_update = EINA_TRUE;
754 }
755}
756
757static void
758_item_position_update(Eina_List *list, int idx)
759{
760 Elm_Gen_Item *it;
761 Eina_List *l;
762
763 EINA_LIST_FOREACH(list, l, it)
764 {
765 it->position = idx++;
766 it->position_update = EINA_TRUE;
767 }
768}
769
770static void
771_item_block_del(Elm_Gen_Item *it)
772{
773 Eina_Inlist *il;
774 Item_Block *itb = it->item->block;
775
776 itb->items = eina_list_remove(itb->items, it);
777 itb->count--;
778 itb->changed = EINA_TRUE;
779 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
780 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
781 if (itb->count < 1)
782 {
783 il = EINA_INLIST_GET(itb);
784 Item_Block *itbn = (Item_Block *)(il->next);
785 if (it->parent)
786 it->parent->item->items = eina_list_remove(it->parent->item->items, it);
787 else
788 {
789 _item_block_position_update(il->next, itb->position);
790 it->wd->blocks = eina_inlist_remove(it->wd->blocks, il);
791 }
792 free(itb);
793 if (itbn) itbn->changed = EINA_TRUE;
794 }
795 else
796 {
797 if (itb->count < itb->wd->max_items_per_block/2)
798 {
799 il = EINA_INLIST_GET(itb);
800 Item_Block *itbp = (Item_Block *)(il->prev);
801 Item_Block *itbn = (Item_Block *)(il->next);
802 if ((itbp) && ((itbp->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
803 {
804 Elm_Gen_Item *it2;
805
806 EINA_LIST_FREE(itb->items, it2)
807 {
808 it2->item->block = itbp;
809 itbp->items = eina_list_append(itbp->items, it2);
810 itbp->count++;
811 itbp->changed = EINA_TRUE;
812 }
813 _item_block_position_update(EINA_INLIST_GET(itb)->next,
814 itb->position);
815 it->wd->blocks = eina_inlist_remove(it->wd->blocks,
816 EINA_INLIST_GET(itb));
817 free(itb);
818 }
819 else if ((itbn) && ((itbn->count + itb->count) < itb->wd->max_items_per_block + itb->wd->max_items_per_block/2))
820 {
821 while (itb->items)
822 {
823 Eina_List *last = eina_list_last(itb->items);
824 Elm_Gen_Item *it2 = last->data;
825
826 it2->item->block = itbn;
827 itb->items = eina_list_remove_list(itb->items, last);
828 itbn->items = eina_list_prepend(itbn->items, it2);
829 itbn->count++;
830 itbn->changed = EINA_TRUE;
831 }
832 _item_block_position_update(EINA_INLIST_GET(itb)->next,
833 itb->position);
834 it->wd->blocks =
835 eina_inlist_remove(it->wd->blocks, EINA_INLIST_GET(itb));
836 free(itb);
837 }
838 }
839 }
840}
841
842static void
843_item_subitems_clear(Elm_Gen_Item *it)
844{
845 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
846 Eina_List *tl = NULL, *l;
847 Elm_Object_Item *it2;
848
849 EINA_LIST_FOREACH(it->item->items, l, it2)
850 tl = eina_list_append(tl, it2);
851 EINA_LIST_FREE(tl, it2)
852 elm_object_item_del(it2);
853}
854
855static void
856_item_del(Elm_Gen_Item *it)
857{
858 Evas_Object *obj = WIDGET(it);
859 Widget_Data *wd = it->wd;
860
861 evas_event_freeze(evas_object_evas_get(obj));
862 elm_genlist_item_subitems_clear((Elm_Object_Item *)it);
863 if (wd->show_item == it) wd->show_item = NULL;
864 if (it->realized) _elm_genlist_item_unrealize(it, EINA_FALSE);
865 if (it->item->decorate_all_item_realized) _decorate_all_item_unrealize(it);
866 if (it->item->block) _item_block_del(it);
867 if (it->item->queued)
868 wd->queue = eina_list_remove(wd->queue, it);
869 if (wd->anchor_item == it)
870 {
871 wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
872 if (!wd->anchor_item)
873 wd->anchor_item = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
874 }
875 if (wd->expanded_item == it)
876 {
877 wd->expanded_item = NULL;
878 if (wd->tree_effect_animator)
879 {
880 ecore_animator_del(wd->tree_effect_animator);
881 wd->tree_effect_animator = NULL;
882 }
883 wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
884 }
885 if (wd->expanded_next_item == it) wd->expanded_next_item = NULL;
886 if (wd->move_items) wd->move_items = eina_list_remove(wd->move_items, it);
887 if (it->parent)
888 it->parent->item->items = eina_list_remove(it->parent->item->items, it);
889 if (it->item->swipe_timer)
890 {
891 ecore_timer_del(it->item->swipe_timer);
892 it->item->swipe_timer = NULL;
893 }
894 _elm_genlist_item_del_serious(it);
895 elm_genlist_item_class_unref((Elm_Genlist_Item_Class *)it->itc);
896 evas_event_thaw(evas_object_evas_get(obj));
897 evas_event_thaw_eval(evas_object_evas_get(obj));
898}
899
900static void
901_clear_cb(Widget_Data *wd)
902{
903 wd->anchor_item = NULL;
904 if (wd->queue_idle_enterer)
905 {
906 ecore_idle_enterer_del(wd->queue_idle_enterer);
907 wd->queue_idle_enterer = NULL;
908 }
909 if (wd->must_recalc_idler)
910 {
911 ecore_idler_del(wd->must_recalc_idler);
912 wd->must_recalc_idler = NULL;
913 }
914 if (wd->queue) wd->queue = eina_list_free(wd->queue);
915 if (wd->reorder_move_animator)
916 {
917 ecore_animator_del(wd->reorder_move_animator);
918 wd->reorder_move_animator = NULL;
919 }
920 wd->show_item = NULL;
921 wd->reorder_old_pan_y = 0;
922}
923
924static void
925_item_unselect(Elm_Gen_Item *it)
926{
927 if ((it->generation < it->wd->generation) || (!it->selected)) return;
928 it->selected = EINA_FALSE;
929 it->wd->selected = eina_list_remove(it->wd->selected, it);
930 evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
931}
932
933static void
934_mouse_move(void *data,
935 Evas *evas __UNUSED__,
936 Evas_Object *obj,
937 void *event_info)
938{
939 Elm_Gen_Item *it = data;
940 Evas_Event_Mouse_Move *ev = event_info;
941 Evas_Coord minw = 0, minh = 0, x, y, dx, dy, adx, ady;
942 Evas_Coord ox, oy, ow, oh, it_scrl_y, y_pos;
943
944 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
945 {
946 if (!it->wd->on_hold)
947 {
948 it->wd->on_hold = EINA_TRUE;
949 if ((!it->wd->wasselected) && (!it->flipped))
950 {
951 _item_unhighlight(it);
952 _item_unselect(it);
953 }
954 }
955 }
956 if (it->wd->multitouched)
957 {
958 it->wd->cur_x = ev->cur.canvas.x;
959 it->wd->cur_y = ev->cur.canvas.y;
960 return;
961 }
962 if ((it->dragging) && (it->down))
963 {
964 if (it->wd->movements == SWIPE_MOVES) it->wd->swipe = EINA_TRUE;
965 else
966 {
967 it->wd->history[it->wd->movements].x = ev->cur.canvas.x;
968 it->wd->history[it->wd->movements].y = ev->cur.canvas.y;
969 if (abs((it->wd->history[it->wd->movements].x -
970 it->wd->history[0].x)) > 40)
971 it->wd->swipe = EINA_TRUE;
972 else
973 it->wd->movements++;
974 }
975 if (it->long_timer)
976 {
977 ecore_timer_del(it->long_timer);
978 it->long_timer = NULL;
979 }
980 evas_object_smart_callback_call(WIDGET(it), SIG_DRAG, it);
981 return;
982 }
983 if ((!it->down) /* || (it->wd->on_hold)*/ || (it->wd->longpressed))
984 {
985 if (it->long_timer)
986 {
987 ecore_timer_del(it->long_timer);
988 it->long_timer = NULL;
989 }
990 if ((it->wd->reorder_mode) && (it->wd->reorder_it))
991 {
992 evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
993 it_scrl_y = ev->cur.canvas.y - it->wd->reorder_it->dy;
994
995 if (!it->wd->reorder_start_y)
996 it->wd->reorder_start_y = it->item->block->y + it->y;
997
998 if (it_scrl_y < oy)
999 y_pos = oy;
1000 else if (it_scrl_y + it->wd->reorder_it->item->h > oy + oh)
1001 y_pos = oy + oh - it->wd->reorder_it->item->h;
1002 else
1003 y_pos = it_scrl_y;
1004
1005 if (it->deco_all_view)
1006 _item_position(it, it->deco_all_view, it->item->scrl_x, y_pos);
1007 else
1008 _item_position(it, VIEW(it), it->item->scrl_x, y_pos);
1009
1010 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1011 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1012 }
1013 return;
1014 }
1015 if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
1016 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1017 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1018 x = ev->cur.canvas.x - x;
1019 y = ev->cur.canvas.y - y;
1020 dx = x - it->dx;
1021 adx = dx;
1022 if (adx < 0) adx = -dx;
1023 dy = y - it->dy;
1024 ady = dy;
1025 if (ady < 0) ady = -dy;
1026 minw /= 2;
1027 minh /= 2;
1028 if ((adx > minw) || (ady > minh))
1029 {
1030 it->dragging = EINA_TRUE;
1031 if (it->long_timer)
1032 {
1033 ecore_timer_del(it->long_timer);
1034 it->long_timer = NULL;
1035 }
1036 if (!it->wd->wasselected)
1037 {
1038 _item_unhighlight(it);
1039 _item_unselect(it);
1040 }
1041 if (dy < 0)
1042 {
1043 if (ady > adx)
1044 evas_object_smart_callback_call(WIDGET(it),
1045 SIG_DRAG_START_UP, it);
1046 else
1047 {
1048 if (dx < 0)
1049 evas_object_smart_callback_call(WIDGET(it),
1050 SIG_DRAG_START_LEFT, it);
1051 else
1052 evas_object_smart_callback_call(WIDGET(it),
1053 SIG_DRAG_START_RIGHT, it);
1054 }
1055 }
1056 else
1057 {
1058 if (ady > adx)
1059 evas_object_smart_callback_call(WIDGET(it),
1060 SIG_DRAG_START_DOWN, it);
1061 else
1062 {
1063 if (dx < 0)
1064 evas_object_smart_callback_call(WIDGET(it),
1065 SIG_DRAG_START_LEFT, it);
1066 else
1067 evas_object_smart_callback_call(WIDGET(it),
1068 SIG_DRAG_START_RIGHT, it);
1069 }
1070 }
1071 }
1072}
1073
1074static Eina_Bool
1075_long_press(void *data)
1076{
1077 Elm_Gen_Item *it = data, *it_tmp;
1078 Eina_List *list, *l;
1079
1080 it->long_timer = NULL;
1081 if (elm_widget_item_disabled_get(it) || (it->dragging) ||
1082 (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1083 return ECORE_CALLBACK_CANCEL;
1084 it->wd->longpressed = EINA_TRUE;
1085 evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
1086 if ((it->wd->reorder_mode) && (!it->group))
1087 {
1088 it->wd->reorder_it = it;
1089 it->wd->reorder_start_y = 0;
1090 if (it->deco_all_view)
1091 evas_object_raise(it->deco_all_view);
1092 else
1093 evas_object_raise(VIEW(it));
1094
1095 elm_smart_scroller_hold_set(it->wd->scr, EINA_TRUE);
1096 elm_smart_scroller_bounce_allow_set(it->wd->scr, EINA_FALSE, EINA_FALSE);
1097
1098 list = elm_genlist_realized_items_get(it->wd->obj);
1099 EINA_LIST_FOREACH(list, l, it_tmp)
1100 {
1101 if (it != it_tmp) _item_unselect(it_tmp);
1102 }
1103 if (elm_genlist_item_expanded_get((Elm_Object_Item *)it))
1104 {
1105 elm_genlist_item_expanded_set((Elm_Object_Item *)it, EINA_FALSE);
1106 return ECORE_CALLBACK_RENEW;
1107 }
1108
1109 if (!it->wd->decorate_all_mode)
1110 edje_object_signal_emit(VIEW(it), "elm,state,reorder,enabled", "elm");
1111 }
1112 return ECORE_CALLBACK_CANCEL;
1113}
1114
1115static void
1116_swipe(Elm_Gen_Item *it)
1117{
1118 int i, sum = 0;
1119
1120 if (!it) return;
1121 if ((it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY) ||
1122 elm_widget_item_disabled_get(it)) return;
1123 it->wd->swipe = EINA_FALSE;
1124 for (i = 0; i < it->wd->movements; i++)
1125 {
1126 sum += it->wd->history[i].x;
1127 if (abs(it->wd->history[0].y - it->wd->history[i].y) > 10) return;
1128 }
1129
1130 sum /= it->wd->movements;
1131 if (abs(sum - it->wd->history[0].x) <= 10) return;
1132 evas_object_smart_callback_call(WIDGET(it), SIG_SWIPE, it);
1133}
1134
1135static Eina_Bool
1136_swipe_cancel(void *data)
1137{
1138 Elm_Gen_Item *it = data;
1139
1140 if (!it) return ECORE_CALLBACK_CANCEL;
1141 it->wd->swipe = EINA_FALSE;
1142 it->wd->movements = 0;
1143 return ECORE_CALLBACK_RENEW;
1144}
1145
1146static Eina_Bool
1147_multi_cancel(void *data)
1148{
1149 Widget_Data *wd = data;
1150
1151 if (!wd) return ECORE_CALLBACK_CANCEL;
1152 wd->multi_timeout = EINA_TRUE;
1153 return ECORE_CALLBACK_RENEW;
1154}
1155
1156static void
1157_multi_touch_gesture_eval(void *data)
1158{
1159 Elm_Gen_Item *it = data;
1160
1161 it->wd->multitouched = EINA_FALSE;
1162 if (it->wd->multi_timer)
1163 {
1164 ecore_timer_del(it->wd->multi_timer);
1165 it->wd->multi_timer = NULL;
1166 }
1167 if (it->wd->multi_timeout)
1168 {
1169 it->wd->multi_timeout = EINA_FALSE;
1170 return;
1171 }
1172
1173 Evas_Coord minw = 0, minh = 0;
1174 Evas_Coord off_x, off_y, off_mx, off_my;
1175
1176 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
1177 off_x = abs(it->wd->cur_x - it->wd->prev_x);
1178 off_y = abs(it->wd->cur_y - it->wd->prev_y);
1179 off_mx = abs(it->wd->cur_mx - it->wd->prev_mx);
1180 off_my = abs(it->wd->cur_my - it->wd->prev_my);
1181
1182 if (((off_x > minw) || (off_y > minh)) && ((off_mx > minw) || (off_my > minh)))
1183 {
1184 if ((off_x + off_mx) > (off_y + off_my))
1185 {
1186 if ((it->wd->cur_x > it->wd->prev_x) && (it->wd->cur_mx > it->wd->prev_mx))
1187 evas_object_smart_callback_call(WIDGET(it),
1188 SIG_MULTI_SWIPE_RIGHT, it);
1189 else if ((it->wd->cur_x < it->wd->prev_x) && (it->wd->cur_mx < it->wd->prev_mx))
1190 evas_object_smart_callback_call(WIDGET(it),
1191 SIG_MULTI_SWIPE_LEFT, it);
1192 else if (abs(it->wd->cur_x - it->wd->cur_mx) > abs(it->wd->prev_x - it->wd->prev_mx))
1193 evas_object_smart_callback_call(WIDGET(it),
1194 SIG_MULTI_PINCH_OUT, it);
1195 else
1196 evas_object_smart_callback_call(WIDGET(it),
1197 SIG_MULTI_PINCH_IN, it);
1198 }
1199 else
1200 {
1201 if ((it->wd->cur_y > it->wd->prev_y) && (it->wd->cur_my > it->wd->prev_my))
1202 evas_object_smart_callback_call(WIDGET(it),
1203 SIG_MULTI_SWIPE_DOWN, it);
1204 else if ((it->wd->cur_y < it->wd->prev_y) && (it->wd->cur_my < it->wd->prev_my))
1205 evas_object_smart_callback_call(WIDGET(it),
1206 SIG_MULTI_SWIPE_UP, it);
1207 else if (abs(it->wd->cur_y - it->wd->cur_my) > abs(it->wd->prev_y - it->wd->prev_my))
1208 evas_object_smart_callback_call(WIDGET(it),
1209 SIG_MULTI_PINCH_OUT, it);
1210 else
1211 evas_object_smart_callback_call(WIDGET(it),
1212 SIG_MULTI_PINCH_IN, it);
1213 }
1214 }
1215 it->wd->multi_timeout = EINA_FALSE;
1216}
1217
1218static void
1219_multi_down(void *data,
1220 Evas *evas __UNUSED__,
1221 Evas_Object *obj __UNUSED__,
1222 void *event_info)
1223{
1224 Elm_Gen_Item *it = data;
1225 Evas_Event_Multi_Down *ev = event_info;
1226
1227 if ((it->wd->multi_device != 0) || (it->wd->multitouched) || (it->wd->multi_timeout)) return;
1228 it->wd->multi_device = ev->device;
1229 it->wd->multi_down = EINA_TRUE;
1230 it->wd->multitouched = EINA_TRUE;
1231 it->wd->prev_mx = ev->canvas.x;
1232 it->wd->prev_my = ev->canvas.y;
1233 if (!it->wd->wasselected)
1234 {
1235 _item_unhighlight(it);
1236 _item_unselect(it);
1237 }
1238 it->wd->wasselected = EINA_FALSE;
1239 it->wd->longpressed = EINA_FALSE;
1240 if (it->long_timer)
1241 {
1242 ecore_timer_del(it->long_timer);
1243 it->long_timer = NULL;
1244 }
1245 if (it->dragging)
1246 {
1247 it->dragging = EINA_FALSE;
1248 evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1249 }
1250 if (it->item->swipe_timer)
1251 {
1252 ecore_timer_del(it->item->swipe_timer);
1253 it->item->swipe_timer = NULL;
1254 }
1255 if (it->wd->on_hold)
1256 {
1257 it->wd->swipe = EINA_FALSE;
1258 it->wd->movements = 0;
1259 it->wd->on_hold = EINA_FALSE;
1260 }
1261}
1262
1263static void
1264_multi_up(void *data,
1265 Evas *evas __UNUSED__,
1266 Evas_Object *obj __UNUSED__,
1267 void *event_info)
1268{
1269 Elm_Gen_Item *it = data;
1270 Evas_Event_Multi_Up *ev = event_info;
1271
1272 if (it->wd->multi_device != ev->device) return;
1273 it->wd->multi_device = 0;
1274 it->wd->multi_down = EINA_FALSE;
1275 if (it->wd->mouse_down) return;
1276 _multi_touch_gesture_eval(data);
1277}
1278
1279static void
1280_multi_move(void *data,
1281 Evas *evas __UNUSED__,
1282 Evas_Object *obj __UNUSED__,
1283 void *event_info)
1284{
1285 Elm_Gen_Item *it = data;
1286 Evas_Event_Multi_Move *ev = event_info;
1287
1288 if (it->wd->multi_device != ev->device) return;
1289 it->wd->cur_mx = ev->cur.canvas.x;
1290 it->wd->cur_my = ev->cur.canvas.y;
1291}
1292
1293static void
1294_mouse_down(void *data,
1295 Evas *evas __UNUSED__,
1296 Evas_Object *obj,
1297 void *event_info)
1298{
1299 Elm_Gen_Item *it = data;
1300 Evas_Event_Mouse_Down *ev = event_info;
1301 Evas_Coord x, y;
1302
1303 if (ev->button != 1) return;
1304 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1305 {
1306 it->wd->on_hold = EINA_TRUE;
1307 }
1308
1309 it->down = EINA_TRUE;
1310 it->dragging = EINA_FALSE;
1311 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
1312 it->dx = ev->canvas.x - x;
1313 it->dy = ev->canvas.y - y;
1314 it->wd->mouse_down = EINA_TRUE;
1315 if (!it->wd->multitouched)
1316 {
1317 it->wd->prev_x = ev->canvas.x;
1318 it->wd->prev_y = ev->canvas.y;
1319 it->wd->multi_timeout = EINA_FALSE;
1320 if (it->wd->multi_timer) ecore_timer_del(it->wd->multi_timer);
1321 it->wd->multi_timer = ecore_timer_add(1, _multi_cancel, it->wd);
1322 }
1323 it->wd->longpressed = EINA_FALSE;
1324 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1325 else it->wd->on_hold = EINA_FALSE;
1326 if (it->wd->on_hold) return;
1327 it->wd->wasselected = it->selected;
1328 _item_highlight(it);
1329 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1330 if ((!elm_widget_item_disabled_get(it)) &&
1331 (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1332 {
1333 evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
1334 evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
1335 }
1336 if (it->item->swipe_timer) ecore_timer_del(it->item->swipe_timer);
1337 it->item->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
1338 if (it->long_timer) ecore_timer_del(it->long_timer);
1339 if (it->realized)
1340 it->long_timer = ecore_timer_add(it->wd->longpress_timeout, _long_press,
1341 it);
1342 else
1343 it->long_timer = NULL;
1344 it->wd->swipe = EINA_FALSE;
1345 it->wd->movements = 0;
1346}
1347
1348static void
1349_mouse_up(void *data,
1350 Evas *evas __UNUSED__,
1351 Evas_Object *obj __UNUSED__,
1352 void *event_info)
1353{
1354 Elm_Gen_Item *it = data;
1355 Evas_Event_Mouse_Up *ev = event_info;
1356 Eina_Bool dragged = EINA_FALSE;
1357
1358 if (ev->button != 1) return;
1359 it->down = EINA_FALSE;
1360 it->wd->mouse_down = EINA_FALSE;
1361 if (it->wd->multitouched)
1362 {
1363 if ((!it->wd->multi) && (!it->selected) && (it->highlighted)) _item_unhighlight(it);
1364 if (it->wd->multi_down) return;
1365 _multi_touch_gesture_eval(data);
1366 return;
1367 }
1368 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) it->wd->on_hold = EINA_TRUE;
1369 else it->wd->on_hold = EINA_FALSE;
1370 if (it->long_timer)
1371 {
1372 ecore_timer_del(it->long_timer);
1373 it->long_timer = NULL;
1374 }
1375 if (it->dragging)
1376 {
1377 it->dragging = EINA_FALSE;
1378 evas_object_smart_callback_call(WIDGET(it), SIG_DRAG_STOP, it);
1379 dragged = 1;
1380 }
1381 if (it->item->swipe_timer)
1382 {
1383 ecore_timer_del(it->item->swipe_timer);
1384 it->item->swipe_timer = NULL;
1385 }
1386 if (it->wd->multi_timer)
1387 {
1388 ecore_timer_del(it->wd->multi_timer);
1389 it->wd->multi_timer = NULL;
1390 it->wd->multi_timeout = EINA_FALSE;
1391 }
1392 if (it->wd->on_hold)
1393 {
1394 if (it->wd->swipe) _swipe(data);
1395 it->wd->longpressed = EINA_FALSE;
1396 it->wd->on_hold = EINA_FALSE;
1397 return;
1398 }
1399 if ((it->wd->reorder_mode) && (it->wd->reorder_it))
1400 {
1401 Evas_Coord it_scrl_y = ev->canvas.y - it->wd->reorder_it->dy;
1402
1403 if (it->wd->reorder_rel && (it->wd->reorder_it->parent == it->wd->reorder_rel->parent))
1404 {
1405 if (it_scrl_y <= it->wd->reorder_rel->item->scrl_y)
1406 _item_move_before(it->wd->reorder_it, it->wd->reorder_rel);
1407 else
1408 _item_move_after(it->wd->reorder_it, it->wd->reorder_rel);
1409 evas_object_smart_callback_call(WIDGET(it), SIG_MOVED, it);
1410 }
1411 else
1412 {
1413 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
1414 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
1415 }
1416 edje_object_signal_emit(VIEW(it), "elm,state,reorder,disabled", "elm");
1417 it->wd->reorder_it = it->wd->reorder_rel = NULL;
1418 elm_smart_scroller_hold_set(it->wd->scr, EINA_FALSE);
1419 elm_smart_scroller_bounce_allow_set(it->wd->scr, it->wd->h_bounce, it->wd->v_bounce);
1420 }
1421 if (it->wd->longpressed)
1422 {
1423 it->wd->longpressed = EINA_FALSE;
1424 if ((!it->wd->wasselected) && (!it->flipped))
1425 {
1426 _item_unhighlight(it);
1427 _item_unselect(it);
1428 }
1429 it->wd->wasselected = EINA_FALSE;
1430 return;
1431 }
1432 if (dragged)
1433 {
1434 if (it->want_unrealize)
1435 {
1436 _elm_genlist_item_unrealize(it, EINA_FALSE);
1437 if (it->item->block->want_unrealize)
1438 _item_block_unrealize(it->item->block);
1439 }
1440 }
1441 if (elm_widget_item_disabled_get(it) || (dragged) ||
1442 (it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY))
1443 return;
1444 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1445 if (it->wd->multi)
1446 {
1447 if (!it->selected)
1448 {
1449 _item_highlight(it);
1450 it->sel_cb(it);
1451 }
1452 else
1453 {
1454 _item_unhighlight(it);
1455 _item_unselect(it);
1456 }
1457 }
1458 else
1459 {
1460 if (!it->selected)
1461 {
1462 Widget_Data *wd = it->wd;
1463 if (wd)
1464 {
1465 while (wd->selected)
1466 {
1467 _item_unhighlight(wd->selected->data);
1468 _item_unselect(wd->selected->data);
1469 }
1470 }
1471 }
1472 else
1473 {
1474 const Eina_List *l, *l_next;
1475 Elm_Gen_Item *it2;
1476
1477 EINA_LIST_FOREACH_SAFE(it->wd->selected, l, l_next, it2)
1478 if (it2 != it)
1479 {
1480 _item_unhighlight(it2);
1481 _item_unselect(it2);
1482 }
1483 //_item_highlight(it);
1484 //_item_select(it);
1485 }
1486 _item_highlight(it);
1487 it->sel_cb(it);
1488 }
1489}
1490
1491static void
1492_item_mouse_callbacks_add(Elm_Gen_Item *it, Evas_Object *view)
1493{
1494 evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_DOWN,
1495 _mouse_down, it);
1496 evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_UP,
1497 _mouse_up, it);
1498 evas_object_event_callback_add(view, EVAS_CALLBACK_MOUSE_MOVE,
1499 _mouse_move, it);
1500 evas_object_event_callback_add(view, EVAS_CALLBACK_MULTI_DOWN,
1501 _multi_down, it);
1502 evas_object_event_callback_add(view, EVAS_CALLBACK_MULTI_UP,
1503 _multi_up, it);
1504 evas_object_event_callback_add(view, EVAS_CALLBACK_MULTI_MOVE,
1505 _multi_move, it);
1506}
1507
1508static void
1509_item_mouse_callbacks_del(Elm_Gen_Item *it, Evas_Object *view)
1510{
1511 evas_object_event_callback_del_full(view, EVAS_CALLBACK_MOUSE_DOWN,
1512 _mouse_down, it);
1513 evas_object_event_callback_del_full(view, EVAS_CALLBACK_MOUSE_UP,
1514 _mouse_up, it);
1515 evas_object_event_callback_del_full(view, EVAS_CALLBACK_MOUSE_MOVE,
1516 _mouse_move, it);
1517 evas_object_event_callback_del_full(view, EVAS_CALLBACK_MULTI_DOWN,
1518 _multi_down, it);
1519 evas_object_event_callback_del_full(view, EVAS_CALLBACK_MULTI_UP,
1520 _multi_up, it);
1521 evas_object_event_callback_del_full(view, EVAS_CALLBACK_MULTI_MOVE,
1522 _multi_move, it);
1523}
1524
1525static void
1526_signal_expand_toggle(void *data,
1527 Evas_Object *obj __UNUSED__,
1528 const char *emission __UNUSED__,
1529 const char *source __UNUSED__)
1530{
1531 Elm_Gen_Item *it = data;
1532
1533 if (it->item->expanded)
1534 evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1535 else
1536 evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1537}
1538
1539static void
1540_signal_expand(void *data,
1541 Evas_Object *obj __UNUSED__,
1542 const char *emission __UNUSED__,
1543 const char *source __UNUSED__)
1544{
1545 Elm_Gen_Item *it = data;
1546
1547 if (!it->item->expanded)
1548 evas_object_smart_callback_call(WIDGET(it), SIG_EXPAND_REQUEST, it);
1549}
1550
1551static void
1552_signal_contract(void *data,
1553 Evas_Object *obj __UNUSED__,
1554 const char *emission __UNUSED__,
1555 const char *source __UNUSED__)
1556{
1557 Elm_Gen_Item *it = data;
1558
1559 if (it->item->expanded)
1560 evas_object_smart_callback_call(WIDGET(it), SIG_CONTRACT_REQUEST, it);
1561}
1562
1563static Eina_Bool
1564_scr_hold_timer_cb(void *data)
1565{
1566 if (!data) return ECORE_CALLBACK_CANCEL;
1567 Widget_Data *wd = data;
1568 elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1569 wd->scr_hold_timer = NULL;
1570 return ECORE_CALLBACK_CANCEL;
1571}
1572
1573static void
1574_decorate_item_finished_signal_cb(void *data,
1575 Evas_Object *obj,
1576 const char *emission __UNUSED__,
1577 const char *source __UNUSED__)
1578{
1579 if (!data) return;
1580 if (!obj) return;
1581 Elm_Gen_Item *it = data;
1582 if ((it->generation < it->wd->generation) || (!it->realized) || (!it->item->deco_it_view)) return;
1583 char buf[1024];
1584 Evas *te = evas_object_evas_get(obj);
1585
1586 evas_event_freeze(te);
1587 it->item->nocache_once = EINA_FALSE;
1588 _decorate_item_unrealize(it);
1589 if (it->item->group_item)
1590 evas_object_raise(it->item->VIEW(group_item));
1591 snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->decorate_it_type);
1592 edje_object_signal_callback_del_full(obj, buf, "elm", _decorate_item_finished_signal_cb, it);
1593 evas_event_thaw(te);
1594 evas_event_thaw_eval(te);
1595}
1596
1597static void
1598_item_cache_clean(Widget_Data *wd)
1599{
1600 evas_event_freeze(evas_object_evas_get(wd->obj));
1601 while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
1602 {
1603 Item_Cache *itc;
1604
1605 itc = EINA_INLIST_CONTAINER_GET(wd->item_cache->last, Item_Cache);
1606 wd->item_cache = eina_inlist_remove(wd->item_cache,
1607 wd->item_cache->last);
1608 wd->item_cache_count--;
1609 if (itc->spacer) evas_object_del(itc->spacer);
1610 if (itc->base_view) evas_object_del(itc->base_view);
1611 eina_stringshare_del(itc->item_style);
1612 free(itc);
1613 }
1614 evas_event_thaw(evas_object_evas_get(wd->obj));
1615 evas_event_thaw_eval(evas_object_evas_get(wd->obj));
1616}
1617
1618static void
1619_item_cache_zero(Widget_Data *wd)
1620{
1621 int pmax = wd->item_cache_max;
1622 wd->item_cache_max = 0;
1623 _item_cache_clean(wd);
1624 wd->item_cache_max = pmax;
1625}
1626
1627static void
1628_item_cache_add(Elm_Gen_Item *it)
1629{
1630 Item_Cache *itc;
1631
1632 evas_event_freeze(evas_object_evas_get(it->wd->obj));
1633 if (it->wd->item_cache_max <= 0)
1634 {
1635 evas_object_del(VIEW(it));
1636 VIEW(it) = NULL;
1637 if (it->spacer)
1638 {
1639 evas_object_del(it->spacer);
1640 it->spacer = NULL;
1641 }
1642 evas_event_thaw(evas_object_evas_get(it->wd->obj));
1643 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1644 return;
1645 }
1646
1647 it->wd->item_cache_count++;
1648 itc = calloc(1, sizeof(Item_Cache));
1649 if (!itc)
1650 {
1651 evas_event_thaw(evas_object_evas_get(it->wd->obj));
1652 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1653 return;
1654 }
1655 it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
1656 EINA_INLIST_GET(itc));
1657 itc->spacer = it->spacer;
1658 it->spacer = NULL;
1659 itc->base_view = VIEW(it);
1660 VIEW(it) = NULL;
1661 edje_object_signal_emit(itc->base_view, "elm,state,unselected", "elm");
1662 evas_object_hide(itc->base_view);
1663 evas_object_move(itc->base_view, -9999, -9999);
1664 itc->item_style = eina_stringshare_add(it->itc->item_style);
1665 if (it->item->type & ELM_GENLIST_ITEM_TREE) itc->tree = 1;
1666 itc->selected = it->selected;
1667 itc->disabled = elm_widget_item_disabled_get(it);
1668 itc->expanded = it->item->expanded;
1669 if (it->long_timer)
1670 {
1671 ecore_timer_del(it->long_timer);
1672 it->long_timer = NULL;
1673 }
1674 if (it->item->swipe_timer)
1675 {
1676 ecore_timer_del(it->item->swipe_timer);
1677 it->item->swipe_timer = NULL;
1678 }
1679 // FIXME: other callbacks?
1680 edje_object_signal_callback_del_full(itc->base_view,
1681 "elm,action,expand,toggle",
1682 "elm", _signal_expand_toggle, it);
1683 edje_object_signal_callback_del_full(itc->base_view, "elm,action,expand",
1684 "elm",
1685 _signal_expand, it);
1686 edje_object_signal_callback_del_full(itc->base_view, "elm,action,contract",
1687 "elm", _signal_contract, it);
1688 _item_mouse_callbacks_del(it, itc->base_view);
1689 _item_cache_clean(it->wd);
1690 evas_event_thaw(evas_object_evas_get(it->wd->obj));
1691 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
1692}
1693
1694static Item_Cache *
1695_item_cache_find(Elm_Gen_Item *it)
1696{
1697 Item_Cache *itc;
1698 Eina_Bool tree = 0;
1699
1700 if (it->item->type & ELM_GENLIST_ITEM_TREE) tree = 1;
1701 EINA_INLIST_FOREACH(it->wd->item_cache, itc)
1702 {
1703 if ((itc->selected) || (itc->disabled) || (itc->expanded))
1704 continue;
1705 if ((itc->tree == tree) &&
1706 (((!it->itc->item_style) && (!itc->item_style)) ||
1707 (it->itc->item_style && itc->item_style &&
1708 (!strcmp(it->itc->item_style, itc->item_style)))))
1709 {
1710 it->wd->item_cache = eina_inlist_remove(it->wd->item_cache,
1711 EINA_INLIST_GET(itc));
1712 it->wd->item_cache_count--;
1713 return itc;
1714 }
1715 }
1716 return NULL;
1717}
1718
1719static void
1720_elm_genlist_item_index_update(Elm_Gen_Item *it)
1721{
1722 if (it->position_update || it->item->block->position_update)
1723 {
1724 evas_object_smart_callback_call(WIDGET(it), SIG_INDEX_UPDATE, it);
1725 it->position_update = EINA_FALSE;
1726 }
1727}
1728
1729static void
1730_elm_genlist_item_odd_even_update(Elm_Gen_Item *it)
1731{
1732 if (!it->item->nostacking)
1733 {
1734 if ((it->item->order_num_in & 0x1) ^ it->item->stacking_even)
1735 {
1736 if (it->deco_all_view) evas_object_lower(it->deco_all_view);
1737 else evas_object_lower(VIEW(it));
1738 }
1739 else
1740 {
1741 if (it->deco_all_view) evas_object_raise(it->deco_all_view);
1742 else evas_object_raise(VIEW(it));
1743 }
1744 }
1745
1746 if (it->item->order_num_in & 0x1)
1747 {
1748 edje_object_signal_emit(VIEW(it), "elm,state,odd", "elm");
1749 if (it->deco_all_view) edje_object_signal_emit(it->deco_all_view, "elm,state,odd", "elm");
1750 }
1751 else
1752 {
1753 edje_object_signal_emit(VIEW(it), "elm,state,even", "elm");
1754 if (it->deco_all_view) edje_object_signal_emit(it->deco_all_view, "elm,state,even", "elm");
1755 }
1756}
1757
1758static void
1759_elm_genlist_item_state_update(Elm_Gen_Item *it, Item_Cache *itc)
1760{
1761 if (itc)
1762 {
1763 if (it->selected != itc->selected)
1764 {
1765 if (it->selected)
1766 {
1767 edje_object_signal_emit(VIEW(it),
1768 "elm,state,selected", "elm");
1769
1770 if (it->deco_all_view)
1771 edje_object_signal_emit(it->deco_all_view,
1772 "elm,state,selected", "elm");
1773 }
1774 }
1775 if (elm_widget_item_disabled_get(it) != itc->disabled)
1776 {
1777 if (elm_widget_item_disabled_get(it))
1778 edje_object_signal_emit(VIEW(it),
1779 "elm,state,disabled", "elm");
1780 if (it->deco_all_view)
1781 edje_object_signal_emit(it->deco_all_view,
1782 "elm,state,disabled", "elm");
1783 }
1784 if (it->item->expanded != itc->expanded)
1785 {
1786 if (it->item->expanded)
1787 edje_object_signal_emit(VIEW(it),
1788 "elm,state,expanded", "elm");
1789 if (it->deco_all_view)
1790 edje_object_signal_emit(it->deco_all_view,
1791 "elm,state,expanded", "elm");
1792 }
1793 }
1794 else
1795 {
1796 if (it->selected)
1797 {
1798 edje_object_signal_emit(VIEW(it),
1799 "elm,state,selected", "elm");
1800 if (it->deco_all_view)
1801 edje_object_signal_emit(it->deco_all_view,
1802 "elm,state,selected", "elm");
1803 }
1804
1805 if (elm_widget_item_disabled_get(it))
1806 {
1807 edje_object_signal_emit(VIEW(it),
1808 "elm,state,disabled", "elm");
1809 if (it->deco_all_view)
1810 edje_object_signal_emit(it->deco_all_view,
1811 "elm,state,disabled", "elm");
1812 }
1813 if (it->item->expanded)
1814 {
1815 edje_object_signal_emit(VIEW(it),
1816 "elm,state,expanded", "elm");
1817 if (it->deco_all_view)
1818 edje_object_signal_emit(it->deco_all_view,
1819 "elm,state,expanded", "elm");
1820 }
1821 }
1822}
1823
1824static Eina_List*
1825_item_mode_content_realize(Elm_Gen_Item *it,
1826 Evas_Object *target,
1827 Eina_List **source,
1828 const char *parts,
1829 Eina_List **contents_list)
1830{
1831 Eina_List *res = *contents_list;
1832
1833 if (it->itc->func.content_get)
1834 {
1835 const Eina_List *l;
1836 const char *key;
1837
1838 EINA_LIST_FOREACH(*source, l, key)
1839 {
1840 if (parts && fnmatch(parts, key, FNM_PERIOD))
1841 continue;
1842
1843 Evas_Object *ic = it->itc->func.content_get
1844 ((void *)it->base.data, WIDGET(it), l->data);
1845
1846 if (ic)
1847 {
1848 res = eina_list_append(res, ic);
1849 edje_object_part_swallow(target, key, ic);
1850 evas_object_show(ic);
1851 elm_widget_sub_object_add(WIDGET(it), ic);
1852 if (it->item->deco_it_view || it->wd->decorate_all_mode)
1853 {
1854 if (elm_widget_item_disabled_get(it))
1855 elm_widget_disabled_set(ic, EINA_TRUE);
1856 }
1857 }
1858 }
1859 }
1860
1861 return res;
1862}
1863
1864static Eina_List*
1865_item_mode_content_unrealize(Elm_Gen_Item *it,
1866 Evas_Object *target,
1867 Eina_List **source,
1868 const char *parts,
1869 Eina_List **contents_list)
1870{
1871 Eina_List *res = *contents_list;
1872
1873 if (it->itc->func.content_get)
1874 {
1875 const Eina_List *l;
1876 const char *key;
1877 Evas_Object *ic = NULL;
1878
1879 EINA_LIST_FOREACH(*source, l, key)
1880 {
1881 if (parts && fnmatch(parts, key, FNM_PERIOD))
1882 continue;
1883
1884 ic = edje_object_part_swallow_get(target, key);
1885 if (ic)
1886 {
1887 res = eina_list_remove(res, ic);
1888 edje_object_part_unswallow(target, ic);
1889 evas_object_del(ic);
1890 }
1891 }
1892 }
1893
1894 return res;
1895}
1896
1897static void
1898_item_cache_free(Item_Cache *itc)
1899{
1900 if (itc->spacer) evas_object_del(itc->spacer);
1901 if (itc->base_view) evas_object_del(itc->base_view);
1902 eina_stringshare_del(itc->item_style);
1903 free(itc);
1904}
1905
1906static void
1907_item_text_realize(Elm_Gen_Item *it,
1908 Evas_Object *target,
1909 Eina_List **source,
1910 const char *parts)
1911{
1912 if (it->itc->func.text_get)
1913 {
1914 const Eina_List *l;
1915 const char *key;
1916
1917 if (!(*source))
1918 *source = elm_widget_stringlist_get(edje_object_data_get(target, "texts"));
1919 EINA_LIST_FOREACH(*source, l, key)
1920 {
1921 if (parts && fnmatch(parts, key, FNM_PERIOD))
1922 continue;
1923
1924 char *s = it->itc->func.text_get
1925 ((void *)it->base.data, WIDGET(it), key);
1926
1927 if (s)
1928 {
1929 edje_object_part_text_escaped_set(target, key, s);
1930 free(s);
1931 }
1932 else
1933 {
1934 edje_object_part_text_set(target, key, "");
1935 }
1936 }
1937 }
1938}
1939
1940static Eina_List *
1941_item_content_unrealize(Elm_Gen_Item *it,
1942 Evas_Object *target,
1943 Eina_List **source,
1944 const char *parts)
1945{
1946 Eina_List *res = it->content_objs;
1947
1948 if (it->itc->func.content_get)
1949 {
1950 const Eina_List *l;
1951 const char *key;
1952 Evas_Object *ic = NULL;
1953
1954 EINA_LIST_FOREACH(*source, l, key)
1955 {
1956 if (parts && fnmatch(parts, key, FNM_PERIOD))
1957 continue;
1958
1959 ic = edje_object_part_swallow_get(target, key);
1960 if (ic)
1961 {
1962 res = eina_list_remove(res, ic);
1963 edje_object_part_unswallow(target, ic);
1964 evas_object_del(ic);
1965 }
1966 }
1967 }
1968
1969 return res;
1970}
1971
1972static Eina_List *
1973_item_content_realize(Elm_Gen_Item *it,
1974 Evas_Object *target,
1975 Eina_List **source,
1976 const char *parts)
1977{
1978 Eina_List *res = it->content_objs;
1979
1980 if (it->itc->func.content_get)
1981 {
1982 const Eina_List *l;
1983 const char *key;
1984 Evas_Object *ic = NULL;
1985
1986 if (!(*source))
1987 *source = elm_widget_stringlist_get(edje_object_data_get(target, "contents"));
1988
1989 EINA_LIST_FOREACH(*source, l, key)
1990 {
1991 if (parts && fnmatch(parts, key, FNM_PERIOD))
1992 continue;
1993
1994 if (it->itc->func.content_get)
1995 ic = it->itc->func.content_get
1996 ((void *)it->base.data, WIDGET(it), key);
1997 if (ic)
1998 {
1999 res = eina_list_append(res, ic);
2000 edje_object_part_swallow(target, key, ic);
2001 evas_object_show(ic);
2002 elm_widget_sub_object_add(WIDGET(it), ic);
2003 if (elm_widget_item_disabled_get(it))
2004 elm_widget_disabled_set(ic, EINA_TRUE);
2005 }
2006 }
2007 }
2008
2009 return res;
2010}
2011
2012static void
2013_item_state_realize(Elm_Gen_Item *it,
2014 Evas_Object *target,
2015 Eina_List **source,
2016 const char *parts)
2017{
2018 if (it->itc->func.state_get)
2019 {
2020 const Eina_List *l;
2021 const char *key;
2022 char buf[4096];
2023
2024 if (!(*source))
2025 *source = elm_widget_stringlist_get(edje_object_data_get(target, "states"));
2026 EINA_LIST_FOREACH(*source, l, key)
2027 {
2028 if (parts && fnmatch(parts, key, FNM_PERIOD))
2029 continue;
2030
2031 Eina_Bool on = it->itc->func.state_get
2032 ((void *)it->base.data, WIDGET(it), key);
2033
2034 if (on)
2035 {
2036 snprintf(buf, sizeof(buf), "elm,state,%s,active", key);
2037 edje_object_signal_emit(target, buf, "elm");
2038 }
2039 else
2040 {
2041 snprintf(buf, sizeof(buf), "elm,state,%s,passive", key);
2042 edje_object_signal_emit(target, buf, "elm");
2043 }
2044 }
2045 }
2046}
2047
2048static void
2049_item_realize(Elm_Gen_Item *it,
2050 int in,
2051 Eina_Bool calc)
2052{
2053 const char *treesize;
2054 char buf[1024];
2055 int tsize = 20;
2056 Item_Cache *itc = NULL;
2057
2058 if (it->generation < it->wd->generation) return;
2059 //evas_event_freeze(evas_object_evas_get(it->wd->obj));
2060 if (it->realized)
2061 {
2062 if (it->item->order_num_in != in)
2063 {
2064 it->item->order_num_in = in;
2065 _elm_genlist_item_odd_even_update(it);
2066 _elm_genlist_item_state_update(it, NULL);
2067 _elm_genlist_item_index_update(it);
2068 }
2069 //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2070 //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2071 return;
2072 }
2073 it->item->order_num_in = in;
2074
2075 if (it->item->nocache_once)
2076 it->item->nocache_once = EINA_FALSE;
2077 else if (!it->item->nocache)
2078 itc = _item_cache_find(it);
2079 if (itc && (!it->wd->tree_effect_enabled))
2080 {
2081 VIEW(it) = itc->base_view;
2082 itc->base_view = NULL;
2083 it->spacer = itc->spacer;
2084 itc->spacer = NULL;
2085 }
2086 else
2087 {
2088 const char *stacking_even;
2089 const char *stacking;
2090
2091 VIEW(it) = edje_object_add(evas_object_evas_get(WIDGET(it)));
2092 edje_object_scale_set(VIEW(it),
2093 elm_widget_scale_get(WIDGET(it)) *
2094 _elm_config->scale);
2095 evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
2096 elm_widget_sub_object_add(WIDGET(it), VIEW(it));
2097
2098 if (it->item->type & ELM_GENLIST_ITEM_TREE)
2099 snprintf(buf, sizeof(buf), "tree%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2100 else
2101 snprintf(buf, sizeof(buf), "item%s/%s", it->wd->mode == ELM_LIST_COMPRESS ? "_compress" : "", it->itc->item_style ?: "default");
2102
2103 _elm_theme_object_set(WIDGET(it), VIEW(it), "genlist", buf,
2104 elm_widget_style_get(WIDGET(it)));
2105
2106 stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
2107 if (!stacking_even) stacking_even = "above";
2108 it->item->stacking_even = !!strcmp("above", stacking_even);
2109
2110 stacking = edje_object_data_get(VIEW(it), "stacking");
2111 if (!stacking) stacking = "yes";
2112 it->item->nostacking = !!strcmp("yes", stacking);
2113
2114 edje_object_mirrored_set(VIEW(it),
2115 elm_widget_mirrored_get(WIDGET(it)));
2116 }
2117
2118 _elm_genlist_item_odd_even_update(it);
2119
2120 treesize = edje_object_data_get(VIEW(it), "treesize");
2121 if (treesize) tsize = atoi(treesize);
2122 if (!it->spacer && treesize)
2123 {
2124 it->spacer =
2125 evas_object_rectangle_add(evas_object_evas_get(WIDGET(it)));
2126 evas_object_color_set(it->spacer, 0, 0, 0, 0);
2127 elm_widget_sub_object_add(WIDGET(it), it->spacer);
2128 }
2129 if (it->spacer)
2130 {
2131 evas_object_size_hint_min_set(it->spacer,
2132 (it->item->expanded_depth * tsize) * _elm_config->scale, 1);
2133 edje_object_part_swallow(VIEW(it), "elm.swallow.pad", it->spacer);
2134 }
2135 if (!calc)
2136 {
2137 edje_object_signal_callback_add(VIEW(it),
2138 "elm,action,expand,toggle",
2139 "elm", _signal_expand_toggle, it);
2140 edje_object_signal_callback_add(VIEW(it), "elm,action,expand",
2141 "elm", _signal_expand, it);
2142 edje_object_signal_callback_add(VIEW(it), "elm,action,contract",
2143 "elm", _signal_contract, it);
2144 _item_mouse_callbacks_add(it, VIEW(it));
2145
2146 if ((it->wd->decorate_all_mode) && (!it->deco_all_view) &&
2147 (it->item->type != ELM_GENLIST_ITEM_GROUP) && (it->itc->decorate_all_item_style))
2148 _decorate_all_item_realize(it, EINA_FALSE);
2149
2150 _elm_genlist_item_state_update(it, itc);
2151 _elm_genlist_item_index_update(it);
2152 }
2153
2154 if ((calc) && (it->wd->homogeneous) &&
2155 ((it->wd->item_width) ||
2156 ((it->wd->item_width) && (it->wd->group_item_width))))
2157 {
2158 /* homogenous genlist shortcut */
2159 if (!it->item->mincalcd)
2160 {
2161 if (it->group)
2162 {
2163 it->item->w = it->item->minw = it->wd->group_item_width;
2164 it->item->h = it->item->minh = it->wd->group_item_height;
2165 }
2166 else
2167 {
2168 it->item->w = it->item->minw = it->wd->item_width;
2169 it->item->h = it->item->minh = it->wd->item_height;
2170 }
2171 it->item->mincalcd = EINA_TRUE;
2172 }
2173 }
2174 else
2175 {
2176 /* FIXME: If you see that assert, please notify us and we
2177 will clean our mess */
2178 assert(eina_list_count(it->content_objs) == 0);
2179
2180 _item_text_realize(it, VIEW(it), &it->texts, NULL);
2181 it->content_objs = _item_content_realize(it, VIEW(it), &it->contents, NULL);
2182 _item_state_realize(it, VIEW(it), &it->states, NULL);
2183 if (it->flipped)
2184 {
2185 edje_object_signal_emit(VIEW(it), "elm,state,flip,enabled", "elm");
2186 if (!(it->item->flip_contents))
2187 it->item->flip_contents =
2188 elm_widget_stringlist_get(edje_object_data_get(VIEW(it), "flips"));
2189 it->item->flip_content_objs =
2190 _item_mode_content_realize(it, VIEW(it),
2191 &it->item->flip_contents, NULL,
2192 &it->item->flip_content_objs);
2193 }
2194
2195 if (!it->item->mincalcd)
2196 {
2197 Evas_Coord mw = -1, mh = -1;
2198
2199 if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2200 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2201 if (it->wd->mode == ELM_LIST_COMPRESS) mw = it->wd->prev_viewport_w;
2202 edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw,
2203 mh);
2204 if (it->select_mode != ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
2205 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
2206 it->item->w = it->item->minw = mw;
2207 it->item->h = it->item->minh = mh;
2208 it->item->mincalcd = EINA_TRUE;
2209
2210 if ((!it->wd->group_item_width) && (it->group))
2211 {
2212 it->wd->group_item_width = mw;
2213 it->wd->group_item_height = mh;
2214 }
2215 else if ((!it->wd->item_width) && (it->item->type == ELM_GENLIST_ITEM_NONE))
2216 {
2217 it->wd->item_width = mw;
2218 it->wd->item_height = mh;
2219 }
2220 }
2221 if (!calc) evas_object_show(VIEW(it));
2222 }
2223
2224 if (it->tooltip.content_cb)
2225 {
2226 elm_widget_item_tooltip_content_cb_set(it,
2227 it->tooltip.content_cb,
2228 it->tooltip.data, NULL);
2229 elm_widget_item_tooltip_style_set(it, it->tooltip.style);
2230 elm_widget_item_tooltip_window_mode_set(it, it->tooltip.free_size);
2231 }
2232
2233 if (it->mouse_cursor)
2234 elm_widget_item_cursor_set(it, it->mouse_cursor);
2235
2236 it->realized = EINA_TRUE;
2237 it->want_unrealize = EINA_FALSE;
2238
2239 if (itc) _item_cache_free(itc);
2240 //evas_event_thaw(evas_object_evas_get(it->wd->obj));
2241 //evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2242 if (!calc)
2243 {
2244 if (it->item->tree_effect_hideme)
2245 {
2246 if (it->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE)
2247 edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
2248 it->item->tree_effect_hideme = EINA_FALSE;
2249 }
2250 evas_object_smart_callback_call(WIDGET(it), SIG_REALIZED, it);
2251 }
2252
2253 if ((!calc) && (it->wd->decorate_all_mode) && (it->item->type != ELM_GENLIST_ITEM_GROUP))
2254 {
2255 if (it->itc->decorate_all_item_style)
2256 {
2257 if (!it->deco_all_view) _decorate_all_item_realize(it, EINA_FALSE);
2258 edje_object_message_signal_process(it->deco_all_view);
2259 }
2260 }
2261 edje_object_message_signal_process(VIEW(it));
2262}
2263
2264static void
2265_item_unrealize_cb(Elm_Gen_Item *it)
2266{
2267 Evas_Object *content;
2268 elm_widget_stringlist_free(it->item->flip_contents);
2269 it->item->flip_contents = NULL;
2270 EINA_LIST_FREE(it->item->flip_content_objs, content)
2271 evas_object_del(content);
2272
2273 if (it->item->nocache_once || it->item->nocache)
2274 {
2275 evas_object_del(VIEW(it));
2276 VIEW(it) = NULL;
2277 if (it->spacer)
2278 {
2279 evas_object_del(it->spacer);
2280 it->spacer = NULL;
2281 }
2282 }
2283 else
2284 {
2285 edje_object_mirrored_set(VIEW(it),
2286 elm_widget_mirrored_get(WIDGET(it)));
2287 edje_object_scale_set(VIEW(it),
2288 elm_widget_scale_get(WIDGET(it))
2289 * _elm_config->scale);
2290 _item_cache_add(it);
2291 }
2292
2293 _decorate_item_unrealize(it);
2294 it->states = NULL;
2295 it->realized = EINA_FALSE;
2296 it->want_unrealize = EINA_FALSE;
2297 if (it->wd->decorate_all_mode) _decorate_all_item_unrealize(it);
2298}
2299
2300static Eina_Bool
2301_item_block_recalc(Item_Block *itb,
2302 int in,
2303 Eina_Bool qadd)
2304{
2305 const Eina_List *l;
2306 Elm_Gen_Item *it;
2307 Evas_Coord minw = 0, minh = 0;
2308 Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
2309 Evas_Coord y = 0;
2310
2311 //evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2312 itb->num = in;
2313 EINA_LIST_FOREACH(itb->items, l, it)
2314 {
2315 if (it->generation < it->wd->generation) continue;
2316 showme |= it->item->showme;
2317 if (!itb->realized)
2318 {
2319 if (qadd)
2320 {
2321 if (!it->item->mincalcd) changed = EINA_TRUE;
2322 if (changed)
2323 {
2324 _item_realize(it, in, EINA_TRUE);
2325 _elm_genlist_item_unrealize(it, EINA_TRUE);
2326 }
2327 }
2328 else
2329 {
2330 _item_realize(it, in, EINA_TRUE);
2331 _elm_genlist_item_unrealize(it, EINA_TRUE);
2332 }
2333 }
2334 else
2335 {
2336 if (!it->item->mincalcd) changed = EINA_TRUE;
2337 _item_realize(it, in, EINA_FALSE);
2338 }
2339 minh += it->item->minh;
2340 if (minw < it->item->minw) minw = it->item->minw;
2341 in++;
2342 it->x = 0;
2343 it->y = y;
2344 y += it->item->h;
2345 }
2346 if (changed) itb->wd->pan_changed = changed;
2347 itb->minw = minw;
2348 itb->minh = minh;
2349 itb->changed = EINA_FALSE;
2350 itb->position_update = EINA_FALSE;
2351 //evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2352 //evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2353 return showme;
2354}
2355
2356static void
2357_item_block_realize(Item_Block *itb)
2358{
2359 if (itb->realized) return;
2360 itb->realized = EINA_TRUE;
2361 itb->want_unrealize = EINA_FALSE;
2362}
2363
2364static void
2365_item_block_unrealize(Item_Block *itb)
2366{
2367 const Eina_List *l;
2368 Elm_Gen_Item *it;
2369 Eina_Bool dragging = EINA_FALSE;
2370
2371 if (!itb->realized) return;
2372 evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2373 EINA_LIST_FOREACH(itb->items, l, it)
2374 {
2375 if (itb->must_recalc || !it->group)
2376 {
2377 if (it->dragging)
2378 {
2379 dragging = EINA_TRUE;
2380 it->want_unrealize = EINA_TRUE;
2381 }
2382 else
2383 _elm_genlist_item_unrealize(it, EINA_FALSE);
2384 }
2385 }
2386 if (!dragging)
2387 {
2388 itb->realized = EINA_FALSE;
2389 itb->want_unrealize = EINA_TRUE;
2390 }
2391 else
2392 itb->want_unrealize = EINA_FALSE;
2393 evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2394 evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2395}
2396
2397static int
2398_get_space_for_reorder_item(Elm_Gen_Item *it)
2399{
2400 Evas_Coord rox, roy, row, roh, oy, oh;
2401 Eina_Bool top = EINA_FALSE;
2402 Elm_Gen_Item *reorder_it = it->wd->reorder_it;
2403 if (!reorder_it) return 0;
2404
2405 evas_object_geometry_get(it->wd->pan_smart, NULL, &oy, NULL, &oh);
2406 evas_object_geometry_get(it->wd->VIEW(reorder_it), &rox, &roy, &row, &roh);
2407
2408 if ((it->wd->reorder_start_y < it->item->block->y) &&
2409 (roy - oy + (roh / 2) >= it->item->block->y - it->wd->pan_y))
2410 {
2411 it->item->block->reorder_offset = it->wd->reorder_it->item->h * -1;
2412 if (it->item->block->count == 1)
2413 it->wd->reorder_rel = it;
2414 }
2415 else if ((it->wd->reorder_start_y >= it->item->block->y) &&
2416 (roy - oy + (roh / 2) <= it->item->block->y - it->wd->pan_y))
2417 {
2418 it->item->block->reorder_offset = it->wd->reorder_it->item->h;
2419 }
2420 else
2421 it->item->block->reorder_offset = 0;
2422
2423 it->item->scrl_y += it->item->block->reorder_offset;
2424
2425 top = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2426 rox, roy + (roh / 2), row, 1));
2427 if (top)
2428 {
2429 it->wd->reorder_rel = it;
2430 it->item->scrl_y += it->wd->reorder_it->item->h;
2431 return it->wd->reorder_it->item->h;
2432 }
2433 else
2434 return 0;
2435}
2436
2437static Eina_Bool
2438_reorder_move_animator_cb(void *data)
2439{
2440 Elm_Gen_Item *it = data;
2441 Eina_Bool down = EINA_FALSE;
2442 double t;
2443 int y, dy = it->item->h / 10 * _elm_config->scale, diff;
2444
2445 t = ((0.0 > (t = ecore_loop_time_get()-it->wd->start_time)) ? 0.0 : t);
2446
2447 if (t <= REORDER_EFFECT_TIME) y = (1 * sin((t / REORDER_EFFECT_TIME) * (M_PI / 2)) * dy);
2448 else y = dy;
2449
2450 diff = abs(it->item->old_scrl_y - it->item->scrl_y);
2451 if (diff > it->item->h) y = diff / 2;
2452
2453 if (it->item->old_scrl_y < it->item->scrl_y)
2454 {
2455 it->item->old_scrl_y += y;
2456 down = EINA_TRUE;
2457 }
2458 else if (it->item->old_scrl_y > it->item->scrl_y)
2459 {
2460 it->item->old_scrl_y -= y;
2461 down = EINA_FALSE;
2462 }
2463
2464 if (it->deco_all_view)
2465 _item_position(it, it->deco_all_view, it->item->scrl_x, it->item->old_scrl_y);
2466 else
2467 _item_position(it, VIEW(it), it->item->scrl_x, it->item->old_scrl_y);
2468 _group_items_recalc(it->wd);
2469
2470 if ((it->wd->reorder_pan_move) ||
2471 (down && it->item->old_scrl_y >= it->item->scrl_y) ||
2472 (!down && it->item->old_scrl_y <= it->item->scrl_y))
2473 {
2474 it->item->old_scrl_y = it->item->scrl_y;
2475 it->item->move_effect_enabled = EINA_FALSE;
2476 it->wd->reorder_move_animator = NULL;
2477 return ECORE_CALLBACK_CANCEL;
2478 }
2479 return ECORE_CALLBACK_RENEW;
2480}
2481
2482static void
2483_item_position(Elm_Gen_Item *it,
2484 Evas_Object *view,
2485 Evas_Coord it_x,
2486 Evas_Coord it_y)
2487{
2488 if (!it) return;
2489 if (!view) return;
2490
2491 evas_event_freeze(evas_object_evas_get(it->wd->obj));
2492 evas_object_resize(view, it->item->w, it->item->h);
2493 evas_object_move(view, it_x, it_y);
2494 evas_object_show(view);
2495 evas_event_thaw(evas_object_evas_get(it->wd->obj));
2496 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
2497}
2498
2499static void
2500_item_block_position(Item_Block *itb,
2501 int in)
2502{
2503 const Eina_List *l;
2504 Elm_Gen_Item *it;
2505 Elm_Gen_Item *git;
2506 Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
2507 Eina_Bool vis = EINA_FALSE;
2508
2509 evas_event_freeze(evas_object_evas_get(itb->wd->obj));
2510 evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
2511 evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
2512 &cvw, &cvh);
2513 EINA_LIST_FOREACH(itb->items, l, it)
2514 {
2515 if (it->generation < it->wd->generation) continue;
2516 else if (it->wd->reorder_it == it) continue;
2517 it->x = 0;
2518 it->y = y;
2519 it->item->w = itb->w;
2520 it->item->scrl_x = itb->x + it->x - it->wd->pan_x + ox;
2521 it->item->scrl_y = itb->y + it->y - it->wd->pan_y + oy;
2522
2523 vis = (ELM_RECTS_INTERSECT(it->item->scrl_x, it->item->scrl_y, it->item->w, it->item->h,
2524 cvx, cvy, cvw, cvh));
2525 if (!it->group)
2526 {
2527 if ((itb->realized) && (!it->realized))
2528 {
2529 if (vis) _item_realize(it, in, EINA_FALSE);
2530 }
2531 if (it->realized)
2532 {
2533 if (vis || it->dragging)
2534 {
2535 if (it->wd->reorder_mode)
2536 y += _get_space_for_reorder_item(it);
2537 git = it->item->group_item;
2538 if (git)
2539 {
2540 if (git->item->scrl_y < oy)
2541 git->item->scrl_y = oy;
2542 if ((git->item->scrl_y + git->item->h) > (it->item->scrl_y + it->item->h))
2543 git->item->scrl_y = (it->item->scrl_y + it->item->h) - git->item->h;
2544 git->item->want_realize = EINA_TRUE;
2545 }
2546 if ((it->wd->reorder_it) && (it->item->old_scrl_y != it->item->scrl_y))
2547 {
2548 if (!it->item->move_effect_enabled)
2549 {
2550 it->item->move_effect_enabled = EINA_TRUE;
2551 it->wd->reorder_move_animator =
2552 ecore_animator_add(
2553 _reorder_move_animator_cb, it);
2554 }
2555 }
2556 if (!it->item->move_effect_enabled)
2557 {
2558 if ((it->wd->decorate_all_mode) && (it->itc->decorate_all_item_style))
2559 _decorate_all_item_position(it, it->item->scrl_x,
2560 it->item->scrl_y);
2561 else
2562 {
2563 if (!it->wd->tree_effect_enabled ||
2564 (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE) ||
2565 ((it->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE) &&
2566 (it->item->old_scrl_y == it->item->scrl_y)))
2567 {
2568 if (it->item->deco_it_view)
2569 _item_position(it, it->item->deco_it_view,
2570 it->item->scrl_x,
2571 it->item->scrl_y);
2572 else
2573 _item_position(it, VIEW(it), it->item->scrl_x,
2574 it->item->scrl_y);
2575 }
2576 }
2577 it->item->old_scrl_y = it->item->scrl_y;
2578 }
2579 }
2580 else
2581 {
2582 if (!it->wd->tree_effect_animator)
2583 _elm_genlist_item_unrealize(it, EINA_FALSE);
2584 }
2585 }
2586 in++;
2587 }
2588 else
2589 {
2590 if (vis) it->item->want_realize = EINA_TRUE;
2591 }
2592 y += it->item->h;
2593 }
2594 evas_event_thaw(evas_object_evas_get(itb->wd->obj));
2595 evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
2596}
2597
2598static void
2599_group_items_recalc(void *data)
2600{
2601 Widget_Data *wd = data;
2602 Eina_List *l;
2603 Elm_Gen_Item *git;
2604
2605 evas_event_freeze(evas_object_evas_get(wd->obj));
2606 EINA_LIST_FOREACH(wd->group_items, l, git)
2607 {
2608 if (git->item->want_realize)
2609 {
2610 if (!git->realized)
2611 _item_realize(git, 0, EINA_FALSE);
2612 evas_object_resize(VIEW(git), wd->minw, git->item->h);
2613 evas_object_move(VIEW(git), git->item->scrl_x, git->item->scrl_y);
2614 evas_object_show(VIEW(git));
2615 evas_object_raise(VIEW(git));
2616 }
2617 else if (!git->item->want_realize && git->realized)
2618 {
2619 if (!git->dragging)
2620 _elm_genlist_item_unrealize(git, EINA_FALSE);
2621 }
2622 }
2623 evas_event_thaw(evas_object_evas_get(wd->obj));
2624 evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2625}
2626
2627static Eina_Bool
2628_must_recalc_idler(void *data)
2629{
2630 Widget_Data *wd = data;
2631 if (wd->calc_job) ecore_job_del(wd->calc_job);
2632 wd->calc_job = ecore_job_add(_calc_job, wd);
2633 wd->must_recalc_idler = NULL;
2634 return ECORE_CALLBACK_CANCEL;
2635}
2636
2637static void
2638_scroll_item(Widget_Data *wd)
2639{
2640 Elm_Gen_Item *it = NULL;
2641 Evas_Coord gith = 0;
2642 Evas_Coord ow, oh, dx = 0, dy = 0, dw = 0, dh = 0;
2643 if (!wd->show_item) return;
2644
2645 evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &oh);
2646 it = wd->show_item;
2647 dx = it->x + it->item->block->x;
2648 dy = it->y + it->item->block->y;
2649 dw = it->item->block->w;
2650 dh = oh;
2651 switch (wd->scrollto_type)
2652 {
2653 case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2654 if (it->item->group_item) gith = it->item->group_item->item->h;
2655 dy -= gith;
2656 break;
2657 case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2658 dy += ((it->item->h / 2) - (oh / 2));
2659 break;
2660 case ELM_GENLIST_ITEM_SCROLLTO_IN:
2661 default:
2662 if ((wd->expanded_item) &&
2663 ((wd->show_item->y + wd->show_item->item->block->y + wd->show_item->item->h)
2664 - (wd->expanded_item->y + wd->expanded_item->item->block->y) > oh))
2665 {
2666 it = wd->expanded_item;
2667 if (it->item->group_item) gith = it->item->group_item->item->h;
2668 dx = it->x + it->item->block->x;
2669 dy = it->y + it->item->block->y - gith;
2670 dw = it->item->block->w;
2671 }
2672 else
2673 {
2674 if ((it->item->group_item) && (wd->pan_y > (it->y + it->item->block->y)))
2675 gith = it->item->group_item->item->h;
2676 dy -= gith;
2677 dh = it->item->h;
2678 }
2679 break;
2680 }
2681 if (wd->bring_in)
2682 elm_smart_scroller_region_bring_in(wd->scr, dx, dy, dw, dh);
2683 else
2684 elm_smart_scroller_child_region_show(wd->scr, dx, dy, dw, dh);
2685
2686 it->item->showme = EINA_FALSE;
2687 wd->show_item = NULL;
2688 wd->auto_scroll_enabled = EINA_FALSE;
2689 wd->check_scroll = EINA_FALSE;
2690}
2691
2692static void
2693_calc_job(void *data)
2694{
2695 Widget_Data *wd = data;
2696 Item_Block *itb, *chb = NULL;
2697 Evas_Coord minw = -1, minh = 0, y = 0, ow, dy = 0, vw;
2698 Evas_Coord pan_w = 0, pan_h = 0;
2699 int in = 0;
2700 Eina_Bool minw_change = EINA_FALSE;
2701 Eina_Bool did_must_recalc = EINA_FALSE;
2702 if (!wd) return;
2703
2704 evas_object_geometry_get(wd->pan_smart, NULL, NULL, &ow, &wd->h);
2705 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, NULL);
2706
2707 if (wd->w != ow)
2708 wd->w = ow;
2709
2710 evas_event_freeze(evas_object_evas_get(wd->obj));
2711 EINA_INLIST_FOREACH(wd->blocks, itb)
2712 {
2713 Eina_Bool showme = EINA_FALSE;
2714
2715 itb->num = in;
2716 showme = itb->showme;
2717 itb->showme = EINA_FALSE;
2718 if (chb)
2719 {
2720 if (itb->realized) _item_block_unrealize(itb);
2721 }
2722 if ((itb->changed) || ((itb->must_recalc) && (!did_must_recalc)))
2723 {
2724 if (itb->must_recalc)
2725 {
2726 Eina_List *l;
2727 Elm_Gen_Item *it;
2728 EINA_LIST_FOREACH(itb->items, l, it)
2729 if (it->item->mincalcd) it->item->mincalcd = EINA_FALSE;
2730 itb->changed = EINA_TRUE;
2731 if (itb->must_recalc) did_must_recalc = EINA_TRUE;
2732 if (itb->realized) _item_block_unrealize(itb);
2733 itb->must_recalc = EINA_FALSE;
2734 }
2735 showme = _item_block_recalc(itb, in, EINA_FALSE);
2736 chb = itb;
2737 }
2738 itb->y = y;
2739 itb->x = 0;
2740 minh += itb->minh;
2741 if (minw == -1) minw = itb->minw;
2742 else if ((!itb->must_recalc) && (minw < itb->minw))
2743 {
2744 minw = itb->minw;
2745 minw_change = EINA_TRUE;
2746 }
2747 if (minw > vw)
2748 {
2749 minw = vw;
2750 minw_change = EINA_TRUE;
2751 }
2752 itb->w = minw;
2753 itb->h = itb->minh;
2754 y += itb->h;
2755 in += itb->count;
2756 if ((showme) && (wd->show_item) && (!wd->show_item->item->queued))
2757 wd->check_scroll = EINA_TRUE;
2758 }
2759 if (minw_change)
2760 {
2761 EINA_INLIST_FOREACH(wd->blocks, itb)
2762 {
2763 itb->minw = minw;
2764 itb->w = itb->minw;
2765 }
2766 }
2767 if ((chb) && (EINA_INLIST_GET(chb)->next))
2768 {
2769 EINA_INLIST_FOREACH(EINA_INLIST_GET(chb)->next, itb)
2770 {
2771 if (itb->realized) _item_block_unrealize(itb);
2772 }
2773 }
2774 wd->realminw = minw;
2775 if (minw < wd->w) minw = wd->w;
2776 if ((minw != wd->minw) || (minh != wd->minh))
2777 {
2778 wd->minw = minw;
2779 wd->minh = minh;
2780 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
2781 _sizing_eval(wd->obj);
2782 if ((wd->anchor_item) && (wd->anchor_item->item->block) && (!wd->auto_scroll_enabled))
2783 {
2784 Elm_Gen_Item *it;
2785 Evas_Coord it_y;
2786
2787 it = wd->anchor_item;
2788 it_y = wd->anchor_y;
2789 elm_smart_scroller_child_pos_set(wd->scr, wd->pan_x,
2790 it->item->block->y + it->y + it_y);
2791 wd->anchor_item = it;
2792 wd->anchor_y = it_y;
2793 }
2794 }
2795 if (did_must_recalc)
2796 {
2797 if (!wd->must_recalc_idler)
2798 wd->must_recalc_idler = ecore_idler_add(_must_recalc_idler, wd);
2799 }
2800 if (wd->check_scroll)
2801 {
2802 _pan_child_size_get(wd->pan_smart, &pan_w, &pan_h);
2803 if (EINA_INLIST_GET(wd->show_item) == wd->items->last)
2804 wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
2805 switch (wd->scrollto_type)
2806 {
2807 case ELM_GENLIST_ITEM_SCROLLTO_TOP:
2808 dy = wd->h;
2809 break;
2810 case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
2811 dy = wd->h / 2;
2812 break;
2813 case ELM_GENLIST_ITEM_SCROLLTO_IN:
2814 default:
2815 dy = 0;
2816 break;
2817 }
2818 if (wd->show_item)
2819 {
2820 if ((pan_w > (wd->show_item->x + wd->show_item->item->block->x)) &&
2821 (pan_h > (wd->show_item->y + wd->show_item->item->block->y + dy)))
2822 {
2823 _scroll_item(wd);
2824 }
2825 }
2826 }
2827 wd->calc_job = NULL;
2828 evas_object_smart_changed(wd->pan_smart);
2829 evas_event_thaw(evas_object_evas_get(wd->obj));
2830 evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2831}
2832
2833static void
2834_update_job(void *data)
2835{
2836 Widget_Data *wd = data;
2837 Eina_List *l2;
2838 Item_Block *itb;
2839 int num, num0;
2840 Eina_Bool position = EINA_FALSE, recalc = EINA_FALSE;
2841 if (!wd) return;
2842 wd->update_job = NULL;
2843 num = 0;
2844
2845 evas_event_freeze(evas_object_evas_get(wd->obj));
2846 EINA_INLIST_FOREACH(wd->blocks, itb)
2847 {
2848 Evas_Coord itminw, itminh;
2849 Elm_Gen_Item *it;
2850
2851 if (!itb->updateme)
2852 {
2853 num += itb->count;
2854 if (position)
2855 _item_block_position(itb, num);
2856 continue;
2857 }
2858 num0 = num;
2859 recalc = EINA_FALSE;
2860 EINA_LIST_FOREACH(itb->items, l2, it)
2861 {
2862 if (it->item->updateme)
2863 {
2864 itminw = it->item->minw;
2865 itminh = it->item->minh;
2866
2867 it->item->updateme = EINA_FALSE;
2868 if (it->realized)
2869 {
2870 _elm_genlist_item_unrealize(it, EINA_FALSE);
2871 _item_realize(it, num, EINA_FALSE);
2872 position = EINA_TRUE;
2873 }
2874 else
2875 {
2876 _item_realize(it, num, EINA_TRUE);
2877 _elm_genlist_item_unrealize(it, EINA_TRUE);
2878 }
2879 if ((it->item->minw != itminw) || (it->item->minh != itminh))
2880 recalc = EINA_TRUE;
2881 }
2882 num++;
2883 }
2884 itb->updateme = EINA_FALSE;
2885 if (recalc)
2886 {
2887 position = EINA_TRUE;
2888 itb->changed = EINA_TRUE;
2889 _item_block_recalc(itb, num0, EINA_FALSE);
2890 _item_block_position(itb, num0);
2891 }
2892 }
2893 if (position)
2894 {
2895 if (wd->calc_job) ecore_job_del(wd->calc_job);
2896 wd->calc_job = ecore_job_add(_calc_job, wd);
2897 }
2898 evas_event_thaw(evas_object_evas_get(wd->obj));
2899 evas_event_thaw_eval(evas_object_evas_get(wd->obj));
2900}
2901
2902static void
2903_pan_set(Evas_Object *obj,
2904 Evas_Coord x,
2905 Evas_Coord y)
2906{
2907 Pan *sd = evas_object_smart_data_get(obj);
2908 Item_Block *itb;
2909
2910 if (!sd) return;
2911 if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2912 sd->wd->pan_x = x;
2913 sd->wd->pan_y = y;
2914
2915 EINA_INLIST_FOREACH(sd->wd->blocks, itb)
2916 {
2917 if ((itb->y + itb->h) > y)
2918 {
2919 Elm_Gen_Item *it;
2920 Eina_List *l2;
2921
2922 EINA_LIST_FOREACH(itb->items, l2, it)
2923 {
2924 if ((itb->y + it->y) >= y)
2925 {
2926 sd->wd->anchor_item = it;
2927 sd->wd->anchor_y = -(itb->y + it->y - y);
2928 goto done;
2929 }
2930 }
2931 }
2932 }
2933done:
2934 if (!sd->wd->reorder_move_animator) evas_object_smart_changed(obj);
2935}
2936
2937static void
2938_pan_get(Evas_Object *obj,
2939 Evas_Coord *x,
2940 Evas_Coord *y)
2941{
2942 Pan *sd = evas_object_smart_data_get(obj);
2943
2944 if (!sd) return;
2945 if (x) *x = sd->wd->pan_x;
2946 if (y) *y = sd->wd->pan_y;
2947}
2948
2949static void
2950_pan_max_get(Evas_Object *obj,
2951 Evas_Coord *x,
2952 Evas_Coord *y)
2953{
2954 Pan *sd = evas_object_smart_data_get(obj);
2955 Evas_Coord ow, oh;
2956
2957 if (!sd) return;
2958 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2959 ow = sd->wd->minw - ow;
2960 if (ow < 0) ow = 0;
2961 oh = sd->wd->minh - oh;
2962 if (oh < 0) oh = 0;
2963 if (x) *x = ow;
2964 if (y) *y = oh;
2965}
2966
2967static void
2968_pan_min_get(Evas_Object *obj __UNUSED__,
2969 Evas_Coord *x,
2970 Evas_Coord *y)
2971{
2972 if (x) *x = 0;
2973 if (y) *y = 0;
2974}
2975
2976static void
2977_pan_child_size_get(Evas_Object *obj,
2978 Evas_Coord *w,
2979 Evas_Coord *h)
2980{
2981 Pan *sd = evas_object_smart_data_get(obj);
2982
2983 if (!sd) return;
2984 if (w) *w = sd->wd->minw;
2985 if (h) *h = sd->wd->minh;
2986}
2987
2988static void
2989_pan_add(Evas_Object *obj)
2990{
2991 Pan *sd;
2992 Evas_Object_Smart_Clipped_Data *cd;
2993
2994 _pan_sc.add(obj);
2995 cd = evas_object_smart_data_get(obj);
2996 sd = ELM_NEW(Pan);
2997 if (!sd) return;
2998 sd->__clipped_data = *cd;
2999 free(cd);
3000 evas_object_smart_data_set(obj, sd);
3001}
3002
3003static void
3004_pan_del(Evas_Object *obj)
3005{
3006 Pan *sd = evas_object_smart_data_get(obj);
3007
3008 if (!sd) return;
3009 if (sd->resize_job)
3010 {
3011 ecore_job_del(sd->resize_job);
3012 sd->resize_job = NULL;
3013 }
3014 _pan_sc.del(obj);
3015}
3016
3017static void
3018_pan_resize_job(void *data)
3019{
3020 Pan *sd = data;
3021 if (!sd) return;
3022 _sizing_eval(sd->wd->obj);
3023 sd->resize_job = NULL;
3024}
3025
3026static void
3027_pan_resize(Evas_Object *obj,
3028 Evas_Coord w,
3029 Evas_Coord h)
3030{
3031 Pan *sd = evas_object_smart_data_get(obj);
3032 Evas_Coord ow, oh;
3033
3034 if (!sd) return;
3035 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
3036 if ((ow == w) && (oh == h)) return;
3037 if ((sd->wd->mode == ELM_LIST_COMPRESS) && (ow != w))
3038 {
3039 /* fix me later */
3040 if (sd->resize_job) ecore_job_del(sd->resize_job);
3041 sd->resize_job = ecore_job_add(_pan_resize_job, sd);
3042 }
3043 sd->wd->pan_changed = EINA_TRUE;
3044 evas_object_smart_changed(obj);
3045 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3046 sd->wd->calc_job = NULL;
3047}
3048
3049static void
3050_pan_calculate(Evas_Object *obj)
3051{
3052 Pan *sd = evas_object_smart_data_get(obj);
3053 Item_Block *itb;
3054 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
3055 int in = 0;
3056 Elm_Gen_Item *git;
3057 Eina_List *l;
3058
3059 if (!sd) return;
3060 evas_event_freeze(evas_object_evas_get(obj));
3061
3062 if (sd->wd->pan_changed)
3063 {
3064 _calc_job(sd->wd);
3065 sd->wd->pan_changed = EINA_FALSE;
3066 }
3067
3068 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
3069 evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
3070 EINA_LIST_FOREACH(sd->wd->group_items, l, git)
3071 {
3072 git->item->want_realize = EINA_FALSE;
3073 }
3074
3075 if (sd->wd->tree_effect_enabled && (sd->wd->move_effect_mode != ELM_GENLIST_TREE_EFFECT_NONE))
3076 {
3077 if (!sd->wd->tree_effect_animator)
3078 {
3079 _item_tree_effect_before(sd->wd->expanded_item);
3080 evas_object_raise(sd->wd->alpha_bg);
3081 evas_object_show(sd->wd->alpha_bg);
3082 sd->wd->start_time = ecore_time_get();
3083 sd->wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, sd->wd);
3084 }
3085 }
3086
3087 EINA_INLIST_FOREACH(sd->wd->blocks, itb)
3088 {
3089 itb->w = sd->wd->minw;
3090 if (ELM_RECTS_INTERSECT(itb->x - sd->wd->pan_x + ox,
3091 itb->y - sd->wd->pan_y + oy,
3092 itb->w, itb->h,
3093 cvx, cvy, cvw, cvh))
3094 {
3095 if ((!itb->realized) || (itb->changed))
3096 _item_block_realize(itb);
3097 _item_block_position(itb, in);
3098 }
3099 else
3100 {
3101 if (itb->realized) _item_block_unrealize(itb);
3102 }
3103 in += itb->count;
3104 }
3105 if ((!sd->wd->reorder_it) || (sd->wd->reorder_pan_move))
3106 _group_items_recalc(sd->wd);
3107 if ((sd->wd->reorder_mode) && (sd->wd->reorder_it))
3108 {
3109 if (sd->wd->pan_y != sd->wd->reorder_old_pan_y)
3110 sd->wd->reorder_pan_move = EINA_TRUE;
3111 else sd->wd->reorder_pan_move = EINA_FALSE;
3112 evas_object_raise(sd->wd->VIEW(reorder_it));
3113 sd->wd->reorder_old_pan_y = sd->wd->pan_y;
3114 sd->wd->start_time = ecore_loop_time_get();
3115 }
3116
3117 if (!sd->wd->tree_effect_enabled || (sd->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_NONE))
3118 _item_auto_scroll(sd->wd);
3119
3120 evas_event_thaw(evas_object_evas_get(obj));
3121 evas_event_thaw_eval(evas_object_evas_get(obj));
3122}
3123
3124static void
3125_pan_move(Evas_Object *obj,
3126 Evas_Coord x __UNUSED__,
3127 Evas_Coord y __UNUSED__)
3128{
3129 Pan *sd = evas_object_smart_data_get(obj);
3130
3131 if (!sd) return;
3132
3133 sd->wd->pan_changed = EINA_TRUE;
3134 evas_object_smart_changed(obj);
3135 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
3136 sd->wd->calc_job = NULL;
3137}
3138
3139static void
3140_hold_on(void *data __UNUSED__,
3141 Evas_Object *obj,
3142 void *event_info __UNUSED__)
3143{
3144 Widget_Data *wd = elm_widget_data_get(obj);
3145 if (!wd) return;
3146 elm_smart_scroller_hold_set(wd->scr, 1);
3147}
3148
3149static void
3150_hold_off(void *data __UNUSED__,
3151 Evas_Object *obj,
3152 void *event_info __UNUSED__)
3153{
3154 Widget_Data *wd = elm_widget_data_get(obj);
3155 if (!wd) return;
3156 elm_smart_scroller_hold_set(wd->scr, 0);
3157}
3158
3159static void
3160_freeze_on(void *data __UNUSED__,
3161 Evas_Object *obj,
3162 void *event_info __UNUSED__)
3163{
3164 Widget_Data *wd = elm_widget_data_get(obj);
3165 if (!wd) return;
3166 elm_smart_scroller_freeze_set(wd->scr, 1);
3167}
3168
3169static void
3170_freeze_off(void *data __UNUSED__,
3171 Evas_Object *obj,
3172 void *event_info __UNUSED__)
3173{
3174 Widget_Data *wd = elm_widget_data_get(obj);
3175 if (!wd) return;
3176 elm_smart_scroller_freeze_set(wd->scr, 0);
3177}
3178
3179static void
3180_scr_anim_start(void *data,
3181 Evas_Object *obj __UNUSED__,
3182 void *event_info __UNUSED__)
3183{
3184 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
3185}
3186
3187static void
3188_scr_anim_stop(void *data,
3189 Evas_Object *obj __UNUSED__,
3190 void *event_info __UNUSED__)
3191{
3192 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
3193}
3194
3195static void
3196_scr_drag_start(void *data,
3197 Evas_Object *obj __UNUSED__,
3198 void *event_info __UNUSED__)
3199{
3200 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
3201}
3202
3203static void
3204_scr_drag_stop(void *data,
3205 Evas_Object *obj __UNUSED__,
3206 void *event_info __UNUSED__)
3207{
3208 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
3209}
3210
3211static void
3212_edge_left(void *data,
3213 Evas_Object *scr __UNUSED__,
3214 void *event_info __UNUSED__)
3215{
3216 Evas_Object *obj = data;
3217 evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
3218}
3219
3220static void
3221_edge_right(void *data,
3222 Evas_Object *scr __UNUSED__,
3223 void *event_info __UNUSED__)
3224{
3225 Evas_Object *obj = data;
3226 evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
3227}
3228
3229static void
3230_edge_top(void *data,
3231 Evas_Object *scr __UNUSED__,
3232 void *event_info __UNUSED__)
3233{
3234 Evas_Object *obj = data;
3235 evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
3236}
3237
3238static void
3239_edge_bottom(void *data,
3240 Evas_Object *scr __UNUSED__,
3241 void *event_info __UNUSED__)
3242{
3243 Evas_Object *obj = data;
3244 evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
3245}
3246
3247static void
3248_decorate_item_realize(Elm_Gen_Item *it)
3249{
3250 char buf[1024];
3251
3252 if ((it->item->deco_it_view) || (it->generation < it->wd->generation)) return;
3253
3254 evas_event_freeze(evas_object_evas_get(it->wd->obj));
3255 it->item->deco_it_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3256 edje_object_scale_set(it->item->deco_it_view,
3257 elm_widget_scale_get(WIDGET(it)) *
3258 _elm_config->scale);
3259 evas_object_smart_member_add(it->item->deco_it_view, it->wd->pan_smart);
3260 elm_widget_sub_object_add(WIDGET(it), it->item->deco_it_view);
3261
3262 strncpy(buf, "item", sizeof(buf));
3263 if (it->wd->mode == ELM_LIST_COMPRESS)
3264 strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3265
3266 if (it->item->order_num_in & 0x1) strncat(buf, "_odd", sizeof(buf) - strlen(buf));
3267 strncat(buf, "/", sizeof(buf) - strlen(buf));
3268 strncat(buf, it->itc->decorate_item_style, sizeof(buf) - strlen(buf));
3269
3270 _elm_theme_object_set(WIDGET(it), it->item->deco_it_view, "genlist", buf,
3271 elm_widget_style_get(WIDGET(it)));
3272 edje_object_mirrored_set(it->item->deco_it_view,
3273 elm_widget_mirrored_get(WIDGET(it)));
3274
3275 /* signal callback add */
3276 evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_DOWN,
3277 _mouse_down, it);
3278 evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_UP,
3279 _mouse_up, it);
3280 evas_object_event_callback_add(it->item->deco_it_view, EVAS_CALLBACK_MOUSE_MOVE,
3281 _mouse_move, it);
3282
3283 /* text_get, content_get, state_get */
3284 /* FIXME: If you see that assert, please notify us and we
3285 will clean our mess */
3286 assert(eina_list_count(it->item->deco_it_content_objs) == 0);
3287
3288 _item_text_realize(it, it->item->deco_it_view, &it->item->deco_it_texts, NULL);
3289 if (!it->item->deco_it_contents)
3290 it->item->deco_it_contents =
3291 elm_widget_stringlist_get(edje_object_data_get(it->item->deco_it_view, "contents"));
3292 it->item->deco_it_content_objs =
3293 _item_mode_content_realize(it, it->item->deco_it_view,
3294 &it->item->deco_it_contents, NULL,
3295 &it->item->deco_it_content_objs);
3296 _item_state_realize(it, it->item->deco_it_view, &it->item->deco_it_states, NULL);
3297 edje_object_part_swallow(it->item->deco_it_view,
3298 edje_object_data_get(it->item->deco_it_view, "mode_part"),
3299 VIEW(it));
3300
3301 it->want_unrealize = EINA_FALSE;
3302 evas_event_thaw(evas_object_evas_get(it->wd->obj));
3303 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3304}
3305
3306static void
3307_decorate_item_unrealize(Elm_Gen_Item *it)
3308{
3309 Widget_Data *wd = it->wd;
3310 Evas_Object *content;
3311 if (!it->item->deco_it_view) return;
3312
3313 evas_event_freeze(evas_object_evas_get(it->wd->obj));
3314 elm_widget_stringlist_free(it->item->deco_it_texts);
3315 it->item->deco_it_texts = NULL;
3316 elm_widget_stringlist_free(it->item->deco_it_contents);
3317 it->item->deco_it_contents = NULL;
3318 elm_widget_stringlist_free(it->item->deco_it_states);
3319
3320 EINA_LIST_FREE(it->item->deco_it_content_objs, content)
3321 evas_object_del(content);
3322
3323 edje_object_part_unswallow(it->item->deco_it_view, VIEW(it));
3324 evas_object_smart_member_add(VIEW(it), wd->pan_smart);
3325 evas_object_del(it->item->deco_it_view);
3326 it->item->deco_it_view = NULL;
3327
3328 if (wd->mode_item == it)
3329 wd->mode_item = NULL;
3330 evas_event_thaw(evas_object_evas_get(it->wd->obj));
3331 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3332}
3333
3334static void
3335_decorate_item_set(Elm_Gen_Item *it)
3336{
3337 if (!it) return;
3338 Widget_Data *wd = it->wd;
3339 if (!wd) return;
3340 char buf[1024];
3341
3342 wd->mode_item = it;
3343 it->item->nocache_once = EINA_TRUE;
3344
3345 if (wd->scr_hold_timer)
3346 {
3347 ecore_timer_del(wd->scr_hold_timer);
3348 wd->scr_hold_timer = NULL;
3349 }
3350 elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
3351 wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
3352
3353 evas_event_freeze(evas_object_evas_get(it->wd->obj));
3354 _decorate_item_realize(it);
3355 if (it->item->group_item)
3356 evas_object_raise(it->item->VIEW(group_item));
3357 _item_position(it, it->item->deco_it_view, it->item->scrl_x, it->item->scrl_y);
3358 evas_event_thaw(evas_object_evas_get(it->wd->obj));
3359 evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
3360
3361 snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->decorate_it_type);
3362 edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3363}
3364
3365static void
3366_decorate_item_unset(Widget_Data *wd)
3367{
3368 if (!wd) return;
3369 if (!wd->mode_item) return;
3370 char buf[1024], buf2[1024];
3371 Elm_Gen_Item *it;
3372
3373 it = wd->mode_item;
3374 it->item->nocache_once = EINA_TRUE;
3375
3376 snprintf(buf, sizeof(buf), "elm,state,%s,passive", wd->decorate_it_type);
3377 snprintf(buf2, sizeof(buf2), "elm,state,%s,passive,finished", wd->decorate_it_type);
3378
3379 edje_object_signal_emit(it->item->deco_it_view, buf, "elm");
3380 edje_object_signal_callback_add(it->item->deco_it_view, buf2, "elm", _decorate_item_finished_signal_cb, it);
3381
3382 wd->mode_item = NULL;
3383}
3384
3385static void
3386_decorate_all_item_position(Elm_Gen_Item *it, int itx, int ity)
3387{
3388 if ((!it) || (!it->wd->decorate_all_mode)) return;
3389 evas_object_resize(it->deco_all_view, it->item->w, it->item->h);
3390 evas_object_move(it->deco_all_view, itx, ity);
3391}
3392
3393static void
3394_decorate_all_item_realize(Elm_Gen_Item *it, Eina_Bool effect_on)
3395{
3396 char buf[1024];
3397 const char *stacking_even;
3398 const char *stacking;
3399
3400 if ((!it) || (it->item->decorate_all_item_realized) ||
3401 (it->generation < it->wd->generation))
3402 return;
3403
3404 it->deco_all_view = edje_object_add(evas_object_evas_get(WIDGET(it)));
3405 edje_object_scale_set(it->deco_all_view, elm_widget_scale_get(WIDGET(it)) *
3406 _elm_config->scale);
3407 evas_object_smart_member_add(it->deco_all_view, it->wd->pan_smart);
3408 elm_widget_sub_object_add(WIDGET(it), it->deco_all_view);
3409
3410 if (it->item->type & ELM_GENLIST_ITEM_TREE)
3411 strncpy(buf, "tree", sizeof(buf));
3412 else strncpy(buf, "item", sizeof(buf));
3413 if (it->wd->mode == ELM_LIST_COMPRESS)
3414 strncat(buf, "_compress", sizeof(buf) - strlen(buf));
3415
3416 strncat(buf, "/", sizeof(buf) - strlen(buf));
3417 strncat(buf, it->itc->decorate_all_item_style, sizeof(buf) - strlen(buf));
3418
3419 _elm_theme_object_set(WIDGET(it), it->deco_all_view, "genlist", buf,
3420 elm_widget_style_get(WIDGET(it)));
3421
3422 stacking_even = edje_object_data_get(VIEW(it), "stacking_even");
3423 if (!stacking_even) stacking_even = "above";
3424 it->item->stacking_even = !!strcmp("above", stacking_even);
3425
3426 stacking = edje_object_data_get(VIEW(it), "stacking");
3427 if (!stacking) stacking = "yes";
3428 it->item->nostacking = !!strcmp("yes", stacking);
3429
3430 edje_object_mirrored_set(it->deco_all_view,
3431 elm_widget_mirrored_get(WIDGET(it)));
3432
3433 _elm_genlist_item_odd_even_update(it);
3434 _elm_genlist_item_state_update(it, NULL);
3435
3436 if (effect_on) edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled,effect", "elm");
3437 else edje_object_signal_emit(it->deco_all_view, "elm,state,decorate,enabled", "elm");
3438
3439 _item_mouse_callbacks_del(it, VIEW(it));
3440 _item_mouse_callbacks_add(it, it->deco_all_view);
3441
3442 _item_text_realize(it, it->deco_all_view, &it->item->deco_all_texts, NULL);
3443 if (it->flipped) edje_object_signal_emit(it->deco_all_view, "elm,state,flip,enabled", "elm");
3444 if (!it->item->deco_all_contents)
3445 it->item->deco_all_contents =
3446 elm_widget_stringlist_get(edje_object_data_get(it->deco_all_view, "contents"));
3447 it->item->deco_all_content_objs =
3448 _item_mode_content_realize(it, it->deco_all_view,
3449 &it->item->deco_all_contents, NULL,
3450 &it->item->deco_all_content_objs);
3451 _item_state_realize(it, it->deco_all_view, &it->item->deco_all_states, NULL);
3452 edje_object_part_swallow(it->deco_all_view, "elm.swallow.decorate.content", VIEW(it));
3453
3454 _decorate_all_item_position(it, it->item->scrl_x, it->item->scrl_y);
3455 evas_object_show(it->deco_all_view);
3456
3457 if (it->selected) edje_object_signal_emit(it->deco_all_view, "elm,state,selected", "elm");
3458
3459 it->item->decorate_all_item_realized = EINA_TRUE;
3460 it->want_unrealize = EINA_FALSE;
3461}
3462
3463static void
3464_decorate_all_item_unrealize(Elm_Gen_Item *it)
3465{
3466 Evas_Object *icon;
3467 if ((!it) || (!it->item->decorate_all_item_realized)) return;
3468
3469 edje_object_part_unswallow(it->deco_all_view, VIEW(it));
3470 evas_object_smart_member_add(VIEW(it), it->wd->pan_smart);
3471 elm_widget_sub_object_add(WIDGET(it), VIEW(it));
3472 _elm_genlist_item_odd_even_update(it);
3473 _elm_genlist_item_state_update(it, NULL);
3474
3475 evas_object_del(it->deco_all_view);
3476 it->deco_all_view = NULL;
3477 elm_widget_stringlist_free(it->item->deco_all_texts);
3478 it->item->deco_all_texts = NULL;
3479 elm_widget_stringlist_free(it->item->deco_all_contents);
3480 it->item->deco_all_contents = NULL;
3481 elm_widget_stringlist_free(it->item->deco_all_states);
3482 it->item->deco_all_states = NULL;
3483 EINA_LIST_FREE(it->item->deco_all_content_objs, icon)
3484 evas_object_del(icon);
3485 edje_object_message_signal_process(it->deco_all_view);
3486 _item_mouse_callbacks_del(it, it->deco_all_view);
3487 _item_mouse_callbacks_add(it, VIEW(it));
3488
3489 it->item->decorate_all_item_realized = EINA_FALSE;
3490}
3491
3492static void
3493_item_auto_scroll(Widget_Data *wd)
3494{
3495 if (!wd) return;
3496 Elm_Gen_Item *tmp_item = NULL;
3497
3498 if ((wd->expanded_item) && (wd->auto_scroll_enabled))
3499 {
3500 tmp_item = eina_list_data_get(eina_list_last(wd->expanded_item->item->items));
3501 if (!tmp_item) return;
3502 wd->show_item = tmp_item;
3503 wd->bring_in = EINA_TRUE;
3504 wd->scrollto_type = ELM_GENLIST_ITEM_SCROLLTO_IN;
3505 if ((wd->show_item->item->queued) || (!wd->show_item->item->mincalcd))
3506 {
3507 wd->show_item->item->showme = EINA_TRUE;
3508 wd->auto_scroll_enabled = EINA_FALSE;
3509 }
3510 else
3511 _scroll_item(wd);
3512 }
3513}
3514
3515EAPI Evas_Object *
3516elm_genlist_add(Evas_Object *parent)
3517{
3518 Evas_Object *obj;
3519 Evas *e;
3520 Widget_Data *wd;
3521 Evas_Coord minw, minh;
3522 static Evas_Smart *smart = NULL;
3523
3524 if (!smart)
3525 {
3526 static Evas_Smart_Class sc;
3527
3528 evas_object_smart_clipped_smart_set(&_pan_sc);
3529 sc = _pan_sc;
3530 sc.name = "elm_genlist_pan";
3531 sc.version = EVAS_SMART_CLASS_VERSION;
3532 sc.add = _pan_add;
3533 sc.del = _pan_del;
3534 sc.resize = _pan_resize;
3535 sc.move = _pan_move;
3536 sc.calculate = _pan_calculate;
3537 if (!(smart = evas_smart_class_new(&sc))) return NULL;
3538 }
3539
3540 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3541
3542 ELM_SET_WIDTYPE(widtype, "genlist");
3543 ELM_GEN_SETUP(wd);
3544 elm_widget_type_set(obj, "genlist");
3545 elm_widget_sub_object_add(parent, obj);
3546 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3547 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
3548 elm_widget_data_set(obj, wd);
3549 elm_widget_del_hook_set(obj, _del_hook);
3550 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3551 elm_widget_theme_hook_set(obj, _theme_hook);
3552 elm_widget_can_focus_set(obj, EINA_TRUE);
3553 elm_widget_event_hook_set(obj, _event_hook);
3554 elm_widget_on_show_region_hook_set(obj, _show_region_hook, obj);
3555 elm_widget_translate_hook_set(obj, _translate_hook);
3556
3557 wd->generation = 1;
3558 wd->scr = elm_smart_scroller_add(e);
3559 elm_smart_scroller_widget_set(wd->scr, obj);
3560 elm_smart_scroller_object_theme_set(obj, wd->scr, "genlist", "base",
3561 elm_widget_style_get(obj));
3562 elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
3563 _elm_config->thumbscroll_bounce_enable);
3564 elm_widget_resize_object_set(obj, wd->scr);
3565
3566 evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
3567 evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
3568 evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
3569 evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
3570 evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
3571 evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
3572 evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
3573 evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
3574
3575 wd->obj = obj;
3576 wd->mode = ELM_LIST_SCROLL;
3577 wd->max_items_per_block = MAX_ITEMS_PER_BLOCK;
3578 wd->item_cache_max = wd->max_items_per_block * 2;
3579 wd->longpress_timeout = _elm_config->longpress_timeout;
3580 wd->highlight = EINA_TRUE;
3581
3582 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
3583 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
3584 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
3585 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
3586
3587 wd->pan_smart = evas_object_smart_add(e, smart);
3588 wd->pan = evas_object_smart_data_get(wd->pan_smart);
3589 wd->pan->wd = wd;
3590
3591 elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3592 _pan_set, _pan_get, _pan_max_get,
3593 _pan_min_get, _pan_child_size_get);
3594
3595 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3596 &minw, &minh);
3597 evas_object_size_hint_min_set(obj, minw, minh);
3598
3599 evas_object_smart_callbacks_descriptions_set(obj, _signals);
3600
3601 _mirrored_set(obj, elm_widget_mirrored_get(obj));
3602 _sizing_eval(obj);
3603 return obj;
3604}
3605
3606void
3607_item_select(Elm_Gen_Item *it)
3608{
3609 Evas_Object *obj = WIDGET(it);
3610
3611 if ((it->generation < it->wd->generation) || (it->decorate_it_set) ||
3612 (it->select_mode == ELM_OBJECT_SELECT_MODE_NONE) ||
3613 (it->wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE))
3614 return;
3615 if (!it->selected)
3616 {
3617 it->selected = EINA_TRUE;
3618 it->wd->selected = eina_list_append(it->wd->selected, it);
3619 }
3620 else if (it->wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) return;
3621
3622 evas_object_ref(obj);
3623 it->walking++;
3624 it->wd->walking++;
3625 if (it->func.func) it->func.func((void *)it->func.data, WIDGET(it), it);
3626 if (it->generation == it->wd->generation)
3627 evas_object_smart_callback_call(WIDGET(it), SIG_SELECTED, it);
3628 it->walking--;
3629 it->wd->walking--;
3630 if ((it->wd->clear_me) && (!it->wd->walking))
3631 _elm_genlist_clear(WIDGET(it), EINA_TRUE);
3632 else
3633 {
3634 if ((!it->walking) && (it->generation < it->wd->generation))
3635 {
3636 if (!it->relcount)
3637 {
3638 it->del_cb(it);
3639 elm_widget_item_free(it);
3640 }
3641 }
3642 else
3643 it->wd->last_selected_item = (Elm_Object_Item *)it;
3644 }
3645 evas_object_unref(obj);
3646}
3647
3648static Evas_Object *
3649_item_content_get_hook(Elm_Gen_Item *it, const char *part)
3650{
3651 return edje_object_part_swallow_get(VIEW(it), part);
3652}
3653
3654static const char *
3655_item_text_get_hook(Elm_Gen_Item *it, const char *part)
3656{
3657 if (!it->itc->func.text_get) return NULL;
3658 return edje_object_part_text_get(VIEW(it), part);
3659}
3660
3661static void
3662_item_disable_hook(Elm_Object_Item *it)
3663{
3664 Eina_List *l;
3665 Evas_Object *obj;
3666 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
3667
3668 if (_it->generation < _it->wd->generation) return;
3669
3670 if (_it->selected)
3671 elm_genlist_item_selected_set(it, EINA_FALSE);
3672
3673 if (_it->realized)
3674 {
3675 if (elm_widget_item_disabled_get(it))
3676 {
3677 edje_object_signal_emit(VIEW(_it), "elm,state,disabled", "elm");
3678 if (_it->deco_all_view)
3679 edje_object_signal_emit(_it->deco_all_view, "elm,state,disabled", "elm");
3680 }
3681 else
3682 {
3683 edje_object_signal_emit(VIEW(_it), "elm,state,enabled", "elm");
3684 if (_it->deco_all_view)
3685 edje_object_signal_emit(_it->deco_all_view, "elm,state,enabled", "elm");
3686 }
3687 EINA_LIST_FOREACH(_it->content_objs, l, obj)
3688 elm_widget_disabled_set(obj, elm_widget_item_disabled_get(_it));
3689 }
3690}
3691
3692static Eina_Bool
3693_item_del_pre_hook(Elm_Object_Item *it)
3694{
3695 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
3696
3697 if ((_it->relcount > 0) || (_it->walking > 0))
3698 {
3699 elm_genlist_item_subitems_clear(it);
3700 if (_it->wd->show_item == _it) _it->wd->show_item = NULL;
3701 _elm_genlist_item_del_notserious(_it);
3702 if (_it->item->block)
3703 {
3704 if (_it->realized) _elm_genlist_item_unrealize(_it, EINA_FALSE);
3705 _it->item->block->changed = EINA_TRUE;
3706 if (_it->wd->calc_job) ecore_job_del(_it->wd->calc_job);
3707 _it->wd->calc_job = ecore_job_add(_calc_job, _it->wd);
3708 }
3709 if (_it->parent)
3710 {
3711 _it->parent->item->items =
3712 eina_list_remove(_it->parent->item->items, it);
3713 _it->parent = NULL;
3714 }
3715 return EINA_FALSE;
3716 }
3717 _item_del(_it);
3718 return EINA_TRUE;
3719}
3720
3721static void
3722_item_signal_emit_hook(Elm_Object_Item *it,
3723 const char *emission,
3724 const char *source)
3725{
3726 edje_object_signal_emit(VIEW(it), emission, source);
3727}
3728
3729Elm_Gen_Item *
3730_elm_genlist_item_new(Widget_Data *wd,
3731 const Elm_Gen_Item_Class *itc,
3732 const void *data,
3733 Elm_Gen_Item *parent,
3734 Evas_Smart_Cb func,
3735 const void *func_data)
3736{
3737 Elm_Gen_Item *it;
3738
3739 it = elm_widget_item_new(wd->obj, Elm_Gen_Item);
3740 if (!it) return NULL;
3741 it->wd = wd;
3742 it->generation = wd->generation;
3743 it->itc = itc;
3744 elm_genlist_item_class_ref((Elm_Genlist_Item_Class *)itc);
3745 it->base.data = data;
3746 it->parent = parent;
3747 it->func.func = func;
3748 it->func.data = func_data;
3749 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
3750 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
3751 elm_widget_item_disable_hook_set(it, _item_disable_hook);
3752 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
3753 elm_widget_item_signal_emit_hook_set(it, _item_signal_emit_hook);
3754
3755 /* TEMPORARY */
3756 it->sel_cb = (Ecore_Cb)_item_select;
3757
3758 return it;
3759}
3760
3761static Elm_Gen_Item *
3762_item_new(Widget_Data *wd,
3763 const Elm_Genlist_Item_Class *itc,
3764 const void *data,
3765 Elm_Gen_Item *parent,
3766 Elm_Genlist_Item_Type type,
3767 Evas_Smart_Cb func,
3768 const void *func_data)
3769{
3770 Elm_Gen_Item *it, *it2;
3771 int depth = 0;
3772
3773 it = _elm_genlist_item_new(wd, itc, data, parent, func, func_data);
3774 if (!it) return NULL;
3775 it->item = ELM_NEW(Elm_Gen_Item_Type);
3776 it->item->type = type;
3777 if (type & ELM_GENLIST_ITEM_GROUP) it->group++;
3778 it->item->expanded_depth = 0;
3779 ELM_GEN_ITEM_SETUP(it);
3780 if (it->parent)
3781 {
3782 if (it->parent->group)
3783 it->item->group_item = parent;
3784 else if (it->parent->item->group_item)
3785 it->item->group_item = it->parent->item->group_item;
3786 }
3787 for (it2 = it, depth = 0; it2->parent; it2 = it2->parent)
3788 {
3789 if (!it2->parent->group) depth += 1;
3790 }
3791 it->item->expanded_depth = depth;
3792 wd->item_count++;
3793 return it;
3794}
3795
3796static Item_Block *
3797_item_block_new(Widget_Data *wd, Eina_Bool prepend)
3798{
3799 Item_Block *itb;
3800
3801 itb = calloc(1, sizeof(Item_Block));
3802 if (!itb) return NULL;
3803 itb->wd = wd;
3804 if (prepend)
3805 {
3806 wd->blocks = eina_inlist_prepend(wd->blocks, EINA_INLIST_GET(itb));
3807 _item_block_position_update(wd->blocks, 0);
3808 }
3809 else
3810 {
3811 wd->blocks = eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3812 itb->position_update = EINA_TRUE;
3813 if (wd->blocks != EINA_INLIST_GET(itb))
3814 {
3815 itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3816 }
3817 else
3818 {
3819 itb->position = 0;
3820 }
3821 }
3822 return itb;
3823}
3824
3825static Eina_Bool
3826_item_block_add(Widget_Data *wd,
3827 Elm_Gen_Item *it)
3828{
3829 Item_Block *itb = NULL;
3830
3831 if (!it->item->rel)
3832 {
3833newblock:
3834 if (it->item->rel)
3835 {
3836 itb = calloc(1, sizeof(Item_Block));
3837 if (!itb) return EINA_FALSE;
3838 itb->wd = wd;
3839 if (!it->item->rel->item->block)
3840 {
3841 wd->blocks =
3842 eina_inlist_append(wd->blocks, EINA_INLIST_GET(itb));
3843 itb->items = eina_list_append(itb->items, it);
3844 itb->position_update = EINA_TRUE;
3845 it->position = eina_list_count(itb->items);
3846 it->position_update = EINA_TRUE;
3847
3848 if (wd->blocks != EINA_INLIST_GET(itb))
3849 {
3850 itb->position = ((Item_Block *) (EINA_INLIST_GET(itb)->prev))->position + 1;
3851 }
3852 else
3853 {
3854 itb->position = 0;
3855 }
3856 }
3857 else
3858 {
3859 Eina_List *tmp;
3860
3861 tmp = eina_list_data_find_list(itb->items, it->item->rel);
3862 if (it->item->before)
3863 {
3864 wd->blocks = eina_inlist_prepend_relative
3865 (wd->blocks, EINA_INLIST_GET(itb),
3866 EINA_INLIST_GET(it->item->rel->item->block));
3867 itb->items =
3868 eina_list_prepend_relative_list(itb->items, it, tmp);
3869
3870 /* Update index from where we prepended */
3871 _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3872 _item_block_position_update(EINA_INLIST_GET(itb),
3873 it->item->rel->item->block->position);
3874 }
3875 else
3876 {
3877 wd->blocks = eina_inlist_append_relative
3878 (wd->blocks, EINA_INLIST_GET(itb),
3879 EINA_INLIST_GET(it->item->rel->item->block));
3880 itb->items =
3881 eina_list_append_relative_list(itb->items, it, tmp);
3882
3883 /* Update block index from where we appended */
3884 _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3885 _item_block_position_update(EINA_INLIST_GET(itb),
3886 it->item->rel->item->block->position + 1);
3887 }
3888 }
3889 }
3890 else
3891 {
3892 if (it->item->before)
3893 {
3894 if (wd->blocks)
3895 {
3896 itb = (Item_Block *)(wd->blocks);
3897 if (itb->count >= wd->max_items_per_block)
3898 {
3899 itb = _item_block_new(wd, EINA_TRUE);
3900 if (!itb) return EINA_FALSE;
3901 }
3902 }
3903 else
3904 {
3905 itb = _item_block_new(wd, EINA_TRUE);
3906 if (!itb) return EINA_FALSE;
3907 }
3908 itb->items = eina_list_prepend(itb->items, it);
3909
3910 _item_position_update(itb->items, 0);
3911 }
3912 else
3913 {
3914 if (wd->blocks)
3915 {
3916 itb = (Item_Block *)(wd->blocks->last);
3917 if (itb->count >= wd->max_items_per_block)
3918 {
3919 itb = _item_block_new(wd, EINA_FALSE);
3920 if (!itb) return EINA_FALSE;
3921 }
3922 }
3923 else
3924 {
3925 itb = _item_block_new(wd, EINA_FALSE);
3926 if (!itb) return EINA_FALSE;
3927 }
3928 itb->items = eina_list_append(itb->items, it);
3929 it->position = eina_list_count(itb->items);
3930 }
3931 }
3932 }
3933 else
3934 {
3935 Eina_List *tmp;
3936
3937 if (it->item->rel->item->queued)
3938 {
3939 /* NOTE: for a strange reason eina_list and eina_inlist don't have the same property
3940 on sorted insertion order, so the queue is not always ordered like the item list.
3941 This lead to issue where we depend on an item that is not yet created. As a quick
3942 work around, we reschedule the calc of the item and stop reordering the list to
3943 prevent any nasty issue to show up here.
3944 */
3945 wd->queue = eina_list_append(wd->queue, it);
3946 wd->requeued = EINA_TRUE;
3947 it->item->queued = EINA_TRUE;
3948 return EINA_FALSE;
3949 }
3950 itb = it->item->rel->item->block;
3951 if (!itb) goto newblock;
3952 tmp = eina_list_data_find_list(itb->items, it->item->rel);
3953 if (it->item->before)
3954 {
3955 itb->items = eina_list_prepend_relative_list(itb->items, it, tmp);
3956 _item_position_update(eina_list_prev(tmp), it->item->rel->position);
3957 }
3958 else
3959 {
3960 itb->items = eina_list_append_relative_list(itb->items, it, tmp);
3961 _item_position_update(eina_list_next(tmp), it->item->rel->position + 1);
3962 }
3963 }
3964 itb->count++;
3965 itb->changed = EINA_TRUE;
3966 it->item->block = itb;
3967 if (itb->wd->calc_job) ecore_job_del(itb->wd->calc_job);
3968 itb->wd->calc_job = ecore_job_add(_calc_job, itb->wd);
3969 if (it->item->rel)
3970 {
3971 it->item->rel->relcount--;
3972 if ((it->item->rel->generation < it->wd->generation) && (!it->item->rel->relcount))
3973 {
3974 _item_del(it->item->rel);
3975 elm_widget_item_free(it->item->rel);
3976 }
3977 it->item->rel = NULL;
3978 }
3979 if (itb->count > itb->wd->max_items_per_block)
3980 {
3981 Item_Block *itb2;
3982 Elm_Gen_Item *it2;
3983 int newc;
3984 Eina_Bool done = EINA_FALSE;
3985
3986 newc = itb->count / 2;
3987
3988 if (EINA_INLIST_GET(itb)->prev)
3989 {
3990 Item_Block *itbp = (Item_Block *)(EINA_INLIST_GET(itb)->prev);
3991
3992 if (itbp->count + newc < wd->max_items_per_block / 2)
3993 {
3994 /* moving items to previous block */
3995 while ((itb->count > newc) && (itb->items))
3996 {
3997 it2 = eina_list_data_get(itb->items);
3998 itb->items = eina_list_remove_list(itb->items, itb->items);
3999 itb->count--;
4000
4001 itbp->items = eina_list_append(itbp->items, it2);
4002 it2->item->block = itbp;
4003 itbp->count++;
4004 }
4005
4006 done = EINA_TRUE;
4007 }
4008 }
4009
4010 if (!done && EINA_INLIST_GET(itb)->next)
4011 {
4012 Item_Block *itbn = (Item_Block *)(EINA_INLIST_GET(itb)->next);
4013
4014 if (itbn->count + newc < wd->max_items_per_block / 2)
4015 {
4016 /* moving items to next block */
4017 while ((itb->count > newc) && (itb->items))
4018 {
4019 Eina_List *l;
4020
4021 l = eina_list_last(itb->items);
4022 it2 = eina_list_data_get(l);
4023 itb->items = eina_list_remove_list(itb->items, l);
4024 itb->count--;
4025
4026 itbn->items = eina_list_prepend(itbn->items, it2);
4027 it2->item->block = itbn;
4028 itbn->count++;
4029 }
4030
4031 done = EINA_TRUE;
4032 }
4033 }
4034
4035 if (!done)
4036 {
4037 /* moving items to new block */
4038 itb2 = calloc(1, sizeof(Item_Block));
4039 if (!itb2) return EINA_FALSE;
4040 itb2->wd = wd;
4041 wd->blocks =
4042 eina_inlist_append_relative(wd->blocks, EINA_INLIST_GET(itb2),
4043 EINA_INLIST_GET(itb));
4044 itb2->changed = EINA_TRUE;
4045 while ((itb->count > newc) && (itb->items))
4046 {
4047 Eina_List *l;
4048
4049 l = eina_list_last(itb->items);
4050 it2 = l->data;
4051 itb->items = eina_list_remove_list(itb->items, l);
4052 itb->count--;
4053
4054 itb2->items = eina_list_prepend(itb2->items, it2);
4055 it2->item->block = itb2;
4056 itb2->count++;
4057 }
4058 }
4059 }
4060
4061 return EINA_TRUE;
4062}
4063
4064static int
4065_queue_process(Widget_Data *wd)
4066{
4067 int n;
4068 Eina_Bool showme = EINA_FALSE;
4069 double t0, t;
4070
4071 t0 = ecore_loop_time_get();
4072 //evas_event_freeze(evas_object_evas_get(wd->obj));
4073 for (n = 0; (wd->queue) && (n < 128); n++)
4074 {
4075 Elm_Gen_Item *it;
4076
4077 it = eina_list_data_get(wd->queue);
4078 wd->queue = eina_list_remove_list(wd->queue, wd->queue);
4079 it->item->queued = EINA_FALSE;
4080 if (!_item_block_add(wd, it)) continue;
4081 if (!wd->blocks)
4082 _item_block_realize(it->item->block);
4083 t = ecore_time_get();
4084 if (it->item->block->changed)
4085 {
4086 showme = _item_block_recalc(it->item->block, it->item->block->num, EINA_TRUE);
4087 it->item->block->changed = 0;
4088 if (wd->pan_changed)
4089 {
4090 if (wd->calc_job) ecore_job_del(wd->calc_job);
4091 wd->calc_job = NULL;
4092 _calc_job(wd);
4093 wd->pan_changed = EINA_FALSE;
4094 }
4095 }
4096 if (showme) it->item->block->showme = EINA_TRUE;
4097 /* same as eina_inlist_count > 1 */
4098 if (wd->blocks && wd->blocks->next)
4099 {
4100 if ((t - t0) > (ecore_animator_frametime_get())) break;
4101 }
4102 }
4103 //evas_event_thaw(evas_object_evas_get(wd->obj));
4104 //evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4105 return n;
4106}
4107
4108static Eina_Bool
4109_idle_process(void *data, Eina_Bool *wakeup)
4110{
4111 Widget_Data *wd = data;
4112
4113 //xxx
4114 //static double q_start = 0.0;
4115 //if (q_start == 0.0) q_start = ecore_time_get();
4116 //xxx
4117 if (_queue_process(wd) > 0) *wakeup = EINA_TRUE;
4118 if (!wd->queue)
4119 {
4120 //xxx
4121 //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
4122 //xxx
4123 return ECORE_CALLBACK_CANCEL;
4124 }
4125 return ECORE_CALLBACK_RENEW;
4126}
4127
4128static Eina_Bool
4129_item_idle_enterer(void *data)
4130{
4131 Widget_Data *wd = data;
4132 Eina_Bool wakeup = EINA_FALSE;
4133 Eina_Bool ok = _idle_process(data, &wakeup);
4134
4135 if (wakeup)
4136 {
4137 // wake up mainloop
4138 if (wd->calc_job) ecore_job_del(wd->calc_job);
4139 wd->calc_job = ecore_job_add(_calc_job, wd);
4140 }
4141 if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
4142 return ok;
4143}
4144
4145static void
4146_item_queue(Widget_Data *wd,
4147 Elm_Gen_Item *it,
4148 Eina_Compare_Cb cb)
4149{
4150 if (it->item->queued) return;
4151 it->item->queued = EINA_TRUE;
4152 if (cb && !wd->requeued)
4153 wd->queue = eina_list_sorted_insert(wd->queue, cb, it);
4154 else
4155 wd->queue = eina_list_append(wd->queue, it);
4156// FIXME: why does a freeze then thaw here cause some genlist
4157// elm_genlist_item_append() to be much much slower?
4158// evas_event_freeze(evas_object_evas_get(wd->obj));
4159 while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
4160 {
4161 if (wd->queue_idle_enterer)
4162 {
4163 ecore_idle_enterer_del(wd->queue_idle_enterer);
4164 wd->queue_idle_enterer = NULL;
4165 }
4166 _queue_process(wd);
4167 }
4168// evas_event_thaw(evas_object_evas_get(wd->obj));
4169// evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4170 if (!wd->queue_idle_enterer)
4171 wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
4172}
4173
4174static int
4175_elm_genlist_item_compare(const void *data, const void *data1)
4176{
4177 const Elm_Gen_Item *it, *item1;
4178 it = ELM_GEN_ITEM_FROM_INLIST(data);
4179 item1 = ELM_GEN_ITEM_FROM_INLIST(data1);
4180 return it->wd->item_compare_cb(it, item1);
4181}
4182
4183static int
4184_elm_genlist_item_list_compare(const void *data, const void *data1)
4185{
4186 const Elm_Gen_Item *it = data;
4187 const Elm_Gen_Item *item1 = data1;
4188 return it->wd->item_compare_cb(it, item1);
4189}
4190
4191/*If application want to know the relative item, use elm_genlist_item_prev_get(it)*/
4192static void
4193_item_move_after(Elm_Gen_Item *it, Elm_Gen_Item *after)
4194{
4195 if (!it) return;
4196 if (!after) return;
4197
4198 it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4199 _item_block_del(it);
4200
4201 it->wd->items = eina_inlist_append_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(after));
4202 it->item->rel = after;
4203 it->item->rel->relcount++;
4204 it->item->before = EINA_FALSE;
4205 if (after->item->group_item) it->item->group_item = after->item->group_item;
4206 _item_queue(it->wd, it, NULL);
4207
4208 evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_AFTER, it);
4209}
4210
4211/*If application want to know the relative item, use elm_genlist_item_next_get(it)*/
4212static void
4213_item_move_before(Elm_Gen_Item *it, Elm_Gen_Item *before)
4214{
4215 if (!it) return;
4216 if (!before) return;
4217
4218 it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
4219 _item_block_del(it);
4220 it->wd->items = eina_inlist_prepend_relative(it->wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(before));
4221 it->item->rel = before;
4222 it->item->rel->relcount++;
4223 it->item->before = EINA_TRUE;
4224 if (before->item->group_item) it->item->group_item = before->item->group_item;
4225 _item_queue(it->wd, it, NULL);
4226
4227 evas_object_smart_callback_call(WIDGET(it), SIG_MOVED_BEFORE, it);
4228}
4229
4230EAPI unsigned int
4231elm_genlist_items_count(const Evas_Object *obj)
4232{
4233 ELM_CHECK_WIDTYPE(obj, widtype) 0;
4234 Widget_Data *wd = elm_widget_data_get(obj);
4235 if (!wd) return 0;
4236 return wd->item_count;
4237}
4238
4239EAPI Elm_Object_Item *
4240elm_genlist_item_append(Evas_Object *obj,
4241 const Elm_Genlist_Item_Class *itc,
4242 const void *data,
4243 Elm_Object_Item *parent,
4244 Elm_Genlist_Item_Type type,
4245 Evas_Smart_Cb func,
4246 const void *func_data)
4247{
4248 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4249 Widget_Data *wd = elm_widget_data_get(obj);
4250 if (!wd) return NULL;
4251 Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4252 func, func_data);
4253 if (!it) return NULL;
4254 if (!it->parent)
4255 {
4256 if (it->group)
4257 wd->group_items = eina_list_append(wd->group_items, it);
4258 wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
4259 it->item->rel = NULL;
4260 }
4261 else
4262 {
4263 Elm_Gen_Item *it2 = NULL;
4264 Eina_List *ll = eina_list_last(it->parent->item->items);
4265 if (ll) it2 = ll->data;
4266 it->parent->item->items = eina_list_append(it->parent->item->items, it);
4267 if (!it2) it2 = it->parent;
4268 wd->items =
4269 eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4270 EINA_INLIST_GET(it2));
4271 it->item->rel = it2;
4272 it->item->rel->relcount++;
4273 }
4274 it->item->before = EINA_FALSE;
4275 _item_queue(wd, it, NULL);
4276 return (Elm_Object_Item *)it;
4277}
4278
4279EAPI Elm_Object_Item *
4280elm_genlist_item_prepend(Evas_Object *obj,
4281 const Elm_Genlist_Item_Class *itc,
4282 const void *data,
4283 Elm_Object_Item *parent,
4284 Elm_Genlist_Item_Type type,
4285 Evas_Smart_Cb func,
4286 const void *func_data)
4287{
4288 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4289 Widget_Data *wd = elm_widget_data_get(obj);
4290 if (!wd) return NULL;
4291 Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4292 func, func_data);
4293 if (!it) return NULL;
4294 if (!it->parent)
4295 {
4296 if (it->group)
4297 wd->group_items = eina_list_prepend(wd->group_items, it);
4298 wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
4299 it->item->rel = NULL;
4300 }
4301 else
4302 {
4303 Elm_Gen_Item *it2 = NULL;
4304 Eina_List *ll = it->parent->item->items;
4305 if (ll) it2 = ll->data;
4306 it->parent->item->items = eina_list_prepend(it->parent->item->items, it);
4307 if (!it2) it2 = it->parent;
4308 wd->items =
4309 eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4310 EINA_INLIST_GET(it2));
4311 it->item->rel = it2;
4312 it->item->rel->relcount++;
4313 }
4314 it->item->before = EINA_TRUE;
4315 _item_queue(wd, it, NULL);
4316 return (Elm_Object_Item *)it;
4317}
4318
4319EAPI Elm_Object_Item *
4320elm_genlist_item_insert_after(Evas_Object *obj,
4321 const Elm_Genlist_Item_Class *itc,
4322 const void *data,
4323 Elm_Object_Item *parent,
4324 Elm_Object_Item *after,
4325 Elm_Genlist_Item_Type type,
4326 Evas_Smart_Cb func,
4327 const void *func_data)
4328{
4329 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4330 ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
4331 Widget_Data *wd = elm_widget_data_get(obj);
4332 Elm_Gen_Item *_after = (Elm_Gen_Item *) after;
4333 if (!wd) return NULL;
4334 /* It makes no sense to insert after in an empty list with after != NULL, something really bad is happening in your app. */
4335 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4336
4337 Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4338 func, func_data);
4339 if (!it) return NULL;
4340 if (!it->parent)
4341 {
4342 if ((it->group) && (_after->group))
4343 wd->group_items = eina_list_append_relative(wd->group_items, it,
4344 _after);
4345 }
4346 else
4347 {
4348 it->parent->item->items =
4349 eina_list_append_relative(it->parent->item->items, it, _after);
4350 }
4351 wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
4352 EINA_INLIST_GET(_after));
4353 it->item->rel = _after;
4354 it->item->rel->relcount++;
4355 it->item->before = EINA_FALSE;
4356 _item_queue(wd, it, NULL);
4357 return (Elm_Object_Item *)it;
4358}
4359
4360EAPI Elm_Object_Item *
4361elm_genlist_item_insert_before(Evas_Object *obj,
4362 const Elm_Genlist_Item_Class *itc,
4363 const void *data,
4364 Elm_Object_Item *parent,
4365 Elm_Object_Item *before,
4366 Elm_Genlist_Item_Type type,
4367 Evas_Smart_Cb func,
4368 const void *func_data)
4369{
4370 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4371 ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
4372 Widget_Data *wd = elm_widget_data_get(obj);
4373 Elm_Gen_Item *_before = (Elm_Gen_Item *) before;
4374 if (!wd) return NULL;
4375 /* It makes no sense to insert before in an empty list with before != NULL, something really bad is happening in your app. */
4376 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->items, NULL);
4377
4378 Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4379 func, func_data);
4380 if (!it) return NULL;
4381 if (!it->parent)
4382 {
4383 if (it->group && _before->group)
4384 wd->group_items = eina_list_prepend_relative(wd->group_items, it,
4385 _before);
4386 }
4387 else
4388 {
4389 it->parent->item->items =
4390 eina_list_prepend_relative(it->parent->item->items, it, _before);
4391 }
4392 wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
4393 EINA_INLIST_GET(_before));
4394 it->item->rel = _before;
4395 it->item->rel->relcount++;
4396 it->item->before = EINA_TRUE;
4397 _item_queue(wd, it, NULL);
4398 return (Elm_Object_Item *)it;
4399}
4400
4401EAPI Elm_Object_Item *
4402elm_genlist_item_sorted_insert(Evas_Object *obj,
4403 const Elm_Genlist_Item_Class *itc,
4404 const void *data,
4405 Elm_Object_Item *parent,
4406 Elm_Genlist_Item_Type type,
4407 Eina_Compare_Cb comp,
4408 Evas_Smart_Cb func,
4409 const void *func_data)
4410{
4411 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4412 Widget_Data *wd = elm_widget_data_get(obj);
4413 if (!wd) return NULL;
4414 Elm_Gen_Item *rel = NULL;
4415 Elm_Gen_Item *it = _item_new(wd, itc, data, (Elm_Gen_Item *) parent, type,
4416 func, func_data);
4417 if (!it) return NULL;
4418
4419 wd->item_compare_cb = comp;
4420
4421 if (it->parent)
4422 {
4423 Eina_List *l;
4424 int cmp_result;
4425
4426 l = eina_list_search_sorted_near_list(it->parent->item->items,
4427 _elm_genlist_item_list_compare,
4428 it,
4429 &cmp_result);
4430 if (l)
4431 rel = eina_list_data_get(l);
4432 else
4433 rel = it->parent;
4434
4435 if (cmp_result >= 0)
4436 {
4437 it->parent->item->items = eina_list_prepend_relative_list(it->parent->item->items, it, l);
4438 wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4439 it->item->before = EINA_FALSE;
4440 }
4441 else if (cmp_result < 0)
4442 {
4443 it->parent->item->items = eina_list_append_relative_list(it->parent->item->items, it, l);
4444 wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it), EINA_INLIST_GET(rel));
4445 it->item->before = EINA_TRUE;
4446 }
4447 }
4448 else
4449 {
4450 if (!wd->state)
4451 {
4452 wd->state = eina_inlist_sorted_state_new();
4453 eina_inlist_sorted_state_init(wd->state, wd->items);
4454 wd->requeued = EINA_FALSE;
4455 }
4456
4457 if (it->group)
4458 wd->group_items = eina_list_append(wd->group_items, it);
4459
4460 wd->items = eina_inlist_sorted_state_insert(wd->items, EINA_INLIST_GET(it),
4461 _elm_genlist_item_compare, wd->state);
4462
4463 if (EINA_INLIST_GET(it)->next)
4464 {
4465 rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4466 it->item->before = EINA_TRUE;
4467 }
4468 else if (EINA_INLIST_GET(it)->prev)
4469 {
4470 rel = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4471 it->item->before = EINA_FALSE;
4472 }
4473 }
4474
4475 if (rel)
4476 {
4477 it->item->rel = rel;
4478 it->item->rel->relcount++;
4479 }
4480
4481 _item_queue(wd, it, _elm_genlist_item_list_compare);
4482
4483 return (Elm_Object_Item *)it;
4484}
4485
4486static void
4487_elm_genlist_clear(Evas_Object *obj, Eina_Bool standby)
4488{
4489 Eina_Inlist *next, *l;
4490 Widget_Data *wd = elm_widget_data_get(obj);
4491 if (!wd) return;
4492
4493 if (!standby) wd->generation++;
4494
4495 if (wd->state)
4496 {
4497 eina_inlist_sorted_state_free(wd->state);
4498 wd->state = NULL;
4499 }
4500
4501 if (wd->walking > 0)
4502 {
4503 wd->clear_me = EINA_TRUE;
4504 return;
4505 }
4506 evas_event_freeze(evas_object_evas_get(wd->obj));
4507 for (l = wd->items, next = l ? l->next : NULL;
4508 l;
4509 l = next, next = next ? next->next : NULL)
4510 {
4511 Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(l);
4512
4513 if (it->generation < wd->generation)
4514 {
4515 Elm_Gen_Item *itn = NULL;
4516
4517 if (next) itn = ELM_GEN_ITEM_FROM_INLIST(next);
4518 if (itn) itn->walking++; /* prevent early death of subitem */
4519 it->del_cb(it);
4520 elm_widget_item_free(it);
4521 if (itn) itn->walking--;
4522 }
4523 }
4524 wd->clear_me = EINA_FALSE;
4525 wd->pan_changed = EINA_TRUE;
4526 if (wd->calc_job)
4527 {
4528 ecore_job_del(wd->calc_job);
4529 wd->calc_job = NULL;
4530 }
4531 if (wd->selected) wd->selected = eina_list_free(wd->selected);
4532 if (wd->clear_cb) wd->clear_cb(wd);
4533 wd->pan_x = 0;
4534 wd->pan_y = 0;
4535 wd->minw = 0;
4536 wd->minh = 0;
4537
4538 if (wd->alpha_bg) evas_object_del(wd->alpha_bg);
4539 wd->alpha_bg = NULL;
4540
4541 if (wd->pan_smart)
4542 {
4543 evas_object_size_hint_min_set(wd->pan_smart, wd->minw, wd->minh);
4544 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
4545 }
4546 if (wd->sizing_cb) wd->sizing_cb(wd->obj);
4547 elm_smart_scroller_child_region_show(wd->scr, 0, 0, 0, 0);
4548 evas_event_thaw(evas_object_evas_get(wd->obj));
4549 evas_event_thaw_eval(evas_object_evas_get(wd->obj));
4550}
4551
4552EAPI void
4553elm_genlist_clear(Evas_Object *obj)
4554{
4555 ELM_CHECK_WIDTYPE(obj, widtype);
4556 _elm_genlist_clear(obj, EINA_FALSE);
4557}
4558
4559EAPI void
4560elm_genlist_multi_select_set(Evas_Object *obj,
4561 Eina_Bool multi)
4562{
4563 ELM_CHECK_WIDTYPE(obj, widtype);
4564 Widget_Data *wd = elm_widget_data_get(obj);
4565 if (!wd) return;
4566 wd->multi = !!multi;
4567}
4568
4569EAPI Eina_Bool
4570elm_genlist_multi_select_get(const Evas_Object *obj)
4571{
4572 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4573 Widget_Data *wd = elm_widget_data_get(obj);
4574 if (!wd) return EINA_FALSE;
4575 return wd->multi;
4576}
4577
4578EAPI Elm_Object_Item *
4579elm_genlist_selected_item_get(const Evas_Object *obj)
4580{
4581 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4582 Widget_Data *wd = elm_widget_data_get(obj);
4583 if (!wd) return NULL;
4584 if (wd->selected) return wd->selected->data;
4585 return NULL;
4586}
4587
4588EAPI const Eina_List *
4589elm_genlist_selected_items_get(const Evas_Object *obj)
4590{
4591 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4592 Widget_Data *wd = elm_widget_data_get(obj);
4593 if (!wd) return NULL;
4594 return wd->selected;
4595}
4596
4597EAPI Eina_List *
4598elm_genlist_realized_items_get(const Evas_Object *obj)
4599{
4600 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4601 Widget_Data *wd = elm_widget_data_get(obj);
4602 Eina_List *list = NULL;
4603 Item_Block *itb;
4604 Eina_Bool done = EINA_FALSE;
4605 if (!wd) return NULL;
4606 EINA_INLIST_FOREACH(wd->blocks, itb)
4607 {
4608 if (itb->realized)
4609 {
4610 Eina_List *l;
4611 Elm_Gen_Item *it;
4612
4613 done = EINA_TRUE;
4614 EINA_LIST_FOREACH(itb->items, l, it)
4615 {
4616 if (it->realized) list = eina_list_append(list, it);
4617 }
4618 }
4619 else
4620 {
4621 if (done) break;
4622 }
4623 }
4624 return list;
4625}
4626
4627EAPI Elm_Object_Item *
4628elm_genlist_at_xy_item_get(const Evas_Object *obj,
4629 Evas_Coord x,
4630 Evas_Coord y,
4631 int *posret)
4632{
4633 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4634 Widget_Data *wd = elm_widget_data_get(obj);
4635 Evas_Coord ox, oy, ow, oh;
4636 Item_Block *itb;
4637 Evas_Coord lasty;
4638 if (!wd) return NULL;
4639 evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
4640 lasty = oy;
4641 EINA_INLIST_FOREACH(wd->blocks, itb)
4642 {
4643 Eina_List *l;
4644 Elm_Gen_Item *it;
4645
4646 if (!ELM_RECTS_INTERSECT(ox + itb->x - itb->wd->pan_x,
4647 oy + itb->y - itb->wd->pan_y,
4648 itb->w, itb->h, x, y, 1, 1))
4649 continue;
4650 EINA_LIST_FOREACH(itb->items, l, it)
4651 {
4652 Evas_Coord itx, ity;
4653
4654 itx = ox + itb->x + it->x - itb->wd->pan_x;
4655 ity = oy + itb->y + it->y - itb->wd->pan_y;
4656 if (ELM_RECTS_INTERSECT(itx, ity, it->item->w, it->item->h, x, y, 1, 1))
4657 {
4658 if (posret)
4659 {
4660 if (y <= (ity + (it->item->h / 4))) *posret = -1;
4661 else if (y >= (ity + it->item->h - (it->item->h / 4)))
4662 *posret = 1;
4663 else *posret = 0;
4664 }
4665 return (Elm_Object_Item *)it;
4666 }
4667 lasty = ity + it->item->h;
4668 }
4669 }
4670 if (posret)
4671 {
4672 if (y > lasty) *posret = 1;
4673 else *posret = -1;
4674 }
4675 return NULL;
4676}
4677
4678EAPI Elm_Object_Item *
4679elm_genlist_first_item_get(const Evas_Object *obj)
4680{
4681 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4682 Widget_Data *wd = elm_widget_data_get(obj);
4683 if (!wd) return NULL;
4684 if (!wd->items) return NULL;
4685 Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items);
4686 while ((it) && (it->generation < wd->generation))
4687 it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
4688 return (Elm_Object_Item *)it;
4689}
4690
4691EAPI Elm_Object_Item *
4692elm_genlist_last_item_get(const Evas_Object *obj)
4693{
4694 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4695 Widget_Data *wd = elm_widget_data_get(obj);
4696 if (!wd) return NULL;
4697 if (!wd->items) return NULL;
4698 Elm_Gen_Item *it = ELM_GEN_ITEM_FROM_INLIST(wd->items->last);
4699 while ((it) && (it->generation < wd->generation))
4700 it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->prev);
4701 return (Elm_Object_Item *)it;
4702}
4703
4704EAPI Elm_Object_Item *
4705elm_genlist_item_next_get(const Elm_Object_Item *it)
4706{
4707 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4708 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4709 while (_it)
4710 {
4711 _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->next);
4712 if ((_it) && (_it->generation == _it->wd->generation)) break;
4713 }
4714 return (Elm_Object_Item *) _it;
4715}
4716
4717EAPI Elm_Object_Item *
4718elm_genlist_item_prev_get(const Elm_Object_Item *it)
4719{
4720 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4721 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4722 while (_it)
4723 {
4724 _it = ELM_GEN_ITEM_FROM_INLIST(EINA_INLIST_GET(_it)->prev);
4725 if ((_it) && (_it->generation == _it->wd->generation)) break;
4726 }
4727 return (Elm_Object_Item *) _it;
4728}
4729
4730EAPI Elm_Object_Item *
4731elm_genlist_item_parent_get(const Elm_Object_Item *it)
4732{
4733 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
4734 return (Elm_Object_Item *) ((Elm_Gen_Item *)it)->parent;
4735}
4736
4737EAPI void
4738elm_genlist_item_subitems_clear(Elm_Object_Item *it)
4739{
4740 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4741 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
4742 if (!wd) return;
4743 Elm_Gen_Item *_it = (Elm_Gen_Item *) it;
4744
4745 if (!wd->tree_effect_enabled || !wd->move_effect_mode)
4746 _item_subitems_clear(_it);
4747 else
4748 {
4749 if (!wd->tree_effect_animator)
4750 {
4751 wd->expanded_item = _it;
4752 _item_tree_effect_before(_it);
4753 evas_object_raise(wd->alpha_bg);
4754 evas_object_show(wd->alpha_bg);
4755 wd->start_time = ecore_time_get();
4756 wd->tree_effect_animator = ecore_animator_add(_tree_effect_animator_cb, wd);
4757 }
4758 else
4759 _item_subitems_clear(_it);
4760 }
4761}
4762
4763EAPI void
4764elm_genlist_item_selected_set(Elm_Object_Item *it,
4765 Eina_Bool selected)
4766{
4767 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4768 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4769 Widget_Data *wd = _it->wd;
4770 if (!wd) return;
4771 if ((_it->generation < wd->generation) || elm_widget_item_disabled_get(_it))
4772 return;
4773 selected = !!selected;
4774 if (_it->selected == selected) return;
4775
4776 if (selected)
4777 {
4778 if (!wd->multi)
4779 {
4780 while (wd->selected)
4781 {
4782 if (_it->unhighlight_cb) _it->unhighlight_cb(wd->selected->data);
4783 _it->unsel_cb(wd->selected->data);
4784 }
4785 }
4786 _it->highlight_cb(_it);
4787 _item_select(_it);
4788 return;
4789 }
4790 if (_it->unhighlight_cb) _it->unhighlight_cb(_it);
4791 _it->unsel_cb(_it);
4792}
4793
4794EAPI Eina_Bool
4795elm_genlist_item_selected_get(const Elm_Object_Item *it)
4796{
4797 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4798 return ((Elm_Gen_Item *)it)->selected;
4799}
4800
4801Elm_Gen_Item *
4802_elm_genlist_expanded_next_item_get(Elm_Gen_Item *it)
4803{
4804 Elm_Gen_Item *it2;
4805 if (it->item->expanded)
4806 {
4807 it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
4808 }
4809 else
4810 {
4811 it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
4812 while (it2)
4813 {
4814 if (it->item->expanded_depth >= it2->item->expanded_depth) break;
4815 it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
4816 }
4817 }
4818 return it2;
4819}
4820
4821static void
4822_elm_genlist_move_items_set(Elm_Gen_Item *it)
4823{
4824 Eina_List *l, *ll;
4825 Elm_Gen_Item *it2 = NULL;
4826 Evas_Coord ox, oy, ow, oh, dh = 0;
4827
4828 it->wd->expanded_next_item = _elm_genlist_expanded_next_item_get(it);
4829
4830 if (it->item->expanded)
4831 {
4832 it->wd->move_items = elm_genlist_realized_items_get(it->wd->obj);
4833 EINA_LIST_FOREACH_SAFE(it->wd->move_items, l, ll, it2)
4834 {
4835 if (it2 == it->wd->expanded_next_item) break;
4836 it->wd->move_items = eina_list_remove(it->wd->move_items, it2);
4837 }
4838 }
4839 else
4840 {
4841 evas_object_geometry_get(it->wd->pan_smart, &ox, &oy, &ow, &oh);
4842 it2 = it->wd->expanded_next_item;
4843 while (it2 && (dh < oy + oh))
4844 {
4845 dh += it2->item->h;
4846 it->wd->move_items = eina_list_append(it->wd->move_items, it2);
4847 it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
4848 }
4849 }
4850}
4851
4852EAPI void
4853elm_genlist_item_expanded_set(Elm_Object_Item *it,
4854 Eina_Bool expanded)
4855{
4856 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4857 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4858 expanded = !!expanded;
4859 if (_it->item->expanded == expanded) return;
4860 _it->item->expanded = expanded;
4861 _it->wd->expanded_item = _it;
4862 _elm_genlist_move_items_set(_it);
4863
4864 if (_it->wd->tree_effect_enabled && !_it->wd->alpha_bg)
4865 _it->wd->alpha_bg = _create_tray_alpha_bg(WIDGET(_it));
4866
4867 if (_it->item->expanded)
4868 {
4869 _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_EXPAND;
4870 if (_it->realized)
4871 edje_object_signal_emit(VIEW(_it), "elm,state,expanded", "elm");
4872 evas_object_smart_callback_call(WIDGET(_it), SIG_EXPANDED, _it);
4873 _it->wd->auto_scroll_enabled = EINA_TRUE;
4874 }
4875 else
4876 {
4877 _it->wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_CONTRACT;
4878 if (_it->realized)
4879 edje_object_signal_emit(VIEW(_it), "elm,state,contracted", "elm");
4880 evas_object_smart_callback_call(WIDGET(_it), SIG_CONTRACTED, _it);
4881 _it->wd->auto_scroll_enabled = EINA_FALSE;
4882 }
4883}
4884
4885EAPI Eina_Bool
4886elm_genlist_item_expanded_get(const Elm_Object_Item *it)
4887{
4888 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
4889 return ((Elm_Gen_Item *)it)->item->expanded;
4890}
4891
4892EAPI int
4893elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it)
4894{
4895 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
4896 return ((Elm_Gen_Item *)it)->item->expanded_depth;
4897}
4898
4899static Eina_Bool
4900_elm_genlist_item_compute_coordinates(Elm_Object_Item *it,
4901 Elm_Genlist_Item_Scrollto_Type type,
4902 Eina_Bool bring_in,
4903 Evas_Coord *x,
4904 Evas_Coord *y,
4905 Evas_Coord *w,
4906 Evas_Coord *h)
4907{
4908 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4909 Evas_Coord gith = 0;
4910 if (_it->generation < _it->wd->generation) return EINA_FALSE;
4911 if ((_it->item->queued) || (!_it->item->mincalcd))
4912 {
4913 _it->wd->show_item = _it;
4914 _it->wd->bring_in = bring_in;
4915 _it->wd->scrollto_type = type;
4916 _it->item->showme = EINA_TRUE;
4917 return EINA_FALSE;
4918 }
4919 if (_it->wd->show_item)
4920 {
4921 _it->wd->show_item->item->showme = EINA_FALSE;
4922 _it->wd->show_item = NULL;
4923 }
4924
4925 evas_object_geometry_get(_it->wd->pan_smart, NULL, NULL, w, h);
4926 switch (type)
4927 {
4928 case ELM_GENLIST_ITEM_SCROLLTO_IN:
4929 if ((_it->item->group_item) &&
4930 (_it->wd->pan_y > (_it->y + _it->item->block->y)))
4931 gith = _it->item->group_item->item->h;
4932 *h = _it->item->h;
4933 *y = _it->y + _it->item->block->y - gith;
4934 break;
4935 case ELM_GENLIST_ITEM_SCROLLTO_TOP:
4936 if (_it->item->group_item) gith = _it->item->group_item->item->h;
4937 *y = _it->y + _it->item->block->y - gith;
4938 break;
4939 case ELM_GENLIST_ITEM_SCROLLTO_MIDDLE:
4940 *y = _it->y + _it->item->block->y - (*h / 2) + (_it->item->h / 2);
4941 break;
4942 default:
4943 return EINA_FALSE;
4944 }
4945
4946 *x = _it->x + _it->item->block->x;
4947 *w = _it->item->block->w;
4948 return EINA_TRUE;
4949}
4950
4951EAPI void
4952elm_genlist_item_promote(Elm_Object_Item *it)
4953{
4954 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4955 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4956 if (_it->generation < _it->wd->generation) return;
4957 _item_move_before(_it,
4958 (Elm_Gen_Item *) elm_genlist_first_item_get(WIDGET(_it)));
4959}
4960
4961EAPI void
4962elm_genlist_item_demote(Elm_Object_Item *it)
4963{
4964 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4965 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4966 if (_it->generation < _it->wd->generation) return;
4967 _item_move_after(_it,
4968 (Elm_Gen_Item *) elm_genlist_last_item_get(WIDGET(_it)));
4969}
4970
4971EAPI void
4972elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4973{
4974 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4975 Evas_Coord x, y, w, h;
4976 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4977
4978 if (_elm_genlist_item_compute_coordinates(it, type, EINA_FALSE, &x, &y, &w, &h))
4979 elm_smart_scroller_child_region_show(_it->wd->scr, x, y, w, h);
4980}
4981
4982EAPI void
4983elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type)
4984{
4985
4986 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4987 Evas_Coord x, y, w, h;
4988 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
4989
4990 if (_elm_genlist_item_compute_coordinates(it, type, EINA_TRUE, &x, &y, &w, &h))
4991 elm_smart_scroller_region_bring_in(_it->wd->scr, x, y, w, h);
4992}
4993
4994EAPI void
4995elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l)
4996{
4997 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
4998
4999 Evas_Object *content;
5000 EINA_LIST_FREE(((Elm_Gen_Item *)it)->content_objs, content)
5001 {
5002 elm_widget_sub_object_del(WIDGET(it), content);
5003 evas_object_smart_member_del(content);
5004 evas_object_hide(content);
5005 if (l) *l = eina_list_append(*l, content);
5006 }
5007}
5008
5009EAPI void
5010elm_genlist_item_update(Elm_Object_Item *it)
5011{
5012 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5013 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5014
5015 if (!_it->item->block) return;
5016 if (_it->generation < _it->wd->generation) return;
5017 _it->item->mincalcd = EINA_FALSE;
5018 _it->item->updateme = EINA_TRUE;
5019 _it->item->block->updateme = EINA_TRUE;
5020 if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5021 _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5022}
5023
5024EAPI void
5025elm_genlist_item_fields_update(Elm_Object_Item *it,
5026 const char *parts,
5027 Elm_Genlist_Item_Field_Type itf)
5028{
5029 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5030 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5031
5032 if (!_it->item->block) return;
5033 if (_it->generation < _it->wd->generation) return;
5034
5035 if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_TEXT))
5036 _item_text_realize(_it, VIEW(_it), &_it->texts, parts);
5037 if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_CONTENT))
5038 {
5039 _it->content_objs = _item_content_unrealize(_it, VIEW(_it),
5040 &_it->contents, parts);
5041 _it->content_objs = _item_content_realize(_it, VIEW(_it),
5042 &_it->contents, parts);
5043
5044 if (_it->flipped)
5045 {
5046 _it->item->flip_content_objs =
5047 _item_mode_content_unrealize(_it, VIEW(_it),
5048 &_it->item->flip_contents, parts,
5049 &_it->item->flip_content_objs);
5050 _it->item->flip_content_objs =
5051 _item_mode_content_realize(_it, VIEW(_it),
5052 &_it->item->flip_contents, parts,
5053 &_it->item->flip_content_objs);
5054 }
5055 if (_it->item->deco_it_view)
5056 {
5057 _it->item->deco_it_content_objs =
5058 _item_mode_content_unrealize(_it, _it->item->deco_it_view,
5059 &_it->item->deco_it_contents, parts,
5060 &_it->item->deco_it_content_objs);
5061 _it->item->deco_it_content_objs =
5062 _item_mode_content_realize(_it, _it->item->deco_it_view,
5063 &_it->item->deco_it_contents, parts,
5064 &_it->item->deco_it_content_objs);
5065 }
5066 if (_it->wd->decorate_all_mode)
5067 {
5068 _it->item->deco_all_content_objs =
5069 _item_mode_content_unrealize(_it, _it->deco_all_view,
5070 &_it->item->deco_all_contents, parts,
5071 &_it->item->deco_all_content_objs);
5072 _it->item->deco_all_content_objs =
5073 _item_mode_content_realize(_it, _it->deco_all_view,
5074 &_it->item->deco_all_contents, parts,
5075 &_it->item->deco_all_content_objs);
5076 }
5077 }
5078 if ((!itf) || (itf & ELM_GENLIST_ITEM_FIELD_STATE))
5079 _item_state_realize(_it, VIEW(_it), &_it->states, parts);
5080}
5081
5082EAPI void
5083elm_genlist_item_item_class_update(Elm_Object_Item *it,
5084 const Elm_Genlist_Item_Class *itc)
5085{
5086 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5087 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5088
5089 if (!_it->item->block) return;
5090 EINA_SAFETY_ON_NULL_RETURN(itc);
5091 if (_it->generation < _it->wd->generation) return;
5092 _it->itc = itc;
5093 _it->item->nocache_once = EINA_TRUE;
5094
5095 elm_widget_stringlist_free(_it->texts);
5096 _it->texts = NULL;
5097 elm_widget_stringlist_free(_it->contents);
5098 _it->contents = NULL;
5099 elm_widget_stringlist_free(_it->states);
5100 _it->states = NULL;
5101
5102 if (_it->flipped)
5103 {
5104 elm_widget_stringlist_free(_it->item->flip_contents);
5105 _it->item->flip_contents = NULL;
5106 }
5107 if (_it->item->deco_it_view)
5108 {
5109 elm_widget_stringlist_free(_it->item->deco_it_texts);
5110 _it->item->deco_it_texts = NULL;
5111 elm_widget_stringlist_free(_it->item->deco_it_contents);
5112 _it->item->deco_it_contents = NULL;
5113 }
5114 if (_it->wd->decorate_all_mode)
5115 {
5116 elm_widget_stringlist_free(_it->item->deco_all_texts);
5117 _it->item->deco_all_texts = NULL;
5118 elm_widget_stringlist_free(_it->item->deco_all_contents);
5119 _it->item->deco_all_contents = NULL;
5120 }
5121
5122 elm_genlist_item_update(it);
5123}
5124
5125EAPI const Elm_Genlist_Item_Class *
5126elm_genlist_item_item_class_get(const Elm_Object_Item *it)
5127{
5128 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5129 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5130 if (_it->generation < _it->wd->generation) return NULL;
5131 return _it->itc;
5132}
5133
5134static Evas_Object *
5135_elm_genlist_item_label_create(void *data,
5136 Evas_Object *obj __UNUSED__,
5137 Evas_Object *tooltip,
5138 void *it __UNUSED__)
5139{
5140 Evas_Object *label = elm_label_add(tooltip);
5141 if (!label)
5142 return NULL;
5143 elm_object_style_set(label, "tooltip");
5144 elm_object_text_set(label, data);
5145 return label;
5146}
5147
5148static void
5149_elm_genlist_item_label_del_cb(void *data,
5150 Evas_Object *obj __UNUSED__,
5151 void *event_info __UNUSED__)
5152{
5153 eina_stringshare_del(data);
5154}
5155
5156EAPI void
5157elm_genlist_item_tooltip_text_set(Elm_Object_Item *it,
5158 const char *text)
5159{
5160 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5161 text = eina_stringshare_add(text);
5162 elm_genlist_item_tooltip_content_cb_set(it, _elm_genlist_item_label_create,
5163 text,
5164 _elm_genlist_item_label_del_cb);
5165}
5166
5167EAPI void
5168elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item *it,
5169 Elm_Tooltip_Item_Content_Cb func,
5170 const void *data,
5171 Evas_Smart_Cb del_cb)
5172{
5173 ELM_OBJ_ITEM_CHECK_OR_GOTO(it, error);
5174 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5175
5176 if ((_it->tooltip.content_cb == func) && (_it->tooltip.data == data))
5177 return;
5178
5179 if (_it->tooltip.del_cb)
5180 _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(it), it);
5181
5182 _it->tooltip.content_cb = func;
5183 _it->tooltip.data = data;
5184 _it->tooltip.del_cb = del_cb;
5185
5186 if (VIEW(_it))
5187 {
5188 elm_widget_item_tooltip_content_cb_set(_it,
5189 _it->tooltip.content_cb,
5190 _it->tooltip.data, NULL);
5191 elm_widget_item_tooltip_style_set(_it, _it->tooltip.style);
5192 elm_widget_item_tooltip_window_mode_set(_it, _it->tooltip.free_size);
5193 }
5194
5195 return;
5196
5197error:
5198 if (del_cb) del_cb((void *)data, NULL, NULL);
5199}
5200
5201EAPI void
5202elm_genlist_item_tooltip_unset(Elm_Object_Item *it)
5203{
5204 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5205 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5206
5207 if ((VIEW(_it)) && (_it->tooltip.content_cb))
5208 elm_widget_item_tooltip_unset(_it);
5209
5210 if (_it->tooltip.del_cb)
5211 _it->tooltip.del_cb((void *) _it->tooltip.data, WIDGET(_it), _it);
5212 _it->tooltip.del_cb = NULL;
5213 _it->tooltip.content_cb = NULL;
5214 _it->tooltip.data = NULL;
5215 _it->tooltip.free_size = EINA_FALSE;
5216 if (_it->tooltip.style)
5217 elm_genlist_item_tooltip_style_set(it, NULL);
5218}
5219
5220EAPI void
5221elm_genlist_item_tooltip_style_set(Elm_Object_Item *it,
5222 const char *style)
5223{
5224 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5225 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5226
5227 eina_stringshare_replace(&_it->tooltip.style, style);
5228 if (VIEW(_it)) elm_widget_item_tooltip_style_set(_it, style);
5229}
5230
5231EAPI const char *
5232elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it)
5233{
5234 return elm_object_item_tooltip_style_get(it);
5235}
5236
5237EAPI Eina_Bool
5238elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it,
5239 Eina_Bool disable)
5240{
5241 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5242 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5243
5244 _it->tooltip.free_size = disable;
5245 if (VIEW(_it)) return elm_widget_item_tooltip_window_mode_set(_it, disable);
5246 return EINA_TRUE;
5247}
5248
5249EAPI Eina_Bool
5250elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it)
5251{
5252 return elm_object_tooltip_window_mode_get(VIEW(it));
5253}
5254
5255EAPI void
5256elm_genlist_item_cursor_set(Elm_Object_Item *it,
5257 const char *cursor)
5258{
5259 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5260 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5261 eina_stringshare_replace(&_it->mouse_cursor, cursor);
5262 if (VIEW(_it)) elm_widget_item_cursor_set(_it, cursor);
5263}
5264
5265EAPI const char *
5266elm_genlist_item_cursor_get(const Elm_Object_Item *it)
5267{
5268 return elm_widget_item_cursor_get(it);
5269}
5270
5271EAPI void
5272elm_genlist_item_cursor_unset(Elm_Object_Item *it)
5273{
5274 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5275 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5276
5277 if (!_it->mouse_cursor) return;
5278
5279 if (VIEW(_it)) elm_widget_item_cursor_unset(_it);
5280
5281 eina_stringshare_del(_it->mouse_cursor);
5282 _it->mouse_cursor = NULL;
5283}
5284
5285EAPI void
5286elm_genlist_item_cursor_style_set(Elm_Object_Item *it,
5287 const char *style)
5288{
5289 elm_widget_item_cursor_style_set(it, style);
5290}
5291
5292EAPI const char *
5293elm_genlist_item_cursor_style_get(const Elm_Object_Item *it)
5294{
5295 return elm_widget_item_cursor_style_get(it);
5296}
5297
5298EAPI void
5299elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it,
5300 Eina_Bool engine_only)
5301{
5302 elm_widget_item_cursor_engine_only_set(it, engine_only);
5303}
5304
5305EAPI Eina_Bool
5306elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it)
5307{
5308 return elm_widget_item_cursor_engine_only_get(it);
5309}
5310
5311EAPI int
5312elm_genlist_item_index_get(const Elm_Object_Item *it)
5313{
5314 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
5315 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5316
5317 if (_it->item->block)
5318 return _it->position + (_it->item->block->position * _it->wd->max_items_per_block);
5319 return -1;
5320}
5321
5322EAPI void
5323elm_genlist_mode_set(Evas_Object *obj,
5324 Elm_List_Mode mode)
5325{
5326 ELM_CHECK_WIDTYPE(obj, widtype);
5327 Widget_Data *wd = elm_widget_data_get(obj);
5328 if (!wd) return;
5329 if (wd->mode == mode) return;
5330 wd->mode = mode;
5331 if (wd->mode == ELM_LIST_COMPRESS)
5332 elm_genlist_homogeneous_set(obj, EINA_FALSE);
5333 _sizing_eval(obj);
5334}
5335
5336
5337EAPI Elm_List_Mode
5338elm_genlist_mode_get(const Evas_Object *obj)
5339{
5340 ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
5341 Widget_Data *wd = elm_widget_data_get(obj);
5342 if (!wd) return ELM_LIST_LAST;
5343 return wd->mode;
5344}
5345
5346EAPI void
5347elm_genlist_bounce_set(Evas_Object *obj,
5348 Eina_Bool h_bounce,
5349 Eina_Bool v_bounce)
5350{
5351 ELM_CHECK_WIDTYPE(obj, widtype);
5352 Widget_Data *wd = elm_widget_data_get(obj);
5353 if (!wd) return;
5354 wd->h_bounce = !!h_bounce;
5355 wd->v_bounce = !!v_bounce;
5356 elm_smart_scroller_bounce_allow_set(wd->scr, wd->h_bounce, wd->v_bounce);
5357}
5358
5359EAPI void
5360elm_genlist_bounce_get(const Evas_Object *obj,
5361 Eina_Bool *h_bounce,
5362 Eina_Bool *v_bounce)
5363{
5364 ELM_CHECK_WIDTYPE(obj, widtype);
5365 Widget_Data *wd = elm_widget_data_get(obj);
5366 if (!wd) return;
5367 if (h_bounce) *h_bounce = wd->h_bounce;
5368 if (v_bounce) *v_bounce = wd->v_bounce;
5369}
5370
5371EAPI void
5372elm_genlist_homogeneous_set(Evas_Object *obj,
5373 Eina_Bool homogeneous)
5374{
5375 ELM_CHECK_WIDTYPE(obj, widtype);
5376 Widget_Data *wd = elm_widget_data_get(obj);
5377 if (!wd) return;
5378 wd->homogeneous = !!homogeneous;
5379}
5380
5381EAPI Eina_Bool
5382elm_genlist_homogeneous_get(const Evas_Object *obj)
5383{
5384 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5385 Widget_Data *wd = elm_widget_data_get(obj);
5386 if (!wd) return EINA_FALSE;
5387 return wd->homogeneous;
5388}
5389
5390EAPI void
5391elm_genlist_block_count_set(Evas_Object *obj,
5392 int count)
5393{
5394 ELM_CHECK_WIDTYPE(obj, widtype);
5395 Widget_Data *wd = elm_widget_data_get(obj);
5396 if (!wd) return;
5397 wd->max_items_per_block = count;
5398 wd->item_cache_max = wd->max_items_per_block * 2;
5399 _item_cache_clean(wd);
5400}
5401
5402EAPI int
5403elm_genlist_block_count_get(const Evas_Object *obj)
5404{
5405 ELM_CHECK_WIDTYPE(obj, widtype) 0;
5406 Widget_Data *wd = elm_widget_data_get(obj);
5407 if (!wd) return 0;
5408 return wd->max_items_per_block;
5409}
5410
5411EAPI void
5412elm_genlist_longpress_timeout_set(Evas_Object *obj,
5413 double timeout)
5414{
5415 ELM_CHECK_WIDTYPE(obj, widtype);
5416 Widget_Data *wd = elm_widget_data_get(obj);
5417 if (!wd) return;
5418 wd->longpress_timeout = timeout;
5419}
5420
5421EAPI double
5422elm_genlist_longpress_timeout_get(const Evas_Object *obj)
5423{
5424 ELM_CHECK_WIDTYPE(obj, widtype) 0;
5425 Widget_Data *wd = elm_widget_data_get(obj);
5426 if (!wd) return 0;
5427 return wd->longpress_timeout;
5428}
5429
5430EAPI void
5431elm_genlist_scroller_policy_set(Evas_Object *obj,
5432 Elm_Scroller_Policy policy_h,
5433 Elm_Scroller_Policy policy_v)
5434{
5435 ELM_CHECK_WIDTYPE(obj, widtype);
5436 Widget_Data *wd = elm_widget_data_get(obj);
5437 if ((!wd) || (!wd->scr)) return;
5438 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
5439 (policy_v >= ELM_SCROLLER_POLICY_LAST))
5440 return;
5441 elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
5442}
5443
5444EAPI void
5445elm_genlist_scroller_policy_get(const Evas_Object *obj,
5446 Elm_Scroller_Policy *policy_h,
5447 Elm_Scroller_Policy *policy_v)
5448{
5449 ELM_CHECK_WIDTYPE(obj, widtype);
5450 Widget_Data *wd = elm_widget_data_get(obj);
5451 Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
5452 if ((!wd) || (!wd->scr)) return;
5453 elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
5454 if (policy_h) *policy_h = (Elm_Scroller_Policy)s_policy_h;
5455 if (policy_v) *policy_v = (Elm_Scroller_Policy)s_policy_v;
5456}
5457
5458EAPI void
5459elm_genlist_realized_items_update(Evas_Object *obj)
5460{
5461 ELM_CHECK_WIDTYPE(obj, widtype);
5462
5463 Eina_List *list, *l;
5464 Elm_Object_Item *it;
5465
5466 list = elm_genlist_realized_items_get(obj);
5467 EINA_LIST_FOREACH(list, l, it)
5468 elm_genlist_item_update(it);
5469}
5470
5471EAPI void
5472elm_genlist_item_decorate_mode_set(Elm_Object_Item *it,
5473 const char *decorate_it_type,
5474 Eina_Bool decorate_it_set)
5475{
5476 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5477 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5478
5479 Widget_Data *wd = _it->wd;
5480 Eina_List *l;
5481 Elm_Object_Item *it2;
5482
5483 if (!wd) return;
5484 if (!decorate_it_type) return;
5485 if ((_it->generation < _it->wd->generation) ||
5486 elm_widget_item_disabled_get(_it)) return;
5487 if (wd->decorate_all_mode) return;
5488
5489 if ((wd->mode_item == _it) &&
5490 (!strcmp(decorate_it_type, wd->decorate_it_type)) &&
5491 (decorate_it_set))
5492 return;
5493 if (!_it->itc->decorate_item_style) return;
5494 _it->decorate_it_set = decorate_it_set;
5495
5496 if (wd->multi)
5497 {
5498 EINA_LIST_FOREACH(wd->selected, l, it2)
5499 if (((Elm_Gen_Item *)it2)->realized)
5500 elm_genlist_item_selected_set(it2, EINA_FALSE);
5501 }
5502 else
5503 {
5504 it2 = elm_genlist_selected_item_get(wd->obj);
5505 if ((it2) && (((Elm_Gen_Item *)it2)->realized))
5506 elm_genlist_item_selected_set(it2, EINA_FALSE);
5507 }
5508
5509 if (((wd->decorate_it_type) && (strcmp(decorate_it_type, wd->decorate_it_type))) ||
5510 (decorate_it_set) || ((_it == wd->mode_item) && (!decorate_it_set)))
5511 _decorate_item_unset(wd);
5512
5513 eina_stringshare_replace(&wd->decorate_it_type, decorate_it_type);
5514 if (decorate_it_set) _decorate_item_set(_it);
5515}
5516
5517EAPI const char *
5518elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it)
5519{
5520 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
5521 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5522 return _it->wd->decorate_it_type;
5523}
5524
5525EAPI const Elm_Object_Item *
5526elm_genlist_decorated_item_get(const Evas_Object *obj)
5527{
5528 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5529 Widget_Data *wd = elm_widget_data_get(obj);
5530 if (!wd) return NULL;
5531 return (Elm_Object_Item *) wd->mode_item;
5532}
5533
5534EAPI Eina_Bool
5535elm_genlist_decorate_mode_get(const Evas_Object *obj)
5536{
5537 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5538 Widget_Data *wd = elm_widget_data_get(obj);
5539 if (!wd) return EINA_FALSE;
5540
5541 return wd->decorate_all_mode;
5542}
5543
5544EAPI void
5545elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated)
5546{
5547 ELM_CHECK_WIDTYPE(obj, widtype);
5548 Eina_List *list, *l;
5549 Elm_Gen_Item *it;
5550
5551 Widget_Data *wd = elm_widget_data_get(obj);
5552 if (!wd) return;
5553 decorated = !!decorated;
5554 if (wd->decorate_all_mode == decorated) return;
5555 wd->decorate_all_mode = decorated;
5556
5557 list = elm_genlist_realized_items_get(obj);
5558 if (!wd->decorate_all_mode)
5559 {
5560 EINA_LIST_FOREACH(list, l, it)
5561 {
5562 if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5563 _decorate_all_item_unrealize(it);
5564 }
5565 _item_cache_zero(wd);
5566 }
5567 else
5568 {
5569 EINA_LIST_FOREACH(list, l, it)
5570 {
5571 if (it->item->type != ELM_GENLIST_ITEM_GROUP)
5572 {
5573 if (it->itc->decorate_all_item_style)
5574 _decorate_all_item_realize(it, EINA_TRUE);
5575 }
5576 }
5577 }
5578 if (wd->calc_job) ecore_job_del(wd->calc_job);
5579 wd->calc_job = ecore_job_add(_calc_job, wd);
5580}
5581
5582EAPI void
5583elm_genlist_reorder_mode_set(Evas_Object *obj,
5584 Eina_Bool reorder_mode)
5585{
5586 ELM_CHECK_WIDTYPE(obj, widtype);
5587 Widget_Data *wd = elm_widget_data_get(obj);
5588 if (!wd) return;
5589 wd->reorder_mode = !!reorder_mode;
5590}
5591
5592EAPI Eina_Bool
5593elm_genlist_reorder_mode_get(const Evas_Object *obj)
5594{
5595 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5596 Widget_Data *wd = elm_widget_data_get(obj);
5597 if (!wd) return EINA_FALSE;
5598 return wd->reorder_mode;
5599}
5600
5601EAPI Elm_Genlist_Item_Type
5602elm_genlist_item_type_get(const Elm_Object_Item *it)
5603{
5604 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_GENLIST_ITEM_MAX);
5605 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5606 return _it->item->type;
5607}
5608
5609EAPI Elm_Genlist_Item_Class *
5610elm_genlist_item_class_new(void)
5611{
5612 Elm_Genlist_Item_Class *itc;
5613
5614 itc = calloc(1, sizeof(Elm_Genlist_Item_Class));
5615 if (!itc)
5616 return NULL;
5617 itc->version = CLASS_ALLOCATED;
5618 itc->refcount = 1;
5619 itc->delete_me = EINA_FALSE;
5620
5621 return itc;
5622}
5623
5624EAPI void
5625elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc)
5626{
5627 if (itc && (itc->version == CLASS_ALLOCATED))
5628 {
5629 if (!itc->delete_me) itc->delete_me = EINA_TRUE;
5630 if (itc->refcount > 0) elm_genlist_item_class_unref(itc);
5631 else
5632 {
5633 itc->version = 0;
5634 free(itc);
5635 }
5636 }
5637}
5638
5639EAPI void
5640elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc)
5641{
5642 if (itc && (itc->version == CLASS_ALLOCATED))
5643 {
5644 itc->refcount++;
5645 if (itc->refcount == 0) itc->refcount--;
5646 }
5647}
5648
5649EAPI void
5650elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc)
5651{
5652 if (itc && (itc->version == CLASS_ALLOCATED))
5653 {
5654 if (itc->refcount > 0) itc->refcount--;
5655 if (itc->delete_me && (!itc->refcount))
5656 elm_genlist_item_class_free(itc);
5657 }
5658}
5659
5660void _flip_job(void *data)
5661{
5662 Elm_Gen_Item *it = (Elm_Gen_Item *) data;
5663 _item_unhighlight(it);
5664 _item_unselect(it);
5665 _elm_genlist_item_unrealize(it, EINA_FALSE);
5666 it->flipped = EINA_TRUE;
5667 it->item->nocache = EINA_TRUE;
5668 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5669 it->wd->calc_job = ecore_job_add(_calc_job, it->wd);
5670}
5671
5672EAPI void
5673elm_genlist_item_flip_set(Elm_Object_Item *it,
5674 Eina_Bool flip)
5675{
5676 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5677 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5678
5679 flip = !!flip;
5680 if (_it->flipped == flip) return;
5681
5682 if (flip)
5683 {
5684 ecore_job_add(_flip_job, _it);
5685 }
5686 else
5687 {
5688 _it->flipped = flip;
5689 _item_cache_zero(_it->wd);
5690 elm_genlist_item_update(it);
5691 _it->item->nocache = EINA_FALSE;
5692 }
5693}
5694
5695EAPI Eina_Bool
5696elm_genlist_item_flip_get(const Elm_Object_Item *it)
5697{
5698 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
5699 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5700 return _it->flipped;
5701}
5702
5703EAPI void
5704elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
5705{
5706 ELM_CHECK_WIDTYPE(obj, widtype);
5707 Widget_Data *wd = elm_widget_data_get(obj);
5708 if (!wd) return;
5709 if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5710 return;
5711 if (wd->select_mode != mode)
5712 wd->select_mode = mode;
5713}
5714
5715EAPI Elm_Object_Select_Mode
5716elm_genlist_select_mode_get(const Evas_Object *obj)
5717{
5718 ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
5719 Widget_Data *wd = elm_widget_data_get(obj);
5720 if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
5721 return wd->select_mode;
5722}
5723
5724EAPI void
5725elm_genlist_highlight_mode_set(Evas_Object *obj,
5726 Eina_Bool highlight)
5727{
5728 ELM_CHECK_WIDTYPE(obj, widtype);
5729 Widget_Data *wd = elm_widget_data_get(obj);
5730 if (!wd) return;
5731 wd->highlight = !!highlight;
5732}
5733
5734EAPI Eina_Bool
5735elm_genlist_highlight_mode_get(const Evas_Object *obj)
5736{
5737 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5738 Widget_Data *wd = elm_widget_data_get(obj);
5739 if (!wd) return EINA_FALSE;
5740 return wd->highlight;
5741}
5742
5743EAPI void
5744elm_genlist_item_select_mode_set(Elm_Object_Item *it,
5745 Elm_Object_Select_Mode mode)
5746{
5747 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
5748 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5749 if (!_it) return;
5750 if (_it->generation < _it->wd->generation) return;
5751 if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
5752 return;
5753 if (_it->select_mode != mode)
5754 _it->select_mode = mode;
5755
5756 if (_it->select_mode == ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY)
5757 {
5758 _it->item->mincalcd = EINA_FALSE;
5759 _it->item->updateme = EINA_TRUE;
5760 if (_it->item->block) _it->item->block->updateme = EINA_TRUE;
5761 if (_it->wd->update_job) ecore_job_del(_it->wd->update_job);
5762 _it->wd->update_job = ecore_job_add(_update_job, _it->wd);
5763 }
5764}
5765
5766EAPI Elm_Object_Select_Mode
5767elm_genlist_item_select_mode_get(const Elm_Object_Item *it)
5768{
5769 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ELM_OBJECT_SELECT_MODE_MAX);
5770 Elm_Gen_Item *_it = (Elm_Gen_Item *)it;
5771 if (!_it) return ELM_OBJECT_SELECT_MODE_MAX;
5772 return _it->select_mode;
5773}
5774
5775/* for gengrid as of now */
5776void
5777_elm_genlist_page_relative_set(Evas_Object *obj,
5778 double h_pagerel,
5779 double v_pagerel)
5780{
5781 Evas_Coord pagesize_h;
5782 Evas_Coord pagesize_v;
5783
5784 ELM_CHECK_WIDTYPE(obj, widtype);
5785 Widget_Data *wd = elm_widget_data_get(obj);
5786 if (!wd) return;
5787
5788 elm_smart_scroller_paging_get(wd->scr, NULL, NULL, &pagesize_h, &pagesize_v);
5789 elm_smart_scroller_paging_set(wd->scr, h_pagerel, v_pagerel, pagesize_h,
5790 pagesize_v);
5791}
5792
5793/* for gengrid as of now */
5794void
5795_elm_genlist_page_relative_get(const Evas_Object *obj,
5796 double *h_pagerel,
5797 double *v_pagerel)
5798{
5799 ELM_CHECK_WIDTYPE(obj, widtype);
5800 Widget_Data *wd = elm_widget_data_get(obj);
5801 if (!wd) return;
5802
5803 elm_smart_scroller_paging_get(wd->scr, h_pagerel, v_pagerel, NULL, NULL);
5804}
5805
5806/* for gengrid as of now */
5807void
5808_elm_genlist_page_size_set(Evas_Object *obj,
5809 Evas_Coord h_pagesize,
5810 Evas_Coord v_pagesize)
5811{
5812 double pagerel_h;
5813 double pagerel_v;
5814
5815 ELM_CHECK_WIDTYPE(obj, widtype);
5816 Widget_Data *wd = elm_widget_data_get(obj);
5817 if (!wd) return;
5818 elm_smart_scroller_paging_get(wd->scr, &pagerel_h, &pagerel_v, NULL, NULL);
5819 elm_smart_scroller_paging_set(wd->scr, pagerel_h, pagerel_v, h_pagesize,
5820 v_pagesize);
5821}
5822
5823/* for gengrid as of now */
5824void
5825_elm_genlist_current_page_get(const Evas_Object *obj,
5826 int *h_pagenumber,
5827 int *v_pagenumber)
5828{
5829 ELM_CHECK_WIDTYPE(obj, widtype);
5830 Widget_Data *wd = elm_widget_data_get(obj);
5831 if (!wd) return;
5832 elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
5833}
5834
5835/* for gengrid as of now */
5836void
5837_elm_genlist_last_page_get(const Evas_Object *obj,
5838 int *h_pagenumber,
5839 int *v_pagenumber)
5840{
5841 ELM_CHECK_WIDTYPE(obj, widtype);
5842 Widget_Data *wd = elm_widget_data_get(obj);
5843 if (!wd) return;
5844 elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
5845}
5846
5847/* for gengrid as of now */
5848void
5849_elm_genlist_page_show(const Evas_Object *obj,
5850 int h_pagenumber,
5851 int v_pagenumber)
5852{
5853 ELM_CHECK_WIDTYPE(obj, widtype);
5854 Widget_Data *wd = elm_widget_data_get(obj);
5855 if (!wd) return;
5856 elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
5857}
5858
5859/* for gengrid as of now */
5860void
5861_elm_genlist_page_bring_in(const Evas_Object *obj,
5862 int h_pagenumber,
5863 int v_pagenumber)
5864{
5865 ELM_CHECK_WIDTYPE(obj, widtype);
5866 Widget_Data *wd = elm_widget_data_get(obj);
5867 if (!wd) return;
5868 elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
5869}
5870
5871void
5872_elm_genlist_item_unrealize(Elm_Gen_Item *it,
5873 Eina_Bool calc)
5874{
5875 Evas_Object *content;
5876
5877 if (!it->realized) return;
5878 if (it->wd->reorder_it == it) return;
5879
5880 evas_event_freeze(evas_object_evas_get(WIDGET(it)));
5881 if (!calc)
5882 evas_object_smart_callback_call(WIDGET(it), SIG_UNREALIZED, it);
5883 if (it->long_timer)
5884 {
5885 ecore_timer_del(it->long_timer);
5886 it->long_timer = NULL;
5887 }
5888
5889 elm_widget_stringlist_free(it->texts);
5890 it->texts = NULL;
5891 elm_widget_stringlist_free(it->contents);
5892 it->contents = NULL;
5893 elm_widget_stringlist_free(it->states);
5894 it->states = NULL;
5895 EINA_LIST_FREE(it->content_objs, content)
5896 evas_object_del(content);
5897
5898 it->unrealize_cb(it);
5899
5900 it->realized = EINA_FALSE;
5901 it->want_unrealize = EINA_FALSE;
5902 evas_event_thaw(evas_object_evas_get(WIDGET(it)));
5903 evas_event_thaw_eval(evas_object_evas_get(WIDGET(it)));
5904}
5905
5906void
5907_elm_genlist_item_del_notserious(Elm_Gen_Item *it)
5908{
5909 elm_widget_item_pre_notify_del(it);
5910 it->generation = it->wd->generation - 1; /* This means that the item is deleted */
5911
5912 if ((it->relcount > 0) || (it->walking > 0)) return;
5913
5914 if (it->selected) it->wd->selected = eina_list_remove(it->wd->selected, it);
5915
5916 if (it->itc->func.del)
5917 it->itc->func.del((void *)it->base.data, WIDGET(it));
5918}
5919
5920void
5921_elm_genlist_item_del_serious(Elm_Gen_Item *it)
5922{
5923 _elm_genlist_item_del_notserious(it);
5924 it->wd->items = eina_inlist_remove(it->wd->items, EINA_INLIST_GET(it));
5925 if (it->tooltip.del_cb)
5926 it->tooltip.del_cb((void *)it->tooltip.data, WIDGET(it), it);
5927 it->wd->walking -= it->walking;
5928 if (it->long_timer)
5929 {
5930 ecore_timer_del(it->long_timer);
5931 it->long_timer = NULL;
5932 }
5933 if (it->group)
5934 it->wd->group_items = eina_list_remove(it->wd->group_items, it);
5935
5936 if (it->wd->state)
5937 {
5938 eina_inlist_sorted_state_free(it->wd->state);
5939 it->wd->state = NULL;
5940 }
5941 if (it->wd->calc_job) ecore_job_del(it->wd->calc_job);
5942 it->wd->calc_job = ecore_job_add(it->wd->calc_cb, it->wd);
5943 free(it->item);
5944
5945 it->item = NULL;
5946 if (it->wd->last_selected_item == (Elm_Object_Item *)it)
5947 it->wd->last_selected_item = NULL;
5948 it->wd->item_count--;
5949}
5950
5951EAPI void
5952elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled)
5953{
5954 ELM_CHECK_WIDTYPE(obj, widtype);
5955 Widget_Data *wd = elm_widget_data_get(obj);
5956 if (!wd) return;
5957 wd->tree_effect_enabled = !!enabled;
5958}
5959
5960EAPI Eina_Bool
5961elm_genlist_tree_effect_enabled_get(const Evas_Object *obj)
5962{
5963 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
5964 Widget_Data *wd = elm_widget_data_get(obj);
5965 if (!wd) return EINA_FALSE;
5966 return wd->tree_effect_enabled;
5967}
5968
5969static Evas_Object*
5970_create_tray_alpha_bg(const Evas_Object *obj)
5971{
5972 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5973 Widget_Data *wd = elm_widget_data_get(obj);
5974 if (!wd) return NULL;
5975
5976 Evas_Object *bg = NULL;
5977 Evas_Coord ox, oy, ow, oh;
5978
5979 evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
5980 bg = evas_object_rectangle_add(evas_object_evas_get(wd->obj));
5981 evas_object_color_set(bg,0,0,0,0);
5982 evas_object_resize(bg , ow, oh);
5983 evas_object_move(bg , ox, oy);
5984 return bg ;
5985}
5986
5987static void
5988_item_contract_emit(Elm_Gen_Item *it)
5989{
5990 Elm_Gen_Item *it2;
5991 Eina_List *l;
5992
5993 edje_object_signal_emit(VIEW(it), "elm,state,contract_flip", "");
5994 it->item->tree_effect_finished = EINA_FALSE;
5995
5996 EINA_LIST_FOREACH(it->item->items, l, it2)
5997 if (it2) _item_contract_emit(it2);
5998}
5999
6000static int
6001_item_tree_effect_before(Elm_Gen_Item *it)
6002{
6003 Elm_Gen_Item *it2;
6004 Eina_List *l;
6005
6006 EINA_LIST_FOREACH(it->item->items, l, it2)
6007 {
6008 if (it2->parent && (it == it2->parent))
6009 {
6010 if (!it2->realized)
6011 it2->item->tree_effect_hideme = EINA_TRUE;
6012 if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6013 edje_object_signal_emit(VIEW(it2), "elm,state,hide", "");
6014 else if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6015 _item_contract_emit(it2);
6016 }
6017 }
6018 return ECORE_CALLBACK_CANCEL;
6019}
6020
6021static void
6022_item_tree_effect(Widget_Data *wd, int y)
6023{
6024 Elm_Gen_Item *it = NULL, *expanded_next_it;
6025
6026 expanded_next_it = wd->expanded_next_item;
6027
6028 if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6029 {
6030 it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6031 while (it)
6032 {
6033 if (it->item->expanded_depth <= expanded_next_it->item->expanded_depth) break;
6034 if (it->item->scrl_y && (it->item->scrl_y <= expanded_next_it->item->old_scrl_y + y) &&
6035 (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6036 {
6037 if (!it->item->tree_effect_finished)
6038 {
6039 edje_object_signal_emit(VIEW(it), "flip_item", "");
6040 _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6041 it->item->tree_effect_finished = EINA_TRUE;
6042 }
6043 }
6044 it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6045 }
6046 }
6047 else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6048 {
6049 it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) expanded_next_it);
6050 while (it)
6051 {
6052 if ((it->item->scrl_y > expanded_next_it->item->old_scrl_y + y) &&
6053 (it->item->expanded_depth > expanded_next_it->item->expanded_depth))
6054 {
6055 if (!it->item->tree_effect_finished)
6056 {
6057 edje_object_signal_emit(VIEW(it), "elm,state,hide", "");
6058 it->item->tree_effect_finished = EINA_TRUE;
6059 }
6060 }
6061 else
6062 break;
6063 it = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it);
6064 }
6065 }
6066}
6067
6068static void
6069_item_tree_effect_finish(Widget_Data *wd)
6070{
6071 Elm_Gen_Item *it = NULL;
6072 const Eina_List *l;
6073
6074 if (wd->tree_effect_animator)
6075 {
6076 if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6077 _item_subitems_clear(wd->expanded_item);
6078 EINA_LIST_FOREACH(wd->expanded_item->item->items, l, it)
6079 {
6080 it->item->tree_effect_finished = EINA_TRUE;
6081 it->item->old_scrl_y = it->item->scrl_y;
6082 if (it->wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6083 edje_object_signal_emit(VIEW(it), "elm,state,show", "");
6084 }
6085 }
6086 _item_auto_scroll(wd);
6087 evas_object_lower(wd->alpha_bg);
6088 evas_object_hide(wd->alpha_bg);
6089 wd->move_effect_mode = ELM_GENLIST_TREE_EFFECT_NONE;
6090 if (wd->move_items) wd->move_items = eina_list_free(wd->move_items);
6091
6092 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
6093 evas_object_smart_callback_call(wd->obj, SIG_TREE_EFFECT_FINISHED, NULL);
6094 evas_object_smart_changed(wd->pan_smart);
6095
6096 wd->tree_effect_animator = NULL;
6097}
6098
6099static Eina_Bool
6100_tree_effect_animator_cb(void *data)
6101{
6102 Widget_Data *wd = data;
6103 if (!wd) return ECORE_CALLBACK_CANCEL;
6104 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh;
6105 Elm_Gen_Item *it = NULL, *it2, *expanded_next_it;
6106 const Eina_List *l;
6107 double effect_duration = 0.3, t;
6108 int y = 0, dy = 0, dh = 0;
6109 Eina_Bool end = EINA_FALSE, vis = EINA_TRUE;
6110 int in = 0;
6111
6112 t = ((0.0 > (t = ecore_time_get() - wd->start_time)) ? 0.0 : t);
6113 evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
6114 evas_output_viewport_get(evas_object_evas_get(wd->pan_smart), &cvx, &cvy, &cvw, &cvh);
6115 if (t > effect_duration) end = EINA_TRUE;
6116
6117 // Below while statement is needed, when the genlist is resized.
6118 it2 = wd->expanded_item;
6119 while (it2 && vis)
6120 {
6121 evas_object_move(VIEW(it2), it2->item->scrl_x, it2->item->scrl_y);
6122 vis = (ELM_RECTS_INTERSECT(it2->item->scrl_x, it2->item->scrl_y, it2->item->w, it2->item->h,
6123 cvx, cvy, cvw, cvh));
6124 it2 = (Elm_Gen_Item *) elm_genlist_item_prev_get((Elm_Object_Item *) it2);
6125 }
6126
6127 if (wd->expanded_next_item)
6128 {
6129 expanded_next_it = wd->expanded_next_item;
6130
6131 /* move items */
6132 EINA_LIST_FOREACH(wd->move_items, l, it)
6133 {
6134 if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6135 {
6136 expanded_next_it->item->old_scrl_y = wd->expanded_item->item->old_scrl_y + wd->expanded_item->item->h;
6137 if (expanded_next_it->item->scrl_y <= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6138 expanded_next_it->item->scrl_y = cvy + cvh;
6139
6140 dy = ((expanded_next_it->item->scrl_y >= (cvy + cvh)) ?
6141 cvy + cvh : expanded_next_it->item->scrl_y) -
6142 expanded_next_it->item->old_scrl_y;
6143 }
6144 else if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_CONTRACT)
6145 {
6146 if (expanded_next_it->item->scrl_y >= expanded_next_it->item->old_scrl_y) //did not calculate next item position
6147 expanded_next_it->item->old_scrl_y = cvy + cvh;
6148
6149 if (expanded_next_it->item->old_scrl_y > (cvy + cvh))
6150 {
6151 dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6152 cvy + cvh;
6153 expanded_next_it->item->old_scrl_y = cvy + cvh;
6154 }
6155 else
6156 {
6157 dy = (wd->expanded_item->item->scrl_y + wd->expanded_item->item->h) -
6158 expanded_next_it->item->old_scrl_y;
6159 }
6160 }
6161
6162 if (t <= effect_duration)
6163 {
6164 y = ((1 - (1 - (t / effect_duration)) * (1 - (t /effect_duration))) * dy);
6165 }
6166 else
6167 {
6168 end = EINA_TRUE;
6169 y = dy;
6170 }
6171
6172 if (!it->realized)
6173 {
6174 _item_realize(it, in, 0);
6175 }
6176 in++;
6177
6178 if (it != expanded_next_it)
6179 {
6180 it->item->old_scrl_y = expanded_next_it->item->old_scrl_y + expanded_next_it->item->h + dh;
6181 dh += it->item->h;
6182 }
6183
6184 if ((it->item->old_scrl_y + y) < (cvy + cvh))
6185 _item_position(it, VIEW(it),it->item->scrl_x, it->item->old_scrl_y + y);
6186 }
6187 /* tree effect */
6188 _item_tree_effect(wd, y);
6189 }
6190 else
6191 {
6192 int expanded_item_num = 0;
6193 int num = 0;
6194
6195 if (wd->expanded_item)
6196 it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) wd->expanded_item);
6197
6198 it2 = it;
6199 while (it2)
6200 {
6201 expanded_item_num++;
6202 it2 = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it2);
6203 }
6204
6205 while (it)
6206 {
6207 num++;
6208 if (wd->expanded_item->item->expanded_depth >= it->item->expanded_depth) break;
6209 if (wd->move_effect_mode == ELM_GENLIST_TREE_EFFECT_EXPAND)
6210 {
6211 if (!it->item->tree_effect_finished)
6212 {
6213 if (t >= (((num - 1) * effect_duration) / expanded_item_num))
6214 {
6215 edje_object_signal_emit(VIEW(it), "flip_item", "");
6216 _item_position(it, VIEW(it), it->item->scrl_x, it->item->scrl_y);
6217 it->item->tree_effect_finished = EINA_TRUE;
6218 }
6219 }
6220 }
6221 it = (Elm_Gen_Item *) elm_genlist_item_next_get((Elm_Object_Item *) it);
6222 }
6223 }
6224
6225 if (end)
6226 {
6227 _item_tree_effect_finish(wd);
6228 return ECORE_CALLBACK_CANCEL;
6229 }
6230 return ECORE_CALLBACK_RENEW;
6231}
diff --git a/libraries/elementary/src/lib/elm_genlist.h b/libraries/elementary/src/lib/elm_genlist.h
new file mode 100644
index 0000000..7b94b5d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_genlist.h
@@ -0,0 +1,1874 @@
1/**
2 * @defgroup Genlist Genlist
3 * @ingroup Elementary
4 *
5 * @image html img/widget/genlist/preview-00.png
6 * @image latex img/widget/genlist/preview-00.eps
7 * @image html img/genlist.png
8 * @image latex img/genlist.eps
9 *
10 * This widget aims to have more expansive list than the simple list in
11 * Elementary that could have more flexible items and allow many more entries
12 * while still being fast and low on memory usage. At the same time it was
13 * also made to be able to do tree structures. But the price to pay is more
14 * complexity when it comes to usage. If all you want is a simple list with
15 * icons and a single text, use the normal @ref List object.
16 *
17 * Genlist has a fairly large API, mostly because it's relatively complex,
18 * trying to be both expansive, powerful and efficient. First we will begin
19 * an overview on the theory behind genlist.
20 *
21 * @section Genlist_Item_Class Genlist item classes - creating items
22 *
23 * In order to have the ability to add and delete items on the fly, genlist
24 * implements a class (callback) system where the application provides a
25 * structure with information about that type of item (genlist may contain
26 * multiple different items with different classes, states and styles).
27 * Genlist will call the functions in this struct (methods) when an item is
28 * "realized" (i.e., created dynamically, while the user is scrolling the
29 * grid). All objects will simply be deleted when no longer needed with
30 * evas_object_del(). The #Elm_Genlist_Item_Class structure contains the
31 * following members:
32 * - @c item_style - This is a constant string and simply defines the name
33 * of the item style. It @b must be specified and the default should be @c
34 * "default".
35 * - @c decorate_item_style - This is a constant string and simply defines the name
36 * of the decorate mode item style. It is used to specify decorate mode item style. It can be
37 * used when you call elm_genlist_item_decorate_mode_set().
38 * - @c decorate_all_item_style - This is a constant string and simply defines the name
39 * of the decorate all item style. It is used to specify decorate all item style. It can be
40 * used to set selection, checking and deletion mode. This is used when you
41 * call elm_genlist_decorate_mode_set().
42 * - @c func - A struct with pointers to functions that will be called when
43 * an item is going to be actually created. All of them receive a @c data
44 * parameter that will point to the same data passed to
45 * elm_genlist_item_append() and related item creation functions, and an @c
46 * obj parameter that points to the genlist object itself.
47 *
48 * The function pointers inside @c func are @c text_get, @c content_get, @c
49 * state_get and @c del. The 3 first functions also receive a @c part
50 * parameter described below. A brief description of these functions follows:
51 *
52 * - @c text_get - The @c part parameter is the name string of one of the
53 * existing text parts in the Edje group implementing the item's theme.
54 * This function @b must return a strdup'()ed string, as the caller will
55 * free() it when done. See #Elm_Genlist_Item_Text_Get_Cb.
56 * - @c content_get - The @c part parameter is the name string of one of the
57 * existing (content) swallow parts in the Edje group implementing the item's
58 * theme. It must return @c NULL, when no content is desired, or a valid
59 * object handle, otherwise. The object will be deleted by the genlist on
60 * its deletion or when the item is "unrealized". See
61 * #Elm_Genlist_Item_Content_Get_Cb.
62 * - @c func.state_get - The @c part parameter is the name string of one of
63 * the state parts in the Edje group implementing the item's theme. Return
64 * @c EINA_FALSE for false/off or @c EINA_TRUE for true/on. Genlists will
65 * emit a signal to its theming Edje object with @c "elm,state,xxx,active"
66 * and @c "elm" as "emission" and "source" arguments, respectively, when
67 * the state is true (the default is false), where @c xxx is the name of
68 * the (state) part. See #Elm_Genlist_Item_State_Get_Cb.
69 * - @c func.del - This is intended for use when genlist items are deleted,
70 * so any data attached to the item (e.g. its data parameter on creation)
71 * can be deleted. See #Elm_Genlist_Item_Del_Cb.
72 *
73 * available item styles:
74 * - default
75 * - default_style - The text part is a textblock
76 *
77 * @image html img/widget/genlist/preview-04.png
78 * @image latex img/widget/genlist/preview-04.eps
79 *
80 * - double_label
81 *
82 * @image html img/widget/genlist/preview-01.png
83 * @image latex img/widget/genlist/preview-01.eps
84 *
85 * - icon_top_text_bottom
86 *
87 * @image html img/widget/genlist/preview-02.png
88 * @image latex img/widget/genlist/preview-02.eps
89 *
90 * - group_index
91 *
92 * @image html img/widget/genlist/preview-03.png
93 * @image latex img/widget/genlist/preview-03.eps
94 *
95 * @section Genlist_Items Structure of items
96 *
97 * An item in a genlist can have 0 or more texts (they can be regular
98 * text or textblock Evas objects - that's up to the style to determine), 0
99 * or more contents (which are simply objects swallowed into the genlist item's
100 * theming Edje object) and 0 or more <b>boolean states</b>, which have the
101 * behavior left to the user to define. The Edje part names for each of
102 * these properties will be looked up, in the theme file for the genlist,
103 * under the Edje (string) data items named @c "labels", @c "contents" and @c
104 * "states", respectively. For each of those properties, if more than one
105 * part is provided, they must have names listed separated by spaces in the
106 * data fields. For the default genlist item theme, we have @b one text
107 * part (@c "elm.text"), @b two content parts (@c "elm.swalllow.icon" and @c
108 * "elm.swallow.end") and @b no state parts.
109 *
110 * A genlist item may be at one of several styles. Elementary provides one
111 * by default - "default", but this can be extended by system or application
112 * custom themes/overlays/extensions (see @ref Theme "themes" for more
113 * details).
114 *
115 * @section Genlist_Manipulation Editing and Navigating
116 *
117 * Items can be added by several calls. All of them return a @ref
118 * Elm_Object_Item handle that is an internal member inside the genlist.
119 * They all take a data parameter that is meant to be used for a handle to
120 * the applications internal data (eg. the struct with the original item
121 * data). The parent parameter is the parent genlist item this belongs to if
122 * it is a tree or an indexed group, and NULL if there is no parent. The
123 * flags can be a bitmask of #ELM_GENLIST_ITEM_NONE,
124 * #ELM_GENLIST_ITEM_TREE and #ELM_GENLIST_ITEM_GROUP. If
125 * #ELM_GENLIST_ITEM_TREE is set then this item is displayed as an item
126 * that is able to expand and have child items. If ELM_GENLIST_ITEM_GROUP
127 * is set then this item is group index item that is displayed at the top
128 * until the next group comes. The func parameter is a convenience callback
129 * that is called when the item is selected and the data parameter will be
130 * the func_data parameter, obj be the genlist object and event_info will be
131 * the genlist item.
132 *
133 * elm_genlist_item_append() adds an item to the end of the list, or if
134 * there is a parent, to the end of all the child items of the parent.
135 * elm_genlist_item_prepend() is the same but adds to the beginning of
136 * the list or children list. elm_genlist_item_insert_before() inserts at
137 * item before another item and elm_genlist_item_insert_after() inserts after
138 * the indicated item.
139 *
140 * The application can clear the list with elm_genlist_clear() which deletes
141 * all the items in the list and elm_object_item_del() will delete a specific
142 * item. elm_genlist_item_subitems_clear() will clear all items that are
143 * children of the indicated parent item.
144 *
145 * To help inspect list items you can jump to the item at the top of the list
146 * with elm_genlist_first_item_get() which will return the item pointer, and
147 * similarly elm_genlist_last_item_get() gets the item at the end of the list.
148 * elm_genlist_item_next_get() and elm_genlist_item_prev_get() get the next
149 * and previous items respectively relative to the indicated item. Using
150 * these calls you can walk the entire item list/tree. Note that as a tree
151 * the items are flattened in the list, so elm_genlist_item_parent_get() will
152 * let you know which item is the parent (and thus know how to skip them if
153 * wanted).
154 *
155 * @section Genlist_Multi_Selection Multi-selection
156 *
157 * If the application wants multiple items to be able to be selected,
158 * elm_genlist_multi_select_set() can enable this. If the list is
159 * single-selection only (the default), then elm_genlist_selected_item_get()
160 * will return the selected item, if any, or NULL if none is selected. If the
161 * list is multi-select then elm_genlist_selected_items_get() will return a
162 * list (that is only valid as long as no items are modified (added, deleted,
163 * selected or unselected)).
164 *
165 * @section Genlist_Usage_Hints Usage hints
166 *
167 * There are also convenience functions. elm_object_item_widget_get() will
168 * return the genlist object the item belongs to. elm_genlist_item_show()
169 * will make the scroller scroll to show that specific item so its visible.
170 * elm_object_item_data_get() returns the data pointer set by the item
171 * creation functions.
172 *
173 * If an item changes (state of boolean changes, text or contents change),
174 * then use elm_genlist_item_update() to have genlist update the item with
175 * the new state. Genlist will re-realize the item and thus call the functions
176 * in the _Elm_Genlist_Item_Class for that item.
177 *
178 * To programmatically (un)select an item use elm_genlist_item_selected_set().
179 * To get its selected state use elm_genlist_item_selected_get(). Similarly
180 * to expand/contract an item and get its expanded state, use
181 * elm_genlist_item_expanded_set() and elm_genlist_item_expanded_get(). And
182 * again to make an item disabled (unable to be selected and appear
183 * differently) use elm_object_item_disabled_set() to set this and
184 * elm_object_item_disabled_get() to get the disabled state.
185 *
186 * In general to indicate how the genlist should expand items horizontally to
187 * fill the list area, use elm_genlist_mode_set(). Valid modes are
188 * ELM_LIST_LIMIT and ELM_LIST_SCROLL. The default is ELM_LIST_SCROLL. This
189 * mode means that if items are too wide to fit, the scroller will scroll
190 * horizontally. Otherwise items are expanded to fill the width of the
191 * viewport of the scroller. If it is ELM_LIST_LIMIT, items will be expanded
192 * to the viewport width and limited to that size. This can be combined with
193 * a different style that uses edjes' ellipsis feature (cutting text off like
194 * this: "tex...").
195 *
196 * Items will only call their selection func and callback when first becoming
197 * selected. Any further clicks will do nothing, unless you enable always
198 * select with elm_genlist_select_mode_set() as ELM_OBJECT_SELECT_MODE_ALWAYS.
199 * This means even if selected, every click will make the selected callbacks
200 * be called. elm_genlist_select_mode_set() as ELM_OBJECT_SELECT_MODE_NONE will
201 * turn off the ability to select items entirely and they will neither
202 * appear selected nor call selected callback functions.
203 *
204 * Remember that you can create new styles and add your own theme augmentation
205 * per application with elm_theme_extension_add(). If you absolutely must
206 * have a specific style that overrides any theme the user or system sets up
207 * you can use elm_theme_overlay_add() to add such a file.
208 *
209 * @section Genlist_Implementation Implementation
210 *
211 * Evas tracks every object you create. Every time it processes an event
212 * (mouse move, down, up etc.) it needs to walk through objects and find out
213 * what event that affects. Even worse every time it renders display updates,
214 * in order to just calculate what to re-draw, it needs to walk through many
215 * many many objects. Thus, the more objects you keep active, the more
216 * overhead Evas has in just doing its work. It is advisable to keep your
217 * active objects to the minimum working set you need. Also remember that
218 * object creation and deletion carries an overhead, so there is a
219 * middle-ground, which is not easily determined. But don't keep massive lists
220 * of objects you can't see or use. Genlist does this with list objects. It
221 * creates and destroys them dynamically as you scroll around. It groups them
222 * into blocks so it can determine the visibility etc. of a whole block at
223 * once as opposed to having to walk the whole list. This 2-level list allows
224 * for very large numbers of items to be in the list (tests have used up to
225 * 2,000,000 items). Also genlist employs a queue for adding items. As items
226 * may be different sizes, every item added needs to be calculated as to its
227 * size and thus this presents a lot of overhead on populating the list, this
228 * genlist employs a queue. Any item added is queued and spooled off over
229 * time, actually appearing some time later, so if your list has many members
230 * you may find it takes a while for them to all appear, with your process
231 * consuming a lot of CPU while it is busy spooling.
232 *
233 * Genlist also implements a tree structure, but it does so with callbacks to
234 * the application, with the application filling in tree structures when
235 * requested (allowing for efficient building of a very deep tree that could
236 * even be used for file-management). See the above smart signal callbacks for
237 * details.
238 *
239 * @section Genlist_Smart_Events Genlist smart events
240 *
241 * Signals that you can add callbacks for are:
242 * - @c "activated" - The user has double-clicked or pressed
243 * (enter|return|spacebar) on an item. The @c event_info parameter is the
244 * item that was activated.
245 * - @c "clicked,double" - The user has double-clicked an item. The @c
246 * event_info parameter is the item that was double-clicked.
247 * - @c "selected" - This is called when a user has made an item selected.
248 * The event_info parameter is the genlist item that was selected.
249 * - @c "unselected" - This is called when a user has made an item
250 * unselected. The event_info parameter is the genlist item that was
251 * unselected.
252 * - @c "expanded" - This is called when elm_genlist_item_expanded_set() is
253 * called and the item is now meant to be expanded. The event_info
254 * parameter is the genlist item that was indicated to expand. It is the
255 * job of this callback to then fill in the child items.
256 * - @c "contracted" - This is called when elm_genlist_item_expanded_set() is
257 * called and the item is now meant to be contracted. The event_info
258 * parameter is the genlist item that was indicated to contract. It is the
259 * job of this callback to then delete the child items.
260 * - @c "expand,request" - This is called when a user has indicated they want
261 * to expand a tree branch item. The callback should decide if the item can
262 * expand (has any children) and then call elm_genlist_item_expanded_set()
263 * appropriately to set the state. The event_info parameter is the genlist
264 * item that was indicated to expand.
265 * - @c "contract,request" - This is called when a user has indicated they
266 * want to contract a tree branch item. The callback should decide if the
267 * item can contract (has any children) and then call
268 * elm_genlist_item_expanded_set() appropriately to set the state. The
269 * event_info parameter is the genlist item that was indicated to contract.
270 * - @c "realized" - This is called when the item in the list is created as a
271 * real evas object. event_info parameter is the genlist item that was
272 * created.
273 * - @c "unrealized" - This is called just before an item is unrealized.
274 * After this call content objects provided will be deleted and the item
275 * object itself delete or be put into a floating cache.
276 * - @c "drag,start,up" - This is called when the item in the list has been
277 * dragged (not scrolled) up.
278 * - @c "drag,start,down" - This is called when the item in the list has been
279 * dragged (not scrolled) down.
280 * - @c "drag,start,left" - This is called when the item in the list has been
281 * dragged (not scrolled) left.
282 * - @c "drag,start,right" - This is called when the item in the list has
283 * been dragged (not scrolled) right.
284 * - @c "drag,stop" - This is called when the item in the list has stopped
285 * being dragged.
286 * - @c "drag" - This is called when the item in the list is being dragged.
287 * - @c "longpressed" - This is called when the item is pressed for a certain
288 * amount of time. By default it's 1 second. The event_info parameter is the
289 * longpressed genlist item.
290 * - @c "scroll,anim,start" - This is called when scrolling animation has
291 * started.
292 * - @c "scroll,anim,stop" - This is called when scrolling animation has
293 * stopped.
294 * - @c "scroll,drag,start" - This is called when dragging the content has
295 * started.
296 * - @c "scroll,drag,stop" - This is called when dragging the content has
297 * stopped.
298 * - @c "edge,top" - This is called when the genlist is scrolled until
299 * the top edge.
300 * - @c "edge,bottom" - This is called when the genlist is scrolled
301 * until the bottom edge.
302 * - @c "edge,left" - This is called when the genlist is scrolled
303 * until the left edge.
304 * - @c "edge,right" - This is called when the genlist is scrolled
305 * until the right edge.
306 * - @c "multi,swipe,left" - This is called when the genlist is multi-touch
307 * swiped left.
308 * - @c "multi,swipe,right" - This is called when the genlist is multi-touch
309 * swiped right.
310 * - @c "multi,swipe,up" - This is called when the genlist is multi-touch
311 * swiped up.
312 * - @c "multi,swipe,down" - This is called when the genlist is multi-touch
313 * swiped down.
314 * - @c "multi,pinch,out" - This is called when the genlist is multi-touch
315 * pinched out.
316 * - @c multi,pinch,in" - This is called when the genlist is multi-touch
317 * pinched in.
318 * - @c "swipe" - This is called when the genlist is swiped.
319 * - @c "moved" - This is called when a genlist item is moved in reorder mode.
320 * - @c "moved,after" - This is called when a genlist item is moved after
321 * another item in reorder mode. The event_info parameter is the reordered
322 * item. To get the relative previous item, use elm_genlist_item_prev_get().
323 * This signal is called along with "moved" signal.
324 * - @c "moved,before" - This is called when a genlist item is moved before
325 * another item in reorder mode. The event_info parameter is the reordered
326 * item. To get the relative previous item, use elm_genlist_item_next_get().
327 * This signal is called along with "moved" signal.
328 * - @c "language,changed" - This is called when the program's language is
329 * changed.
330 * - @c "tree,effect,finished" - This is called when a genlist tree effect is finished.
331 *
332 * Supported elm_object common APIs
333 * @li @ref elm_object_signal_emit()
334 *
335 * Supported elm_object_item common APIs
336 * @li @ref elm_object_item_part_content_get()
337 * @li @ref elm_object_item_part_text_get()
338 * @li @ref elm_object_item_disabled_set()
339 * @li @ref elm_object_item_disabled_get()
340 * @li @ref elm_object_item_signal_emit()
341 *
342 * Unsupported elm_object_item common APIs due to the genlist concept.
343 * Genlist fills content/text according to the appropriate callback functions.
344 * Please use elm_genlist_item_update() or elm_genlist_item_fields_update()
345 * instead.
346 * @li @ref elm_object_item_part_content_set()
347 * @li @ref elm_object_item_part_content_unset()
348 * @li @ref elm_object_item_part_text_set()
349 *
350 * @section Genlist_Examples Examples
351 *
352 * Here is a list of examples that use the genlist, trying to show some of
353 * its capabilities:
354 * - @ref genlist_example_01
355 * - @ref genlist_example_02
356 * - @ref genlist_example_03
357 * - @ref genlist_example_04
358 * - @ref genlist_example_05
359 */
360
361/**
362 * @addtogroup Genlist
363 * @{
364 */
365
366#define ELM_GENLIST_ITEM_CLASS_VERSION ELM_GEN_ITEM_CLASS_VERSION
367#define ELM_GENLIST_ITEM_CLASS_HEADER ELM_GEN_ITEM_CLASS_HEADER
368
369/**
370 * Defines if the item is of any special type (has subitems or it's the
371 * index of a group), or is just a simple item.
372 *
373 * @ingroup Genlist
374 */
375typedef enum
376{
377 ELM_GENLIST_ITEM_NONE = 0, /**< simple item */
378 ELM_GENLIST_ITEM_TREE = (1 << 0), /**< this may be expanded and have child items. */
379 ELM_GENLIST_ITEM_GROUP = (1 << 1), /**< an index item of a group of items. this item can have child items. */
380
381 ELM_GENLIST_ITEM_MAX = (1 << 2)
382} Elm_Genlist_Item_Type;
383
384/**
385 * Defines the type of the item part
386 * Used while updating item's parts
387 * It can be used at updating multi fields.
388 *
389 * @ingroup Genlist
390 */
391typedef enum
392{
393 ELM_GENLIST_ITEM_FIELD_ALL = 0,
394 ELM_GENLIST_ITEM_FIELD_TEXT = (1 << 0),
395 ELM_GENLIST_ITEM_FIELD_CONTENT = (1 << 1),
396 ELM_GENLIST_ITEM_FIELD_STATE = (1 << 2)
397} Elm_Genlist_Item_Field_Type;
398
399/**
400 * Defines where to position the item in the genlist.
401 *
402 * @ingroup Genlist
403 */
404typedef enum
405{
406 ELM_GENLIST_ITEM_SCROLLTO_NONE = 0, /**< no scrollto */
407 ELM_GENLIST_ITEM_SCROLLTO_IN = (1 << 0), /**< to the nearest viewport */
408 ELM_GENLIST_ITEM_SCROLLTO_TOP = (1 << 1), /**< to the top of viewport */
409 ELM_GENLIST_ITEM_SCROLLTO_MIDDLE = (1 << 2) /**< to the middle of viewport */
410} Elm_Genlist_Item_Scrollto_Type;
411
412/**
413 * @see Elm_Gen_Item_Class
414 */
415typedef Elm_Gen_Item_Class Elm_Genlist_Item_Class;
416
417/**
418 * @see Elm_Gen_Item_Text_Get_Cb
419 */
420typedef Elm_Gen_Item_Text_Get_Cb Elm_Genlist_Item_Text_Get_Cb;
421
422/**
423 * @see Elm_Gen_Item_Content_Get_Cb
424 */
425typedef Elm_Gen_Item_Content_Get_Cb Elm_Genlist_Item_Content_Get_Cb;
426
427/**
428 * @see Elm_Gen_Item_State_Get_Cb
429 */
430typedef Elm_Gen_Item_State_Get_Cb Elm_Genlist_Item_State_Get_Cb;
431
432/**
433 * @see Elm_Gen_Item_Del_Cb
434 */
435typedef Elm_Gen_Item_Del_Cb Elm_Genlist_Item_Del_Cb;
436
437/**
438 * Add a new genlist widget to the given parent Elementary
439 * (container) object
440 *
441 * @param parent The parent object
442 * @return a new genlist widget handle or @c NULL, on errors
443 *
444 * This function inserts a new genlist widget on the canvas.
445 *
446 * @see elm_genlist_item_append()
447 * @see elm_object_item_del()
448 * @see elm_genlist_clear()
449 *
450 * @ingroup Genlist
451 */
452EAPI Evas_Object *elm_genlist_add(Evas_Object *parent);
453
454/**
455 * Remove all items from a given genlist widget.
456 *
457 * @param obj The genlist object
458 *
459 * This removes (and deletes) all items in @p obj, leaving it empty.
460 *
461 * @see elm_object_item_del(), to remove just one item.
462 *
463 * @ingroup Genlist
464 */
465EAPI void elm_genlist_clear(Evas_Object *obj);
466
467/**
468 * Enable or disable multi-selection in the genlist
469 *
470 * @param obj The genlist object
471 * @param multi Multi-select enable/disable. Default is disabled.
472 *
473 * This enables (@c EINA_TRUE) or disables (@c EINA_FALSE) multi-selection in
474 * the list. This allows more than 1 item to be selected. To retrieve the list
475 * of selected items, use elm_genlist_selected_items_get().
476 *
477 * @see elm_genlist_selected_items_get()
478 * @see elm_genlist_multi_select_get()
479 *
480 * @ingroup Genlist
481 */
482EAPI void elm_genlist_multi_select_set(Evas_Object *obj, Eina_Bool multi);
483
484/**
485 * Gets if multi-selection in genlist is enabled or disabled.
486 *
487 * @param obj The genlist object
488 * @return Multi-select enabled/disabled
489 * (@c EINA_TRUE = enabled/@c EINA_FALSE = disabled). Default is @c EINA_FALSE.
490 *
491 * @see elm_genlist_multi_select_set()
492 *
493 * @ingroup Genlist
494 */
495EAPI Eina_Bool elm_genlist_multi_select_get(const Evas_Object *obj);
496
497/**
498 * This sets the horizontal stretching mode.
499 *
500 * @param obj The genlist object
501 * @param mode The mode to use (one of #ELM_LIST_SCROLL or #ELM_LIST_LIMIT).
502 *
503 * This sets the mode used for sizing items horizontally. Valid modes
504 * are #ELM_LIST_LIMIT, #ELM_LIST_SCROLL, and #ELM_LIST_COMPRESS. The default is
505 * ELM_LIST_SCROLL. This mode means that if items are too wide to fit,
506 * the scroller will scroll horizontally. Otherwise items are expanded
507 * to fill the width of the viewport of the scroller. If it is
508 * ELM_LIST_LIMIT, items will be expanded to the viewport width and
509 * limited to that size. If it is ELM_LIST_COMPRESS, the item width will be
510 * fixed (restricted to a minimum of) to the list width when calculating its
511 * size in order to allow the height to be calculated based on it. This allows,
512 * for instance, text block to wrap lines if the Edje part is configured with
513 * "text.min: 0 1".
514 * @note ELM_LIST_COMPRESS will make list resize slower as it will have to
515 * recalculate every item height again whenever the list width
516 * changes!
517 * @note When ELM_LIST_COMPRESS mode is enabled, it also enables
518 * compress mode (see elm_genlist_mode_set()) and
519 * disables homogeneous (see elm_genlist_homogeneous_set()).
520 *
521 * @see elm_genlist_mode_get()
522 *
523 * @ingroup Genlist
524 */
525EAPI void elm_genlist_mode_set(Evas_Object *obj, Elm_List_Mode mode);
526
527/**
528 * Gets the horizontal stretching mode.
529 *
530 * @param obj The genlist object
531 * @return The mode to use
532 * (#ELM_LIST_LIMIT, #ELM_LIST_SCROLL)
533 *
534 * @see elm_genlist_mode_set()
535 *
536 * @ingroup Genlist
537 */
538EAPI Elm_List_Mode elm_genlist_mode_get(const Evas_Object *obj);
539
540/**
541 * Enable/disable horizontal and vertical bouncing effect.
542 *
543 * @param obj The genlist object
544 * @param h_bounce Allow bounce horizontally (@c EINA_TRUE = on, @c
545 * EINA_FALSE = off). Default is @c EINA_FALSE.
546 * @param v_bounce Allow bounce vertically (@c EINA_TRUE = on, @c
547 * EINA_FALSE = off). Default is @c EINA_TRUE.
548 *
549 * This will enable or disable the scroller bouncing effect for the
550 * genlist. See elm_scroller_bounce_set() for details.
551 *
552 * @see elm_scroller_bounce_set()
553 * @see elm_genlist_bounce_get()
554 *
555 * @ingroup Genlist
556 */
557EAPI void elm_genlist_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
558
559/**
560 * Get whether the horizontal and vertical bouncing effect is enabled.
561 *
562 * @param obj The genlist object
563 * @param h_bounce Pointer to a bool to receive if the bounce horizontally
564 * option is set.
565 * @param v_bounce Pointer to a bool to receive if the bounce vertically
566 * option is set.
567 *
568 * @see elm_genlist_bounce_set()
569 *
570 * @ingroup Genlist
571 */
572EAPI void elm_genlist_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
573
574/**
575 * Append a new item in a given genlist widget.
576 *
577 * @param obj The genlist object
578 * @param itc The item class for the item
579 * @param data The item data
580 * @param parent The parent item, or NULL if none
581 * @param type Item type
582 * @param func Convenience function called when the item is selected
583 * @param func_data Data passed to @p func above.
584 * @return A handle to the item added or @c NULL if not possible
585 *
586 * This adds the given item to the end of the list or the end of
587 * the children list if the @p parent is given.
588 *
589 * @see elm_genlist_item_prepend()
590 * @see elm_genlist_item_insert_before()
591 * @see elm_genlist_item_insert_after()
592 * @see elm_object_item_del()
593 *
594 * @ingroup Genlist
595 */
596EAPI Elm_Object_Item *elm_genlist_item_append(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *parent, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data);
597
598/**
599 * Prepend a new item in a given genlist widget.
600 *
601 * @param obj The genlist object
602 * @param itc The item class for the item
603 * @param data The item data
604 * @param parent The parent item, or NULL if none
605 * @param type Item type
606 * @param func Convenience function called when the item is selected
607 * @param func_data Data passed to @p func above.
608 * @return A handle to the item added or NULL if not possible
609 *
610 * This adds an item to the beginning of the list or beginning of the
611 * children of the parent if given.
612 *
613 * @see elm_genlist_item_append()
614 * @see elm_genlist_item_insert_before()
615 * @see elm_genlist_item_insert_after()
616 * @see elm_object_item_del()
617 *
618 * @ingroup Genlist
619 */
620EAPI Elm_Object_Item *elm_genlist_item_prepend(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *parent, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data);
621
622/**
623 * Insert an item before another in a genlist widget
624 *
625 * @param obj The genlist object
626 * @param itc The item class for the item
627 * @param data The item data
628 * @param parent The parent item, or NULL if none
629 * @param before The item to place this new one before.
630 * @param type Item type
631 * @param func Convenience function called when the item is selected
632 * @param func_data Data passed to @p func above.
633 * @return A handle to the item added or @c NULL if not possible
634 *
635 * This inserts an item before another in the list. It will be in the
636 * same tree level or group as the item it is inserted before.
637 *
638 * @see elm_genlist_item_append()
639 * @see elm_genlist_item_prepend()
640 * @see elm_genlist_item_insert_after()
641 * @see elm_object_item_del()
642 *
643 * @ingroup Genlist
644 */
645EAPI Elm_Object_Item *elm_genlist_item_insert_before(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *parent, Elm_Object_Item *before, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data);
646
647/**
648 * Insert an item after another in a genlist widget
649 *
650 * @param obj The genlist object
651 * @param itc The item class for the item
652 * @param data The item data
653 * @param parent The parent item, or NULL if none
654 * @param after The item to place this new one after.
655 * @param type Item type
656 * @param func Convenience function called when the item is selected
657 * @param func_data Data passed to @p func above.
658 * @return A handle to the item added or @c NULL if not possible
659 *
660 * This inserts an item after another in the list. It will be in the
661 * same tree level or group as the item it is inserted after.
662 *
663 * @see elm_genlist_item_append()
664 * @see elm_genlist_item_prepend()
665 * @see elm_genlist_item_insert_before()
666 * @see elm_object_item_del()
667 *
668 * @ingroup Genlist
669 */
670EAPI Elm_Object_Item *elm_genlist_item_insert_after(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *parent, Elm_Object_Item *after, Elm_Genlist_Item_Type type, Evas_Smart_Cb func, const void *func_data);
671
672/**
673 * Insert a new item into the sorted genlist object
674 *
675 * @param obj The genlist object
676 * @param itc The item class for the item
677 * @param data The item data
678 * @param parent The parent item, or NULL if none
679 * @param type Item type
680 * @param comp The function called for the sort
681 * @param func Convenience function called when item selected
682 * @param func_data Data passed to @p func above.
683 * @return A handle to the item added or NULL if not possible
684 *
685 * This inserts an item in the genlist based on user defined comparison
686 * function. The two arguments passed to the function @p func are genlist item
687 * handles to compare.
688 *
689 * @see elm_genlist_item_append()
690 * @see elm_genlist_item_prepend()
691 * @see elm_genlist_item_insert_after()
692 * @see elm_object_item_del()
693
694 * @ingroup Genlist
695 */
696EAPI Elm_Object_Item *elm_genlist_item_sorted_insert(Evas_Object *obj, const Elm_Genlist_Item_Class *itc, const void *data, Elm_Object_Item *parent, Elm_Genlist_Item_Type type, Eina_Compare_Cb comp, Evas_Smart_Cb func, const void *func_data);
697
698/* operations to retrieve existing items */
699/**
700 * Get the selected item in the genlist.
701 *
702 * @param obj The genlist object
703 * @return The selected item, or NULL if none is selected.
704 *
705 * This gets the selected item in the list (if multi-selection is enabled, only
706 * the item that was first selected in the list is returned - which is not very
707 * useful, so see elm_genlist_selected_items_get() for when multi-selection is
708 * used).
709 *
710 * If no item is selected, NULL is returned.
711 *
712 * @see elm_genlist_selected_items_get()
713 *
714 * @ingroup Genlist
715 */
716EAPI Elm_Object_Item *elm_genlist_selected_item_get(const Evas_Object *obj);
717
718/**
719 * Get a list of selected items in the genlist.
720 *
721 * @param obj The genlist object
722 * @return The list of selected items, or NULL if none are selected.
723 *
724 * It returns a list of the selected items. This list pointer is only valid so
725 * long as the selection doesn't change (no items are selected or unselected, or
726 * unselected implicitly by deletion). The list contains genlist items
727 * pointers. The order of the items in this list is the order which they were
728 * selected, i.e. the first item in this list is the first item that was
729 * selected, and so on.
730 *
731 * @note If not in multi-select mode, consider using function
732 * elm_genlist_selected_item_get() instead.
733 *
734 * @see elm_genlist_multi_select_set()
735 * @see elm_genlist_selected_item_get()
736 *
737 * @ingroup Genlist
738 */
739EAPI const Eina_List *elm_genlist_selected_items_get(const Evas_Object *obj);
740
741/**
742 * Get a list of realized items in genlist
743 *
744 * @param obj The genlist object
745 * @return The list of realized items, nor NULL if none are realized.
746 *
747 * This returns a list of the realized items in the genlist. The list
748 * contains genlist item pointers. The list must be freed by the
749 * caller when done with eina_list_free(). The item pointers in the
750 * list are only valid so long as those items are not deleted or the
751 * genlist is not deleted.
752 *
753 * @see elm_genlist_realized_items_update()
754 *
755 * @ingroup Genlist
756 */
757EAPI Eina_List *elm_genlist_realized_items_get(const Evas_Object *obj);
758
759/**
760 * Get the first item in the genlist
761 *
762 * This returns the first item in the list.
763 *
764 * @param obj The genlist object
765 * @return The first item, or NULL if none
766 *
767 * @ingroup Genlist
768 */
769EAPI Elm_Object_Item *elm_genlist_first_item_get(const Evas_Object *obj);
770
771/**
772 * Get the last item in the genlist
773 *
774 * This returns the last item in the list.
775 *
776 * @return The last item, or NULL if none
777 *
778 * @ingroup Genlist
779 */
780EAPI Elm_Object_Item *elm_genlist_last_item_get(const Evas_Object *obj);
781
782/**
783 * Set the scrollbar policy
784 *
785 * @param obj The genlist object
786 * @param policy_h Horizontal scrollbar policy.
787 * @param policy_v Vertical scrollbar policy.
788 *
789 * This sets the scrollbar visibility policy for the given genlist
790 * scroller. #ELM_SCROLLER_POLICY_AUTO means the scrollbar is
791 * made visible if it is needed, and otherwise kept hidden.
792 * #ELM_SCROLLER_POLICY_ON turns it on all the time, and
793 * #ELM_SCROLLER_POLICY_OFF always keeps it off. This applies
794 * respectively for the horizontal and vertical scrollbars. Default is
795 * #ELM_SCROLLER_POLICY_AUTO
796 *
797 * @see elm_genlist_scroller_policy_get()
798 *
799 * @ingroup Genlist
800 */
801EAPI void elm_genlist_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
802
803/**
804 * Get the scrollbar policy
805 *
806 * @param obj The genlist object
807 * @param policy_h Pointer to store the horizontal scrollbar policy.
808 * @param policy_v Pointer to store the vertical scrollbar policy.
809 *
810 * @see elm_genlist_scroller_policy_set()
811 *
812 * @ingroup Genlist
813 */
814EAPI void elm_genlist_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
815
816/**
817 * Get the @b next item in a genlist widget's internal list of items,
818 * given a handle to one of those items.
819 *
820 * @param it The genlist item to fetch next from
821 * @return The item after @p item, or @c NULL if there's none (and
822 * on errors)
823 *
824 * This returns the item placed after the @p item, on the container
825 * genlist.
826 *
827 * @see elm_genlist_item_prev_get()
828 *
829 * @ingroup Genlist
830 */
831EAPI Elm_Object_Item *elm_genlist_item_next_get(const Elm_Object_Item *it);
832
833/**
834 * Get the @b previous item in a genlist widget's internal list of items,
835 * given a handle to one of those items.
836 *
837 * @param it The genlist item to fetch previous from
838 * @return The item before @p item, or @c NULL if there's none (and
839 * on errors)
840 *
841 * This returns the item placed before the @p item, on the container
842 * genlist.
843 *
844 * @see elm_genlist_item_next_get()
845 *
846 * @ingroup Genlist
847 */
848EAPI Elm_Object_Item *elm_genlist_item_prev_get(const Elm_Object_Item *it);
849
850/**
851 * Set whether a given genlist item is selected or not
852 *
853 * @param it The item
854 * @param selected Use @c EINA_TRUE, to make it selected, @c
855 * EINA_FALSE to make it unselected
856 *
857 * This sets the selected state of an item. If multi selection is
858 * not enabled on the containing genlist and @p selected is @c
859 * EINA_TRUE, any other previously selected items will get
860 * unselected in favor of this new one.
861 *
862 * @see elm_genlist_item_selected_get()
863 *
864 * @ingroup Genlist
865 */
866EAPI void elm_genlist_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
867
868/**
869 * Get whether a given genlist item is selected or not
870 *
871 * @param it The item
872 * @return @c EINA_TRUE, if it's selected, @c EINA_FALSE otherwise
873 *
874 * @see elm_genlist_item_selected_set() for more details
875 *
876 * @ingroup Genlist
877 */
878EAPI Eina_Bool elm_genlist_item_selected_get(const Elm_Object_Item *it);
879
880/**
881 * Show the portion of a genlist's internal list containing a given
882 * item, immediately.
883 *
884 * @param it The item to display
885 * @param type The position to bring in, the given item to.
886 * @ref Elm_Genlist_Item_Scrollto_Type
887 *
888 * This causes genlist to jump to the given item @p it and show it (by
889 * jumping to that position), if it is not fully visible.
890 *
891 * @see elm_genlist_item_bring_in()
892 *
893 * @ingroup Genlist
894 */
895EAPI void elm_genlist_item_show(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type);
896
897/**
898 * Animatedly bring in, to the visible are of a genlist, a given
899 * item on it.
900 *
901 * @param it The item to display
902 * @param type The position to bring in, the given item to.
903 * @ref Elm_Genlist_Item_Scrollto_Type
904 *
905 * This causes genlist to jump to the given item @p it and show it (by
906 * animatedly scrolling), if it is not fully visible.
907 * This may use animation and take a some time to do so.
908 *
909 * @see elm_genlist_item_show()
910 *
911 * @ingroup Genlist
912 */
913EAPI void elm_genlist_item_bring_in(Elm_Object_Item *it, Elm_Genlist_Item_Scrollto_Type type);
914
915/**
916 * Update the contents of an item
917 *
918 * @param it The item
919 *
920 * This updates an item by calling all the item class functions again
921 * to get the contents, texts and states. Use this when the original
922 * item data has changed and the changes are desired to be reflected.
923 *
924 * Use elm_genlist_realized_items_update() to update all already realized
925 * items.
926 *
927 * @see elm_genlist_realized_items_update()
928 *
929 * @ingroup Genlist
930 */
931EAPI void elm_genlist_item_update(Elm_Object_Item *it);
932
933/**
934 * Update the item class of an item
935 *
936 * @param it The item
937 * @param itc The item class for the item
938 *
939 * This sets another class of the item, changing the way that it is
940 * displayed. After changing the item class, elm_genlist_item_update() is
941 * called on the item @p it.
942 *
943 * @ingroup Genlist
944 */
945EAPI void elm_genlist_item_item_class_update(Elm_Object_Item *it, const Elm_Genlist_Item_Class *itc);
946
947/**
948 * Get the Genlist Item class for the given Genlist Item.
949 *
950 * @param it The genlist item
951 *
952 * This returns the Genlist_Item_Class for the given item. It can be used to
953 * examine the function pointers and item_style.
954 *
955 * @ingroup Genlist
956 */
957EAPI const Elm_Genlist_Item_Class *elm_genlist_item_item_class_get(const Elm_Object_Item *it);
958
959/**
960 * Get the index of the item. It is only valid once displayed.
961 *
962 * @param it a genlist item
963 * @return the position inside the list of item.
964 *
965 * @ingroup Genlist
966 */
967EAPI int elm_genlist_item_index_get(const Elm_Object_Item *it);
968
969/**
970 * Update the contents of all realized items.
971 *
972 * @param obj The genlist object.
973 *
974 * This updates all realized items by calling all the item class functions again
975 * to get the contents, texts and states. Use this when the original
976 * item data has changed and the changes are desired to be reflected.
977 *
978 * To update just one item, use elm_genlist_item_update().
979 *
980 * @see elm_genlist_realized_items_get()
981 * @see elm_genlist_item_update()
982 *
983 * @ingroup Genlist
984 */
985EAPI void elm_genlist_realized_items_update(Evas_Object *obj);
986
987/**
988 * Return how many items are currently in a list
989 *
990 * @param obj The list
991 * @return The total number of list items in the list
992 *
993 * This behavior is O(1) and includes items which may or may not be realized.
994 *
995 * @ingroup Genlist
996 */
997EAPI unsigned int elm_genlist_items_count(const Evas_Object *obj);
998
999/**
1000 * Create a new genlist item class in a given genlist widget.
1001 *
1002 * @return New allocated a genlist item class.
1003 *
1004 * This adds genlist item class for the genlist widget. When adding an item,
1005 * genlist_item_{append, prepend, insert} function needs item class of the item.
1006 * Given callback parameters are used at retrieving {text, content} of
1007 * added item. Set as NULL if it's not used.
1008 * If there's no available memory, return can be NULL.
1009 *
1010 * @see elm_genlist_item_class_free()
1011 * @see elm_genlist_item_append()
1012 *
1013 * @ingroup Genlist
1014 */
1015EAPI Elm_Genlist_Item_Class *elm_genlist_item_class_new(void);
1016
1017/**
1018 * Remove an item class in a given genlist widget.
1019 *
1020 * @param itc The itc to be removed.
1021 *
1022 * This removes item class from the genlist widget.
1023 * Whenever it has no more references to it, item class is going to be freed.
1024 * Otherwise it just decreases its reference count.
1025 *
1026 * @see elm_genlist_item_class_new()
1027 * @see elm_genlist_item_class_ref()
1028 * @see elm_genlist_item_class_unref()
1029 *
1030 * @ingroup Genlist
1031 */
1032EAPI void elm_genlist_item_class_free(Elm_Genlist_Item_Class *itc);
1033
1034/**
1035 * Increments object reference count for the item class.
1036 *
1037 * @param itc The given item class object to reference
1038 *
1039 * This API just increases its reference count for item class management.
1040 *
1041 * @see elm_genlist_item_class_unref()
1042 *
1043 * @ingroup Genlist
1044 */
1045EAPI void elm_genlist_item_class_ref(Elm_Genlist_Item_Class *itc);
1046
1047/**
1048 * Decrements object reference count for the item class.
1049 *
1050 * @param itc The given item class object to reference
1051 *
1052 * This API just decreases its reference count for item class management.
1053 * Reference count can't be less than 0.
1054 *
1055 * @see elm_genlist_item_class_ref()
1056 * @see elm_genlist_item_class_free()
1057 *
1058 * @ingroup Genlist
1059 */
1060EAPI void elm_genlist_item_class_unref(Elm_Genlist_Item_Class *itc);
1061
1062/**
1063 * Set the text to be shown in a given genlist item's tooltips.
1064 *
1065 * @param it The genlist item
1066 * @param text The text to set in the content
1067 *
1068 * This call will setup the text to be used as tooltip to that item
1069 * (analogous to elm_object_tooltip_text_set(), but being item
1070 * tooltips with higher precedence than object tooltips). It can
1071 * have only one tooltip at a time, so any previous tooltip data
1072 * will get removed.
1073 *
1074 * In order to set a content or something else as a tooltip, look at
1075 * elm_genlist_item_tooltip_content_cb_set().
1076 *
1077 * @ingroup Genlist
1078 */
1079EAPI void elm_genlist_item_tooltip_text_set(Elm_Object_Item *it, const char *text);
1080
1081/**
1082 * Set the content to be shown in a given genlist item's tooltips
1083 *
1084 * @param it The genlist item.
1085 * @param func The function returning the tooltip contents.
1086 * @param data What to provide to @a func as callback data/context.
1087 * @param del_cb Called when data is not needed anymore, either when
1088 * another callback replaces @p func, the tooltip is unset with
1089 * elm_genlist_item_tooltip_unset() or the owner @p item
1090 * dies. This callback receives as its first parameter the
1091 * given @p data, being @c event_info the item handle.
1092 *
1093 * This call will setup the tooltip's contents to @p item
1094 * (analogous to elm_object_tooltip_content_cb_set(), but being
1095 * item tooltips with higher precedence than object tooltips). It
1096 * can have only one tooltip at a time, so any previous tooltip
1097 * content will get removed. @p func (with @p data) will be called
1098 * every time Elementary needs to show the tooltip and it should
1099 * return a valid Evas object, which will be fully managed by the
1100 * tooltip system, getting deleted when the tooltip is gone.
1101 *
1102 * In order to set just a text as a tooltip, look at
1103 * elm_genlist_item_tooltip_text_set().
1104 *
1105 * @ingroup Genlist
1106 */
1107EAPI void elm_genlist_item_tooltip_content_cb_set(Elm_Object_Item *it, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
1108
1109/**
1110 * Unset a tooltip from a given genlist item
1111 *
1112 * @param it genlist item to remove a previously set tooltip from.
1113 *
1114 * This call removes any tooltip set on @p item. The callback
1115 * provided as @c del_cb to
1116 * elm_genlist_item_tooltip_content_cb_set() will be called to
1117 * notify it is not used anymore (and have resources cleaned, if
1118 * need be).
1119 *
1120 * @see elm_genlist_item_tooltip_content_cb_set()
1121 *
1122 * @ingroup Genlist
1123 */
1124EAPI void elm_genlist_item_tooltip_unset(Elm_Object_Item *it);
1125
1126/**
1127 * Set a different @b style for a given genlist item's tooltip.
1128 *
1129 * @param it genlist item with tooltip set
1130 * @param style the <b>theme style</b> to use on tooltips (e.g. @c
1131 * "default", @c "transparent", etc)
1132 *
1133 * Tooltips can have <b>alternate styles</b> to be displayed on,
1134 * which are defined by the theme set on Elementary. This function
1135 * works analogously as elm_object_tooltip_style_set(), but here
1136 * applied only to genlist item objects. The default style for
1137 * tooltips is @c "default".
1138 *
1139 * @note before you set a style you should define a tooltip with
1140 * elm_genlist_item_tooltip_content_cb_set() or
1141 * elm_genlist_item_tooltip_text_set()
1142 *
1143 * @see elm_genlist_item_tooltip_style_get()
1144 *
1145 * @ingroup Genlist
1146 */
1147EAPI void elm_genlist_item_tooltip_style_set(Elm_Object_Item *it, const char *style);
1148
1149/**
1150 * Get the style set a given genlist item's tooltip.
1151 *
1152 * @param it genlist item with tooltip already set on.
1153 * @return style the theme style in use, which defaults to
1154 * "default". If the object does not have a tooltip set,
1155 * then @c NULL is returned.
1156 *
1157 * @see elm_genlist_item_tooltip_style_set() for more details
1158 *
1159 * @ingroup Genlist
1160 */
1161EAPI const char *elm_genlist_item_tooltip_style_get(const Elm_Object_Item *it);
1162
1163/**
1164 * @brief Disable size restrictions on an object's tooltip
1165 * @param it The tooltip's anchor object
1166 * @param disable If EINA_TRUE, size restrictions are disabled
1167 * @return EINA_FALSE on failure, EINA_TRUE on success
1168 *
1169 * This function allows a tooltip to expand beyond its parent window's canvas.
1170 * It will instead be limited only by the size of the display.
1171 */
1172EAPI Eina_Bool elm_genlist_item_tooltip_window_mode_set(Elm_Object_Item *it, Eina_Bool disable);
1173
1174/**
1175 * @brief Retrieve size restriction state of an object's tooltip
1176 * @param it The tooltip's anchor object
1177 * @return If EINA_TRUE, size restrictions are disabled
1178 *
1179 * This function returns whether a tooltip is allowed to expand beyond
1180 * its parent window's canvas.
1181 * It will instead be limited only by the size of the display.
1182 */
1183EAPI Eina_Bool elm_genlist_item_tooltip_window_mode_get(const Elm_Object_Item *it);
1184
1185/**
1186 * Set the type of mouse pointer/cursor decoration to be shown,
1187 * when the mouse pointer is over the given genlist widget item
1188 *
1189 * @param it genlist item to customize cursor on
1190 * @param cursor the cursor type's name
1191 *
1192 * This function works analogously as elm_object_cursor_set(), but
1193 * here the cursor's changing area is restricted to the item's
1194 * area, and not the whole widget's. Note that that item cursors
1195 * have precedence over widget cursors, so that a mouse over @p
1196 * item will always show cursor @p type.
1197 *
1198 * If this function is called twice for an object, a previously set
1199 * cursor will be unset on the second call.
1200 *
1201 * @see elm_object_cursor_set()
1202 * @see elm_genlist_item_cursor_get()
1203 * @see elm_genlist_item_cursor_unset()
1204 *
1205 * @ingroup Genlist
1206 */
1207EAPI void elm_genlist_item_cursor_set(Elm_Object_Item *it, const char *cursor);
1208
1209/**
1210 * Get the type of mouse pointer/cursor decoration set to be shown,
1211 * when the mouse pointer is over the given genlist widget item
1212 *
1213 * @param it genlist item with custom cursor set
1214 * @return the cursor type's name or @c NULL, if no custom cursors
1215 * were set to @p item (and on errors)
1216 *
1217 * @see elm_object_cursor_get()
1218 * @see elm_genlist_item_cursor_set() for more details
1219 * @see elm_genlist_item_cursor_unset()
1220 *
1221 * @ingroup Genlist
1222 */
1223EAPI const char *elm_genlist_item_cursor_get(const Elm_Object_Item *it);
1224
1225/**
1226 * Unset any custom mouse pointer/cursor decoration set to be
1227 * shown, when the mouse pointer is over the given genlist widget
1228 * item, thus making it show the @b default cursor again.
1229 *
1230 * @param it a genlist item
1231 *
1232 * Use this call to undo any custom settings on this item's cursor
1233 * decoration, bringing it back to defaults (no custom style set).
1234 *
1235 * @see elm_object_cursor_unset()
1236 * @see elm_genlist_item_cursor_set() for more details
1237 *
1238 * @ingroup Genlist
1239 */
1240EAPI void elm_genlist_item_cursor_unset(Elm_Object_Item *it);
1241
1242/**
1243 * Set a different @b style for a given custom cursor set for a
1244 * genlist item.
1245 *
1246 * @param it genlist item with custom cursor set
1247 * @param style the <b>theme style</b> to use (e.g. @c "default",
1248 * @c "transparent", etc)
1249 *
1250 * This function only makes sense when one is using custom mouse
1251 * cursor decorations <b>defined in a theme file</b> , which can
1252 * have, given a cursor name/type, <b>alternate styles</b> on
1253 * it. It works analogously as elm_object_cursor_style_set(), but
1254 * here applied only to genlist item objects.
1255 *
1256 * @warning Before you set a cursor style you should have defined a
1257 * custom cursor previously on the item, with
1258 * elm_genlist_item_cursor_set()
1259 *
1260 * @see elm_genlist_item_cursor_engine_only_set()
1261 * @see elm_genlist_item_cursor_style_get()
1262 *
1263 * @ingroup Genlist
1264 */
1265EAPI void elm_genlist_item_cursor_style_set(Elm_Object_Item *it, const char *style);
1266
1267/**
1268 * Get the current @b style set for a given genlist item's custom
1269 * cursor
1270 *
1271 * @param it genlist item with custom cursor set.
1272 * @return style the cursor style in use. If the object does not
1273 * have a cursor set, then @c NULL is returned.
1274 *
1275 * @see elm_genlist_item_cursor_style_set() for more details
1276 *
1277 * @ingroup Genlist
1278 */
1279EAPI const char *elm_genlist_item_cursor_style_get(const Elm_Object_Item *it);
1280
1281/**
1282 * Set if the (custom) cursor for a given genlist item should be
1283 * searched in its theme, also, or should only rely on the
1284 * rendering engine.
1285 *
1286 * @param it item with custom (custom) cursor already set on
1287 * @param engine_only Use @c EINA_TRUE to have cursors looked for
1288 * only on those provided by the rendering engine, @c EINA_FALSE to
1289 * have them searched on the widget's theme, as well.
1290 *
1291 * @note This call is of use only if you've set a custom cursor
1292 * for genlist items, with elm_genlist_item_cursor_set().
1293 *
1294 * @note By default, cursors will only be looked for between those
1295 * provided by the rendering engine.
1296 *
1297 * @ingroup Genlist
1298 */
1299EAPI void elm_genlist_item_cursor_engine_only_set(Elm_Object_Item *it, Eina_Bool engine_only);
1300
1301/**
1302 * Get if the (custom) cursor for a given genlist item is being
1303 * searched in its theme, also, or is only relying on the rendering
1304 * engine.
1305 *
1306 * @param it a genlist item
1307 * @return @c EINA_TRUE, if cursors are being looked for only on
1308 * those provided by the rendering engine, @c EINA_FALSE if they
1309 * are being searched on the widget's theme, as well.
1310 *
1311 * @see elm_genlist_item_cursor_engine_only_set(), for more details
1312 *
1313 * @ingroup Genlist
1314 */
1315EAPI Eina_Bool elm_genlist_item_cursor_engine_only_get(const Elm_Object_Item *it);
1316
1317/**
1318 * Enable/disable homogeneous mode.
1319 *
1320 * @param obj The genlist object
1321 * @param homogeneous Assume the items within the genlist are of the
1322 * same height and width (EINA_TRUE = on, EINA_FALSE = off). Default is @c
1323 * EINA_FALSE.
1324 *
1325 * This will enable the homogeneous mode where items are of the same
1326 * height and width so that genlist may do the lazy-loading at its
1327 * maximum (which increases the performance for scrolling the list). This
1328 * implies 'compressed' mode.
1329 *
1330 * @see elm_genlist_mode_set()
1331 * @see elm_genlist_homogeneous_get()
1332 *
1333 * @ingroup Genlist
1334 */
1335EAPI void elm_genlist_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous);
1336
1337/**
1338 * Get whether the homogeneous mode is enabled.
1339 *
1340 * @param obj The genlist object
1341 * @return Assume the items within the genlist are of the same height
1342 * and width (EINA_TRUE = on, EINA_FALSE = off)
1343 *
1344 * @see elm_genlist_homogeneous_set()
1345 *
1346 * @ingroup Genlist
1347 */
1348EAPI Eina_Bool elm_genlist_homogeneous_get(const Evas_Object *obj);
1349
1350/**
1351 * Set the maximum number of items within an item block
1352 *
1353 * @param obj The genlist object
1354 * @param count Maximum number of items within an item block. Default is 32.
1355 *
1356 * This will configure the block count to tune to the target with particular
1357 * performance matrix.
1358 *
1359 * A block of objects will be used to reduce the number of operations due to
1360 * many objects in the screen. It can determine the visibility, or if the
1361 * object has changed, it theme needs to be updated, etc. doing this kind of
1362 * calculation to the entire block, instead of per object.
1363 *
1364 * The default value for the block count is enough for most lists, so unless
1365 * you know you will have a lot of objects visible in the screen at the same
1366 * time, don't try to change this.
1367 *
1368 * @see elm_genlist_block_count_get()
1369 * @see @ref Genlist_Implementation
1370 *
1371 * @ingroup Genlist
1372 */
1373EAPI void elm_genlist_block_count_set(Evas_Object *obj, int count);
1374
1375/**
1376 * Get the maximum number of items within an item block
1377 *
1378 * @param obj The genlist object
1379 * @return Maximum number of items within an item block
1380 *
1381 * @see elm_genlist_block_count_set()
1382 *
1383 * @ingroup Genlist
1384 */
1385EAPI int elm_genlist_block_count_get(const Evas_Object *obj);
1386
1387/**
1388 * Set the timeout in seconds for the longpress event.
1389 *
1390 * @param obj The genlist object
1391 * @param timeout timeout in seconds. Default is elm config value(1.0)
1392 *
1393 * This option will change how long it takes to send an event "longpressed"
1394 * after the mouse down signal is sent to the list. If this event occurs, no
1395 * "clicked" event will be sent.
1396 *
1397 * @warning If you set the longpress timeout value with this API, your genlist
1398 * will not be affected by the longpress value of elementary config value
1399 * later.
1400 *
1401 * @see elm_genlist_longpress_timeout_set()
1402 *
1403 * @ingroup Genlist
1404 */
1405EAPI void elm_genlist_longpress_timeout_set(Evas_Object *obj, double timeout);
1406
1407/**
1408 * Get the timeout in seconds for the longpress event.
1409 *
1410 * @param obj The genlist object
1411 * @return timeout in seconds
1412 *
1413 * @see elm_genlist_longpress_timeout_get()
1414 *
1415 * @ingroup Genlist
1416 */
1417EAPI double elm_genlist_longpress_timeout_get(const Evas_Object *obj);
1418
1419/**
1420 * Get the item that is at the x, y canvas coords.
1421 *
1422 * @param obj The genlist object.
1423 * @param x The input x coordinate
1424 * @param y The input y coordinate
1425 * @param posret The position relative to the item returned here
1426 * @return The item at the coordinates or NULL if none
1427 *
1428 * This returns the item at the given coordinates (which are canvas
1429 * relative, not object-relative). If an item is at that coordinate,
1430 * that item handle is returned, and if @p posret is not NULL, the
1431 * integer pointed to is set to a value of -1, 0 or 1, depending if
1432 * the coordinate is on the upper portion of that item (-1), on the
1433 * middle section (0) or on the lower part (1). If NULL is returned as
1434 * an item (no item found there), then posret may indicate -1 or 1
1435 * based if the coordinate is above or below all items respectively in
1436 * the genlist.
1437 *
1438 * @ingroup Genlist
1439 */
1440EAPI Elm_Object_Item *elm_genlist_at_xy_item_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, int *posret);
1441
1442/**
1443 * Get the parent item of the given item
1444 *
1445 * @param it The item
1446 * @return The parent of the item or @c NULL if it has no parent.
1447 *
1448 * This returns the item that was specified as parent of the item @p it on
1449 * elm_genlist_item_append() and insertion related functions.
1450 *
1451 * @ingroup Genlist
1452 */
1453EAPI Elm_Object_Item *elm_genlist_item_parent_get(const Elm_Object_Item *it);
1454
1455/**
1456 * Remove all sub-items (children) of the given item
1457 *
1458 * @param it The item
1459 *
1460 * This removes all items that are children (and their descendants) of the
1461 * given item @p it.
1462 *
1463 * @see elm_genlist_clear()
1464 * @see elm_object_item_del()
1465 *
1466 * @ingroup Genlist
1467 */
1468EAPI void elm_genlist_item_subitems_clear(Elm_Object_Item *it);
1469
1470/**
1471 * Sets the expanded state of an item.
1472 *
1473 * @param it The item
1474 * @param expanded The expanded state (@c EINA_TRUE expanded, @c EINA_FALSE not expanded).
1475 *
1476 * This function flags the item of type #ELM_GENLIST_ITEM_TREE as
1477 * expanded or not.
1478 *
1479 * The theme will respond to this change visually, and a signal "expanded" or
1480 * "contracted" will be sent from the genlist with a pointer to the item that
1481 * has been expanded/contracted.
1482 *
1483 * Calling this function won't show or hide any child of this item (if it is
1484 * a parent). You must manually delete and create them on the callbacks of
1485 * the "expanded" or "contracted" signals.
1486 *
1487 * @see elm_genlist_item_expanded_get()
1488 *
1489 * @ingroup Genlist
1490 */
1491EAPI void elm_genlist_item_expanded_set(Elm_Object_Item *it, Eina_Bool expanded);
1492
1493/**
1494 * Get the expanded state of an item
1495 *
1496 * @param it The item
1497 * @return The expanded state
1498 *
1499 * This gets the expanded state of an item.
1500 *
1501 * @see elm_genlist_item_expanded_set()
1502 *
1503 * @ingroup Genlist
1504 */
1505EAPI Eina_Bool elm_genlist_item_expanded_get(const Elm_Object_Item *it);
1506
1507/**
1508 * Get the depth of expanded item
1509 *
1510 * @param it The genlist item object
1511 * @return The depth of expanded item
1512 *
1513 * @ingroup Genlist
1514 */
1515EAPI int elm_genlist_item_expanded_depth_get(const Elm_Object_Item *it);
1516
1517/**
1518 * Unset all contents fetched by the item class
1519 *
1520 * @param it The item
1521 * @param l The contents list to return
1522 *
1523 * This instructs genlist to release references to contents in the item,
1524 * meaning that they will no longer be managed by genlist and are
1525 * floating "orphans" that can be re-used elsewhere if the user wants
1526 * to.
1527 *
1528 * @ingroup Genlist
1529 */
1530EAPI void elm_genlist_item_all_contents_unset(Elm_Object_Item *it, Eina_List **l);
1531
1532/**
1533 * Promote an item to the top of the list
1534 *
1535 * @param it The item
1536 *
1537 * @ingroup Genlist
1538 */
1539EAPI void elm_genlist_item_promote(Elm_Object_Item *it);
1540
1541/**
1542 * Demote an item to the end of the list
1543 *
1544 * @param it The item
1545 *
1546 * @ingroup Genlist
1547 */
1548EAPI void elm_genlist_item_demote(Elm_Object_Item *it);
1549
1550/**
1551 * Update the part of an item
1552 *
1553 * @param it The item
1554 * @param parts The name of item's part
1555 * @param itf The type of item's part type
1556 *
1557 * This updates an item's part by calling item's fetching functions again
1558 * to get the contents, texts and states. Use this when the original
1559 * item data has changed and the changes are desired to be reflected.
1560 * Second parts argument is used for globbing to match '*', '?', and '.'
1561 * It can be used at updating multi fields.
1562 *
1563 * Use elm_genlist_realized_items_update() to update an item's all
1564 * property.
1565 *
1566 * @see elm_genlist_item_update()
1567 *
1568 * @ingroup Genlist
1569 */
1570EAPI void elm_genlist_item_fields_update(Elm_Object_Item *it, const char *parts, Elm_Genlist_Item_Field_Type itf);
1571
1572/**
1573 * Activate a genlist mode on an item
1574 *
1575 * @param it The genlist item
1576 * @param decorate_it_type Mode name
1577 * @param decorate_it_set Boolean to define set or unset mode.
1578
1579 *
1580 * A genlist mode is a different way of selecting an item. Once a mode is
1581 * activated on an item, any other selected item is immediately unselected.
1582 * This feature provides an easy way of implementing a new kind of animation
1583 * for selecting an item, without having to entirely rewrite the item style
1584 * theme. However, the elm_genlist_selected_* API can't be used to get what
1585 * item is activate for a mode.
1586 *
1587 * The current item style will still be used, but applying a genlist mode to
1588 * an item will select it using a different kind of animation.
1589 *
1590 * The current active item for a mode can be found by
1591 * elm_genlist_decorated_item_get().
1592 *
1593 * The characteristics of genlist mode are:
1594 * - Only one mode can be active at any time, and for only one item.
1595 * - Genlist handles deactivating other items when one item is activated.
1596 * - A mode is defined in the genlist theme (edc), and more modes can easily
1597 * be added.
1598 * - A mode style and the genlist item style are different things. They
1599 * can be combined to provide a default style to the item, with some kind
1600 * of animation for that item when the mode is activated.
1601 *
1602 * When a mode is activated on an item, a new view for that item is created.
1603 * The theme of this mode defines the animation that will be used to transit
1604 * the item from the old view to the new view. This second (new) view will be
1605 * active for that item while the mode is active on the item, and will be
1606 * destroyed after the mode is totally deactivated from that item.
1607 *
1608 * @see elm_genlist_mode_get()
1609 * @see elm_genlist_decorated_item_get()
1610 *
1611 * @ingroup Genlist
1612 */
1613EAPI void elm_genlist_item_decorate_mode_set(Elm_Object_Item *it, const char *decorate_it_type, Eina_Bool decorate_it_set);
1614
1615/**
1616 * Get the item's decorate mode.
1617 *
1618 * @param it The genlist item
1619 *
1620 * This function just returns the name of the item's decorate mode.
1621 *
1622 * @see elm_genlist_item_decorate_mode_set()
1623 * @see elm_genlist_decorated_item_get()
1624 *
1625 * @ingroup Genlist
1626 */
1627EAPI const char *elm_genlist_item_decorate_mode_get(const Elm_Object_Item *it);
1628
1629/**
1630 * Get active genlist mode item
1631 *
1632 * @param obj The genlist object
1633 * @return The active item for that current mode. Or @c NULL if no item is
1634 * activated with any mode.
1635 *
1636 * This function returns the item that was activated with a mode, by the
1637 * function elm_genlist_item_decorate_mode_set().
1638 *
1639 * @see elm_genlist_item_decorate_mode_set()
1640 * @see elm_genlist_mode_get()
1641 *
1642 * @ingroup Genlist
1643 */
1644EAPI const Elm_Object_Item *elm_genlist_decorated_item_get(const Evas_Object *obj);
1645
1646/**
1647 * Set reorder mode
1648 *
1649 * @param obj The genlist object
1650 * @param reorder_mode The reorder mode
1651 * (EINA_TRUE = on, EINA_FALSE = off)
1652 *
1653 * @ingroup Genlist
1654 */
1655EAPI void elm_genlist_reorder_mode_set(Evas_Object *obj, Eina_Bool reorder_mode);
1656
1657/**
1658 * Get the reorder mode
1659 *
1660 * @param obj The genlist object
1661 * @return The reorder mode
1662 * (EINA_TRUE = on, EINA_FALSE = off)
1663 *
1664 * @ingroup Genlist
1665 */
1666EAPI Eina_Bool elm_genlist_reorder_mode_get(const Evas_Object *obj);
1667
1668/**
1669 * Get the Item's Type
1670 *
1671 * @param it The genlist item
1672 * @return The item type.
1673 *
1674 * This function returns the item's type. Normally the item's type.
1675 * If it failed, return value is ELM_GENLIST_ITEM_MAX
1676 *
1677 * @ingroup Genlist
1678 */
1679EAPI Elm_Genlist_Item_Type elm_genlist_item_type_get(const Elm_Object_Item *it);
1680
1681/**
1682 * Set Genlist decorate mode
1683 *
1684 * This sets Genlist decorate mode to all items.
1685 *
1686 * @param obj The Genlist object
1687 * @param decorated The decorate mode status
1688 * (EINA_TRUE = decorate mode, EINA_FALSE = normal mode
1689 *
1690 * @ingroup Genlist
1691 */
1692EAPI void elm_genlist_decorate_mode_set(Evas_Object *obj, Eina_Bool decorated);
1693
1694/**
1695 * Get Genlist decorate mode
1696 *
1697 * @param obj The genlist object
1698 * @return The decorate mode status
1699 * (EINA_TRUE = decorate mode, EINA_FALSE = normal mode
1700 *
1701 * @ingroup Genlist
1702 */
1703EAPI Eina_Bool elm_genlist_decorate_mode_get(const Evas_Object *obj);
1704
1705/**
1706 * Set the flip state of a given genlist item.
1707 *
1708 * @param it The genlist item object
1709 * @param flip The flip mode
1710 * (EINA_TRUE = on, EINA_FALSE = off)
1711 *
1712 * This function sets the flip state of a given genlist item.
1713 * Flip mode overrides current item object.
1714 * It can be used for on-the-fly item replace.
1715 * Flip mode can be used with/without edit mode.
1716 *
1717 * @see elm_genlist_item_flip_get()
1718 *
1719 * @ingroup Genlist
1720 */
1721
1722EAPI void elm_genlist_item_flip_set(Elm_Object_Item *it, Eina_Bool flip);
1723
1724/**
1725 * Get the flip state of a given genlist item.
1726 *
1727 * @param it The genlist item object
1728 *
1729 * This function returns the flip state of a given genlist item.
1730 * If the parameter is invalid, it returns EINA_FALSE.
1731 *
1732 * @see elm_genlist_item_flip_set()
1733 *
1734 * @ingroup Genlist
1735 */
1736
1737EAPI Eina_Bool elm_genlist_item_flip_get(const Elm_Object_Item *it);
1738
1739/**
1740 * Set Genlist tree effect
1741 *
1742 * @param obj The genlist object
1743 * @param enabled The tree effect status
1744 * (EINA_TRUE = enabled, EINA_FALSE = disabled
1745 *
1746 * @ingroup Genlist
1747 */
1748EAPI void elm_genlist_tree_effect_enabled_set(Evas_Object *obj, Eina_Bool enabled);
1749
1750/**
1751 * Get Genlist tree effect
1752 *
1753 * @param obj The genlist object
1754 * @return The tree effect status
1755 * (EINA_TRUE = enabled, EINA_FALSE = disabled
1756 *
1757 * @ingroup Genlist
1758 */
1759EAPI Eina_Bool elm_genlist_tree_effect_enabled_get(const Evas_Object *obj);
1760
1761/**
1762 * Set the genlist select mode.
1763 *
1764 * @param obj The genlist object
1765 * @param mode The select mode
1766 *
1767 * elm_genlist_select_mode_set() changes item select mode in the genlist widget.
1768 * - ELM_OBJECT_SELECT_MODE_DEFAULT : Items will only call their selection func and
1769 * callback when first becoming selected. Any further clicks will
1770 * do nothing, unless you set always select mode.
1771 * - ELM_OBJECT_SELECT_MODE_ALWAYS : This means that, even if selected,
1772 * every click will make the selected callbacks be called.
1773 * - ELM_OBJECT_SELECT_MODE_NONE : This will turn off the ability to select items
1774 * entirely and they will neither appear selected nor call selected
1775 * callback functions.
1776 *
1777 * @see elm_genlist_select_mode_get()
1778 *
1779 * @ingroup Genlist
1780 */
1781EAPI void elm_genlist_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode);
1782
1783/**
1784 * Get the genlist select mode.
1785 *
1786 * @param obj The genlist object
1787 * @return The select mode
1788 * (If getting mode is failed, it returns ELM_OBJECT_SELECT_MODE_MAX)
1789 *
1790 * @see elm_genlist_select_mode_set()
1791 *
1792 * @ingroup Genlist
1793 */
1794EAPI Elm_Object_Select_Mode elm_genlist_select_mode_get(const Evas_Object *obj);
1795
1796/**
1797 * Set whether the genlist items' should be highlighted when item selected.
1798 *
1799 * @param obj The genlist object.
1800 * @param highlight @c EINA_TRUE to enable highlighting or @c EINA_FALSE to
1801 * disable it.
1802 *
1803 * This will turn on/off the highlight effect when item selection and
1804 * they will, or will not highlighted. The selected and clicked
1805 * callback functions will still be called.
1806 *
1807 * Highlight is enabled by default.
1808 *
1809 * @see elm_genlist_highlight_mode_get().
1810 *
1811 * @ingroup Genlist
1812 */
1813EAPI void elm_genlist_highlight_mode_set(Evas_Object *obj, Eina_Bool highlight);
1814
1815/**
1816 * Get whether the genlist items' should be highlighted when item selected.
1817 *
1818 * @param obj The genlist object.
1819 * @return @c EINA_TRUE means items can be highlighted. @c EINA_FALSE indicates
1820 * they can't. If @p obj is @c NULL, @c EINA_FALSE is returned.
1821 *
1822 * @see elm_genlist_highlight_mode_set() for details.
1823 *
1824 * @ingroup Genlist
1825 */
1826EAPI Eina_Bool elm_genlist_highlight_mode_get(const Evas_Object *obj);
1827
1828/**
1829 * Set the genlist item's select mode.
1830 *
1831 * @param it The genlist item object
1832 * @param mode The select mode
1833 *
1834 * elm_genlist_select_mode_set() changes item's select mode.
1835 * - ELM_OBJECT_SELECT_MODE_DEFAULT : The item will only call their selection func and
1836 * callback when first becoming selected. Any further clicks will
1837 * do nothing, unless you set always select mode.
1838 * - ELM_OBJECT_SELECT_MODE_ALWAYS : This means that, even if selected,
1839 * every click will make the selected callbacks be called.
1840 * - ELM_OBJECT_SELECT_MODE_NONE : This will turn off the ability to select the item
1841 * entirely and they will neither appear selected nor call selected
1842 * callback functions.
1843 * - ELM_OBJECT_SELECT_MODE_DISPLAY_ONLY : This will apply no-finger-size rule
1844 * with ELM_OBJECT_SELECT_MODE_NONE. No-finger-size rule makes an item can be
1845 * smaller than lower limit. Clickable objects should be bigger than
1846 * human touch point device (your finger) for some touch or
1847 * small screen devices. So it is enabled, the item can be shrink than
1848 * predefined finger-size value. And the item will be updated.
1849 *
1850 * @see elm_genlist_item_select_mode_get()
1851 *
1852 * @ingroup Genlist
1853 */
1854EAPI void
1855elm_genlist_item_select_mode_set(Elm_Object_Item *it,
1856 Elm_Object_Select_Mode mode);
1857
1858/**
1859 * Get the genlist item's select mode.
1860 *
1861 * @param it The genlist item object
1862 * @return The select mode
1863 * (If getting mode is failed, it returns ELM_OBJECT_SELECT_MODE_MAX)
1864 *
1865 * @see elm_genlist_item_select_mode_set()
1866 *
1867 * @ingroup Genlist
1868 */
1869EAPI Elm_Object_Select_Mode
1870elm_genlist_item_select_mode_get(const Elm_Object_Item *it);
1871
1872/**
1873 * @}
1874 */
diff --git a/libraries/elementary/src/lib/elm_gesture_layer.c b/libraries/elementary/src/lib/elm_gesture_layer.c
new file mode 100644
index 0000000..2d6dcc7
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_gesture_layer.c
@@ -0,0 +1,3520 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3/** @defgroup Elm_Gesture_Layer Gesture Layer */
4
5/* Some defaults */
6#define ELM_MOUSE_DEVICE 0
7/* ELM_GESTURE_NEGATIVE_ANGLE - magic number says we didn't compute this yet */
8#define ELM_GESTURE_NEGATIVE_ANGLE (-1.0) /* Magic number */
9#define ELM_GESTURE_MOMENTUM_DELAY 25
10#define ELM_GESTURE_MOMENTUM_TIMEOUT 50
11#define ELM_GESTURE_MULTI_TIMEOUT 50
12#define ELM_GESTURE_MINIMUM_MOMENTUM 0.001
13
14/* Some Trigo values */
15#define RAD_90DEG M_PI_2
16#define RAD_180DEG M_PI
17#define RAD_270DEG (M_PI_2 * 3)
18#define RAD_360DEG (M_PI * 2)
19/* #define DEBUG_GESTURE_LAYER 1 */
20
21#define RAD2DEG(x) ((x) * 57.295779513)
22#define DEG2RAD(x) ((x) / 57.295779513)
23
24static void *
25_glayer_bufdup(void *buf, size_t size)
26{
27 void *p;
28 p = malloc(size);
29 memcpy(p, buf, size);
30 return p;
31}
32#define COPY_EVENT_INFO(EV) _glayer_bufdup(EV, sizeof(*EV))
33
34
35#define SET_TEST_BIT(P) do { \
36 P->test = P->fn[ELM_GESTURE_STATE_START].cb || P->fn[ELM_GESTURE_STATE_MOVE].cb || P->fn[ELM_GESTURE_STATE_END].cb || P->fn[ELM_GESTURE_STATE_ABORT].cb; \
37} while (0)
38
39#define IS_TESTED(T) ((wd->gesture[T]) ? wd->gesture[T]->test : EINA_FALSE)
40
41/**
42 * @internal
43 *
44 * @struct _Func_Data
45 * Struct holds callback information.
46 *
47 * @ingroup Elm_Gesture_Layer
48 */
49struct _Func_Data
50{
51 void *user_data; /**< Holds user data to CB (like sd) */
52 Elm_Gesture_Event_Cb cb;
53};
54
55/**
56 * @internal
57 *
58 * @typedef Func_Data
59 * type for callback information
60 *
61 * @ingroup Elm_Gesture_Layer
62 */
63typedef struct _Func_Data Func_Data;
64
65/**
66 * @internal
67 *
68 * @struct _Gesture_Info
69 * Struct holds gesture info
70 *
71 * @ingroup Elm_Gesture_Layer
72 */
73struct _Gesture_Info
74{
75 Evas_Object *obj;
76 void *data; /**< Holds gesture intemidiate processing data */
77 Func_Data fn[ELM_GESTURE_STATE_ABORT + 1]; /**< Callback info for states */
78 Elm_Gesture_Type g_type; /**< gesture type */
79 Elm_Gesture_State state; /**< gesture state */
80 void *info; /**< Data for the state callback */
81 Eina_Bool test; /**< if true this gesture should be tested on input */
82};
83
84/**
85 * @internal
86 *
87 * @typedef Gesture_Info
88 * Type for _Gesture_Info
89 *
90 * @ingroup Elm_Gesture_Layer
91 */
92typedef struct _Gesture_Info Gesture_Info;
93
94/**
95 * @internal
96 *
97 * @struct _Event_History
98 * Struct holds event history.
99 * These events are repeated if no gesture found.
100 *
101 * @ingroup Elm_Gesture_Layer
102 */
103struct _Event_History
104{
105 EINA_INLIST;
106 void *event;
107 Evas_Callback_Type event_type;
108};
109
110/**
111 * @internal
112 *
113 * @typedef Event_History
114 * Type for _Event_History
115 *
116 * @ingroup Elm_Gesture_Layer
117 */
118typedef struct _Event_History Event_History;
119
120/**
121 * @internal
122 *
123 * @struct _Pointer_Event
124 * Struct holds pointer-event info
125 * This is a generic pointer event structure
126 *
127 * @ingroup Elm_Gesture_Layer
128 */
129struct _Pointer_Event
130{
131 Evas_Coord x, y;
132 unsigned int timestamp;
133 int device;
134 Evas_Callback_Type event_type;
135};
136
137/**
138 * @internal
139 *
140 * @typedef Pointer_Event
141 * Type for generic pointer event structure
142 *
143 * @ingroup Elm_Gesture_Layer
144 */
145typedef struct _Pointer_Event Pointer_Event;
146
147/* All *Type structs hold result for the user in 'info' field
148 * The rest is gesture processing intermediate data.
149 * NOTE: info field must be FIRST in the struct.
150 * This is used when reporting ABORT in event_history_clear() */
151struct _Taps_Type
152{
153 Elm_Gesture_Taps_Info info;
154 unsigned int sum_x;
155 unsigned int sum_y;
156 unsigned int n_taps_needed;
157 unsigned int n_taps;
158 Eina_List *l;
159};
160typedef struct _Taps_Type Taps_Type;
161
162struct _Long_Tap_Type
163{
164 Elm_Gesture_Taps_Info info;
165 Evas_Coord center_x;
166 Evas_Coord center_y;
167 unsigned int max_touched;
168 Ecore_Timer *timeout; /* When this expires, long tap STARTed */
169 Eina_List *touched;
170};
171typedef struct _Long_Tap_Type Long_Tap_Type;
172
173struct _Momentum_Type
174{ /* Fields used by _line_test() */
175 Elm_Gesture_Momentum_Info info;
176 Evas_Coord_Point line_st;
177 Evas_Coord_Point line_end;
178 unsigned int t_st_x; /* Time start on X */
179 unsigned int t_st_y; /* Time start on Y */
180 unsigned int t_end; /* Time end */
181 unsigned int t_up; /* Recent up event time */
182 int xdir, ydir;
183};
184typedef struct _Momentum_Type Momentum_Type;
185
186struct _Line_Data
187{
188 Evas_Coord_Point line_st;
189 Evas_Coord_Point line_end;
190 Evas_Coord line_length;
191 unsigned int t_st; /* Time start */
192 unsigned int t_end; /* Time end */
193 int device;
194 double line_angle; /* Current angle of line */
195};
196typedef struct _Line_Data Line_Data;
197
198struct _Line_Type
199{ /* Fields used by _line_test() */
200 Elm_Gesture_Line_Info info;
201 Eina_List *list; /* List of Line_Data */
202};
203typedef struct _Line_Type Line_Type;
204
205struct _Zoom_Type
206{ /* Fields used by _zoom_test() */
207 Elm_Gesture_Zoom_Info info;
208 Pointer_Event zoom_st;
209 Pointer_Event zoom_mv;
210 Pointer_Event zoom_st1;
211 Pointer_Event zoom_mv1;
212 Evas_Event_Mouse_Wheel *zoom_wheel;
213 Evas_Coord zoom_base; /* Holds gap between fingers on zoom-start */
214 Evas_Coord zoom_distance_tolerance;
215 unsigned int m_st_tm; /* momentum start time */
216 unsigned int m_prev_tm; /* momentum prev time */
217 int dir; /* Direction: 1=zoom-in, (-1)=zoom-out */
218 double m_base; /* zoom value when momentum starts */
219 double next_step;
220};
221typedef struct _Zoom_Type Zoom_Type;
222
223struct _Rotate_Type
224{ /* Fields used by _rotation_test() */
225 Elm_Gesture_Rotate_Info info;
226 Pointer_Event rotate_st;
227 Pointer_Event rotate_mv;
228 Pointer_Event rotate_st1;
229 Pointer_Event rotate_mv1;
230 unsigned int prev_momentum_tm; /* timestamp of prev_momentum */
231 double prev_momentum; /* Snapshot of momentum 0.01 sec ago */
232 double accum_momentum;
233 double rotate_angular_tolerance;
234 double next_step;
235};
236typedef struct _Rotate_Type Rotate_Type;
237
238struct _Widget_Data
239{
240 Evas_Object *target; /* Target Widget */
241 Event_History *event_history_list;
242
243 int line_min_length;
244 Evas_Coord zoom_distance_tolerance;
245 Evas_Coord line_distance_tolerance;
246 double line_angular_tolerance;
247 double zoom_wheel_factor; /* mouse wheel zoom steps */
248 double zoom_finger_factor; /* used for zoom factor */
249 double rotate_angular_tolerance;
250 unsigned int flick_time_limit_ms;
251 double long_tap_start_timeout;
252 Eina_Bool glayer_continues_enable;
253
254 double zoom_step;
255 double rotate_step;
256
257 Gesture_Info *gesture[ELM_GESTURE_LAST];
258 Ecore_Timer *dbl_timeout; /* When this expires, dbl click/taps ABORTed */
259 Eina_List *pending; /* List of devices need to refeed *UP event */
260 Eina_List *touched; /* Information of touched devices */
261
262 Eina_Bool repeat_events : 1;
263};
264typedef struct _Widget_Data Widget_Data;
265
266static const char *widtype = NULL;
267static void _del_hook(Evas_Object *obj);
268
269static Eina_Bool _event_history_clear(Evas_Object *obj);
270static void _reset_states(Widget_Data *wd);
271static void _key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
272static void _key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
273static void _zoom_with_wheel_test(Evas_Object *obj, void *event_info, Evas_Callback_Type event_type, Elm_Gesture_Type g_type);
274static void _mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
275static void _mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
276static void _mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
277static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
278
279static void _multi_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
280static void _multi_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
281static void _multi_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info);
282
283/* START - Functions to manage touched-device list */
284/**
285 * @internal
286 * This function is used to find if device is touched
287 *
288 * @ingroup Elm_Gesture_Layer
289 */
290static int
291compare_device(const void *data1, const void *data2)
292{ /* Compare the two device numbers */
293 return (((Pointer_Event *) data1)->device -((Pointer_Event *) data2)->device);
294}
295
296/**
297 * @internal
298 *
299 * Remove Pointer Event from touched device list
300 * @param list Pointer to touched device list.
301 * @param Pointer_Event Pointer to PE.
302 *
303 * @ingroup Elm_Gesture_Layer
304 */
305static Eina_List *
306_remove_touched_device(Eina_List *list, Pointer_Event *pe)
307{
308 Eina_List *lst = NULL;
309 Pointer_Event *p = eina_list_search_unsorted(list, compare_device, pe);
310 if (p)
311 {
312 lst = eina_list_remove(list, p);
313 free(p);
314 return lst;
315 }
316
317 return list;
318}
319
320/**
321 * @internal
322 *
323 * Recoed Pointer Event in touched device list
324 * Note: This fuction allocates memory for PE event
325 * This memory is released in _remove_touched_device()
326 * @param list Pointer to touched device list.
327 * @param Pointer_Event Pointer to PE.
328 *
329 * @ingroup Elm_Gesture_Layer
330 */
331static Eina_List *
332_add_touched_device(Eina_List *list, Pointer_Event *pe)
333{
334 Pointer_Event *p = eina_list_search_unsorted(list, compare_device, pe);
335 if (p)
336 { /* We like to track device touch-position, overwrite info */
337 memcpy(p, pe, sizeof(Pointer_Event));
338 return list;
339 }
340
341 if ((pe->event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
342 (pe->event_type == EVAS_CALLBACK_MULTI_DOWN))
343 { /* Add touched device on DOWN event only */
344 p = malloc(sizeof(Pointer_Event));
345 /* Freed in _remove_touched_device() */
346 memcpy(p, pe, sizeof(Pointer_Event));
347 return eina_list_append(list, p);
348 }
349
350 return list;
351}
352/* END - Functions to manage touched-device list */
353
354/**
355 * @internal
356 *
357 * Get event flag
358 * @param event_info pointer to event.
359 *
360 * @ingroup Elm_Gesture_Layer
361 */
362static Evas_Event_Flags
363_get_event_flag(void *event_info, Evas_Callback_Type event_type)
364{
365 switch(event_type)
366 {
367 case EVAS_CALLBACK_MOUSE_IN:
368 return ((Evas_Event_Mouse_In *) event_info)->event_flags;
369 case EVAS_CALLBACK_MOUSE_OUT:
370 return ((Evas_Event_Mouse_Out *) event_info)->event_flags;
371 case EVAS_CALLBACK_MOUSE_DOWN:
372 return ((Evas_Event_Mouse_Down *) event_info)->event_flags;
373 case EVAS_CALLBACK_MOUSE_MOVE:
374 return ((Evas_Event_Mouse_Move *) event_info)->event_flags;
375 case EVAS_CALLBACK_MOUSE_UP:
376 return ((Evas_Event_Mouse_Up *) event_info)->event_flags;
377 case EVAS_CALLBACK_MOUSE_WHEEL:
378 return ((Evas_Event_Mouse_Wheel *) event_info)->event_flags;
379 case EVAS_CALLBACK_MULTI_DOWN:
380 return ((Evas_Event_Multi_Down *) event_info)->event_flags;
381 case EVAS_CALLBACK_MULTI_MOVE:
382 return ((Evas_Event_Multi_Move *) event_info)->event_flags;
383 case EVAS_CALLBACK_MULTI_UP:
384 return ((Evas_Event_Multi_Up *) event_info)->event_flags;
385 case EVAS_CALLBACK_KEY_DOWN:
386 return ((Evas_Event_Key_Down *) event_info)->event_flags;
387 case EVAS_CALLBACK_KEY_UP:
388 return ((Evas_Event_Key_Up *) event_info)->event_flags;
389 default:
390 return EVAS_EVENT_FLAG_NONE;
391 }
392}
393
394/**
395 * @internal
396 *
397 * Sets event flag to value returned from user callback
398 * @param wd Widget Data
399 * @param event_info pointer to event.
400 * @param event_type what type was ev (mouse down, etc...)
401 * @param ev_flags event flags
402 *
403 * @ingroup Elm_Gesture_Layer
404 */
405static void
406consume_event(Widget_Data *wd, void *event_info,
407 Evas_Callback_Type event_type, Evas_Event_Flags ev_flags)
408{ /* Mark EVAS_EVENT_FLAG_ON_HOLD on events that are used by gesture layer */
409 /* ev_flags != EVAS_EVENT_FLAG_NONE means target used event and g-layer */
410 /* should not refeed this event. */
411 if (!event_info)
412 return; /* This happens when restarting gestures */
413
414 if ((ev_flags) || (!wd->repeat_events))
415 {
416 switch(event_type)
417 {
418 case EVAS_CALLBACK_MOUSE_DOWN:
419 ((Evas_Event_Mouse_Down *) event_info)->event_flags |= ev_flags;
420 break;
421 case EVAS_CALLBACK_MOUSE_MOVE:
422 ((Evas_Event_Mouse_Move *) event_info)->event_flags |= ev_flags;
423 break;
424 case EVAS_CALLBACK_MOUSE_UP:
425 ((Evas_Event_Mouse_Up *) event_info)->event_flags |= ev_flags;
426 break;
427 case EVAS_CALLBACK_MOUSE_WHEEL:
428 ((Evas_Event_Mouse_Wheel *) event_info)->event_flags |= ev_flags;
429 break;
430 case EVAS_CALLBACK_MULTI_DOWN:
431 ((Evas_Event_Multi_Down *) event_info)->event_flags |= ev_flags;
432 break;
433 case EVAS_CALLBACK_MULTI_MOVE:
434 ((Evas_Event_Multi_Move *) event_info)->event_flags |= ev_flags;
435 break;
436 case EVAS_CALLBACK_MULTI_UP:
437 ((Evas_Event_Multi_Up *) event_info)->event_flags |= ev_flags;
438 break;
439 case EVAS_CALLBACK_KEY_DOWN:
440 ((Evas_Event_Key_Down *) event_info)->event_flags |= ev_flags;
441 break;
442 case EVAS_CALLBACK_KEY_UP:
443 ((Evas_Event_Key_Up *) event_info)->event_flags |= ev_flags;
444 break;
445 default:
446 return;
447 }
448 }
449}
450
451/**
452 * @internal
453 *
454 * Report current state of a gesture by calling user callback.
455 * @param gesture what gesture state we report.
456 * @param info inforamtion for user callback
457 *
458 * @ingroup Elm_Gesture_Layer
459 */
460static Evas_Event_Flags
461_report_state(Gesture_Info *gesture, void *info)
462{ /* We report current state (START, MOVE, END, ABORT), once */
463#if defined(DEBUG_GESTURE_LAYER)
464 printf("%s reporting gesture=<%d> state=<%d>\n" , __func__, gesture->g_type,
465 gesture->state);
466#endif
467 if ((gesture->state != ELM_GESTURE_STATE_UNDEFINED) &&
468 (gesture->fn[gesture->state].cb))
469 { /* Fill state-info struct and send ptr to user callback */
470 return gesture->fn[gesture->state].cb(
471 gesture->fn[gesture->state].user_data, info);
472 }
473
474 return EVAS_EVENT_FLAG_NONE;
475}
476
477/**
478 * @internal
479 *
480 * Update state for a given gesture.
481 * We may update gesture state to:
482 * UNDEFINED - current input did not start gesure yet.
483 * START - gesture started according to input.
484 * MOVE - gusture in progress.
485 * END - gesture completed according to input.
486 * ABORT - input does not matches gesure.
487 * note that we may move from UNDEFINED to ABORT
488 * because we may detect that gesture will not START
489 * with a given input.
490 *
491 * @param g given gesture to change state.
492 * @param s gesure new state.
493 * @param info buffer to be sent to user callback on report_state.
494 * @param force makes report_state to report the new-state even
495 * if its same as current state. Works for MOVE - gesture in progress.
496 *
497 * @ingroup Elm_Gesture_Layer
498 */
499static Evas_Event_Flags
500_set_state(Gesture_Info *g, Elm_Gesture_State s,
501 void *info, Eina_Bool force)
502{
503 Elm_Gesture_State old_state;
504 if ((g->state == s) && (!force))
505 return EVAS_EVENT_FLAG_NONE;
506
507 old_state = g->state;
508
509 g->state = s;
510 g->info = info; /* Information for user callback */
511 if ((g->state == ELM_GESTURE_STATE_ABORT) ||
512 (g->state == ELM_GESTURE_STATE_END))
513 g->test = EINA_FALSE;
514
515 if ((g->state != ELM_GESTURE_STATE_UNDEFINED) &&
516 (!((old_state == ELM_GESTURE_STATE_UNDEFINED) &&
517 (s == ELM_GESTURE_STATE_ABORT))))
518 return _report_state(g, g->info);
519
520 return EVAS_EVENT_FLAG_NONE;
521}
522
523/**
524 * @internal
525 *
526 * This resets all gesture states and sets test-bit.
527 * this is used for restarting gestures to listen to input.
528 * happens after we complete a gesture or no gesture was detected.
529 * @param wd Widget data of the gesture-layer object.
530 *
531 * @ingroup Elm_Gesture_Layer
532 */
533static void
534_reset_states(Widget_Data *wd)
535{
536 int i;
537 Gesture_Info *p;
538 for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
539 {
540 p = wd->gesture[i];
541 if (p)
542 {
543 _set_state(p, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
544 SET_TEST_BIT(p);
545 }
546 }
547}
548
549/**
550 * @internal
551 *
552 * if gesture was NOT detected AND we only have gestures in ABORT state
553 * we clear history immediately to be ready for input.
554 *
555 * @param obj The gesture-layer object.
556 * @return TRUE on event history_clear
557 *
558 * @ingroup Elm_Gesture_Layer
559 */
560static Eina_Bool
561_clear_if_finished(Evas_Object *obj)
562{
563 Widget_Data *wd = elm_widget_data_get(obj);
564 if (!wd) return EINA_FALSE;
565 int i;
566
567 /* Clear history if all we have aborted gestures */
568 Eina_Bool reset_s = EINA_TRUE, all_undefined = EINA_TRUE;
569 for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
570 { /* If no gesture started and all we have aborted gestures, reset all */
571 Gesture_Info *p = wd->gesture[i];
572 if ((p) && (p->state != ELM_GESTURE_STATE_UNDEFINED))
573 {
574 if ((p->state == ELM_GESTURE_STATE_START) ||
575 (p->state == ELM_GESTURE_STATE_MOVE))
576 reset_s = EINA_FALSE;
577
578 all_undefined = EINA_FALSE;
579 }
580 }
581
582 if (reset_s && (!all_undefined))
583 return _event_history_clear(obj);
584
585 return EINA_FALSE;
586}
587
588static Eina_Bool
589_inside(Evas_Coord xx1, Evas_Coord yy1, Evas_Coord xx2, Evas_Coord yy2)
590{
591 int w = _elm_config->finger_size >> 1; /* Finger size devided by 2 */
592 if (xx1 < (xx2 - w))
593 return EINA_FALSE;
594
595 if (xx1 > (xx2 + w))
596 return EINA_FALSE;
597
598 if (yy1 < (yy2 - w))
599 return EINA_FALSE;
600
601 if (yy1 > (yy2 + w))
602 return EINA_FALSE;
603
604 return EINA_TRUE;
605}
606
607/* All *test_reset() funcs are called to clear
608 * gesture intermediate data.
609 * This happens when we need to reset our tests.
610 * for example when gesture is detected or all ABORTed. */
611static void
612_tap_gestures_test_reset(Gesture_Info *gesture)
613{
614 if (!gesture)
615 return;
616
617 Widget_Data *wd = elm_widget_data_get(gesture->obj);
618 wd->dbl_timeout = NULL;
619 Eina_List *data;
620 Pointer_Event *pe;
621
622 if (!gesture->data)
623 return;
624
625 EINA_LIST_FREE(((Taps_Type *) gesture->data)->l, data)
626 EINA_LIST_FREE(data, pe)
627 free(pe);
628
629 memset(gesture->data, 0, sizeof(Taps_Type));
630}
631
632/* All *test_reset() funcs are called to clear
633 * gesture intermediate data.
634 * This happens when we need to reset our tests.
635 * for example when gesture is detected or all ABORTed. */
636static void
637_n_long_tap_test_reset(Gesture_Info *gesture)
638{
639 if (!gesture)
640 return;
641
642 if (!gesture->data)
643 return;
644
645 Long_Tap_Type *st = gesture->data;
646 Eina_List *l;
647 Pointer_Event *p;
648 EINA_LIST_FOREACH(st->touched, l, p)
649 free(p);
650
651 eina_list_free(st->touched);
652 if (st->timeout)
653 {
654 ecore_timer_del(st->timeout);
655 st->timeout = NULL;
656 }
657 memset(gesture->data, 0, sizeof(Long_Tap_Type));
658}
659
660static void
661_momentum_test_reset(Gesture_Info *gesture)
662{
663 if (!gesture)
664 return;
665
666 if (!gesture->data)
667 return;
668
669 memset(gesture->data, 0, sizeof(Momentum_Type));
670}
671
672static void
673_line_data_reset(Line_Data *st)
674{
675 if (!st)
676 return;
677
678 memset(st, 0, sizeof(Line_Data));
679 st->line_angle = ELM_GESTURE_NEGATIVE_ANGLE;
680}
681
682static void
683_line_test_reset(Gesture_Info *gesture)
684{
685 if (!gesture)
686 return;
687
688 if (!gesture->data)
689 return;
690
691 Line_Type *st = gesture->data;
692 Eina_List *list = st->list;
693 Eina_List *l;
694 Line_Data *t_line;
695 EINA_LIST_FOREACH(list, l, t_line)
696 free(t_line);
697
698 eina_list_free(list);
699 st->list = NULL;
700}
701
702static void
703_zoom_test_reset(Gesture_Info *gesture)
704{
705 if (!gesture)
706 return;
707
708 if (!gesture->data)
709 return;
710
711 Widget_Data *wd = elm_widget_data_get(gesture->obj);
712 Zoom_Type *st = gesture->data;
713 Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
714 evas_object_evas_get(wd->target), "Control");
715 evas_object_key_ungrab(wd->target, "Control_L", mask, 0);
716 evas_object_key_ungrab(wd->target, "Control_R", mask, 0);
717
718 memset(st, 0, sizeof(Zoom_Type));
719 st->zoom_distance_tolerance = wd->zoom_distance_tolerance;
720 st->info.zoom = 1.0;
721}
722
723static void
724_rotate_test_reset(Gesture_Info *gesture)
725{
726 if (!gesture)
727 return;
728
729 if (!gesture->data)
730 return;
731
732 Widget_Data *wd = elm_widget_data_get(gesture->obj);
733 Rotate_Type *st = gesture->data;
734
735 memset(st, 0, sizeof(Rotate_Type));
736 st->info.base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
737 st->rotate_angular_tolerance = wd->rotate_angular_tolerance;
738}
739
740
741/**
742 * @internal
743 *
744 * We register callbacks when gesture layer is attached to an object
745 * or when its enabled after disable.
746 *
747 * @param obj The gesture-layer object.
748 *
749 * @ingroup Elm_Gesture_Layer
750 */
751static void
752_register_callbacks(Evas_Object *obj)
753{
754 Widget_Data *wd = elm_widget_data_get(obj);
755 if (!wd) return;
756
757 if (wd->target)
758 {
759 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_DOWN,
760 _mouse_down, obj);
761 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_MOVE,
762 _mouse_move, obj);
763 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_UP,
764 _mouse_up, obj);
765
766 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOUSE_WHEEL,
767 _mouse_wheel, obj);
768
769 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MULTI_DOWN,
770 _multi_down, obj);
771 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MULTI_MOVE,
772 _multi_move, obj);
773 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MULTI_UP,
774 _multi_up, obj);
775
776 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_KEY_DOWN,
777 _key_down_cb, obj);
778 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_KEY_UP,
779 _key_up_cb, obj);
780 }
781}
782
783/**
784 * @internal
785 *
786 * We unregister callbacks when gesture layer is disabled.
787 *
788 * @param obj The gesture-layer object.
789 *
790 * @ingroup Elm_Gesture_Layer
791 */
792static void
793_unregister_callbacks(Evas_Object *obj)
794{
795 Widget_Data *wd = elm_widget_data_get(obj);
796 if (!wd) return;
797
798 if (wd->target)
799 {
800 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_DOWN,
801 _mouse_down);
802 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_MOVE,
803 _mouse_move);
804 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_UP,
805 _mouse_up);
806
807 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MOUSE_WHEEL,
808 _mouse_wheel);
809
810 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MULTI_DOWN,
811 _multi_down);
812
813 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MULTI_MOVE,
814 _multi_move);
815
816 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_MULTI_UP,
817 _multi_up);
818
819 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_KEY_DOWN,
820 _key_down_cb);
821 evas_object_event_callback_del(wd->target, EVAS_CALLBACK_KEY_UP,
822 _key_up_cb);
823 }
824}
825
826/* START - Event history list handling functions */
827/**
828 * @internal
829 * This function is used to find if device number
830 * is found in a list of devices.
831 * The list contains devices for refeeding *UP event
832 *
833 * @ingroup Elm_Gesture_Layer
834 */
835static int
836device_in_pending_list(const void *data1, const void *data2)
837{ /* Compare the two device numbers */
838 return (((intptr_t) data1) - ((intptr_t) data2));
839}
840
841/**
842 * @internal
843 *
844 * This functions adds device to refeed-pending device list
845 * @ingroup Elm_Gesture_Layer
846 */
847static Eina_List *
848_add_device_pending(Eina_List *list, void *event, Evas_Callback_Type event_type)
849{
850 int device = ELM_MOUSE_DEVICE;
851 switch(event_type)
852 {
853 case EVAS_CALLBACK_MOUSE_DOWN:
854 break;
855 case EVAS_CALLBACK_MULTI_DOWN:
856 device = ((Evas_Event_Multi_Down *) event)->device;
857 break;
858 default:
859 return list;
860 }
861
862 if (!eina_list_search_unsorted_list(list, device_in_pending_list,
863 (void *)(intptr_t)device))
864 {
865 return eina_list_append(list, (void *)(intptr_t)device);
866 }
867
868 return list;
869}
870
871/**
872 * @internal
873 *
874 * This functions returns pending-device node
875 * @ingroup Elm_Gesture_Layer
876 */
877static Eina_List *
878_device_is_pending(Eina_List *list, void *event, Evas_Callback_Type event_type)
879{
880 int device = ELM_MOUSE_DEVICE;
881 switch(event_type)
882 {
883 case EVAS_CALLBACK_MOUSE_UP:
884 break;
885 case EVAS_CALLBACK_MULTI_UP:
886 device = ((Evas_Event_Multi_Up *) event)->device;
887 break;
888 default:
889 return NULL;
890 }
891
892 return eina_list_search_unsorted_list(list, device_in_pending_list,
893 (void *)(intptr_t)device);
894}
895
896/**
897 * @internal
898 *
899 * This function reports ABORT to all none-detected gestures
900 * Then resets test bits for all desired gesures
901 * and clears input-events history.
902 * note: if no gesture was detected, events from history list
903 * are streamed to the widget because it's unused by layer.
904 * user may cancel refeed of events by setting repeat events.
905 *
906 * @param obj The gesture-layer object.
907 *
908 * @ingroup Elm_Gesture_Layer
909 */
910static Eina_Bool
911_event_history_clear(Evas_Object *obj)
912{
913 Widget_Data *wd = elm_widget_data_get(obj);
914 if (!wd) return EINA_FALSE;
915
916 int i;
917 Gesture_Info *p;
918 Evas *e = evas_object_evas_get(obj);
919 Eina_Bool gesture_found = EINA_FALSE;
920 for (i = ELM_GESTURE_FIRST; i < ELM_GESTURE_LAST; i++)
921 {
922 p = wd->gesture[i];
923 if (p)
924 {
925 if (p->state == ELM_GESTURE_STATE_END)
926 gesture_found = EINA_TRUE;
927 else
928 { /* Report ABORT to all gestures that still not finished */
929 _set_state(p, ELM_GESTURE_STATE_ABORT, wd->gesture[i]->info,
930 EINA_FALSE);
931 }
932 }
933 }
934
935 _reset_states(wd); /* we are ready to start testing for gestures again */
936
937 /* Clear all gestures intermediate data */
938 if (IS_TESTED(ELM_GESTURE_N_LONG_TAPS))
939 { /* We do not clear a long-tap gesture if fingers still on surface */
940 /* and gesture timer still pending to test gesture state */
941 Long_Tap_Type *st = wd->gesture[ELM_GESTURE_N_LONG_TAPS]->data;
942 if ((st) && /* st not allocated if clear occurs before 1st input */
943 ((!eina_list_count(st->touched)) || (!st->timeout)))
944 _n_long_tap_test_reset(wd->gesture[ELM_GESTURE_N_LONG_TAPS]);
945 }
946
947 if (wd->dbl_timeout)
948 {
949 ecore_timer_del(wd->dbl_timeout);
950 wd->dbl_timeout = NULL;
951 }
952
953 _tap_gestures_test_reset(wd->gesture[ELM_GESTURE_N_TAPS]);
954 _tap_gestures_test_reset(wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
955 _tap_gestures_test_reset(wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
956 _momentum_test_reset(wd->gesture[ELM_GESTURE_MOMENTUM]);
957 _line_test_reset(wd->gesture[ELM_GESTURE_N_LINES]);
958 _line_test_reset(wd->gesture[ELM_GESTURE_N_FLICKS]);
959 _zoom_test_reset(wd->gesture[ELM_GESTURE_ZOOM]);
960 _rotate_test_reset(wd->gesture[ELM_GESTURE_ROTATE]);
961
962 /* Disable gesture layer so refeeded events won't be consumed by it */
963 _unregister_callbacks(obj);
964 while (wd->event_history_list)
965 {
966 Event_History *t;
967 t = wd->event_history_list;
968 Eina_List *pending = _device_is_pending(wd->pending,
969 wd->event_history_list->event,
970 wd->event_history_list->event_type);
971
972 /* Refeed events if no gesture matched input */
973 if (pending || ((!gesture_found) && (!wd->repeat_events)))
974 {
975 evas_event_refeed_event(e, wd->event_history_list->event,
976 wd->event_history_list->event_type);
977
978 if (pending)
979 {
980 wd->pending = eina_list_remove_list(wd->pending, pending);
981 }
982 else
983 {
984 wd->pending = _add_device_pending(wd->pending,
985 wd->event_history_list->event,
986 wd->event_history_list->event_type);
987 }
988 }
989
990 free(wd->event_history_list->event);
991 wd->event_history_list = (Event_History *) eina_inlist_remove(
992 EINA_INLIST_GET(wd->event_history_list),
993 EINA_INLIST_GET(wd->event_history_list));
994 free(t);
995 }
996 _register_callbacks(obj);
997 return EINA_TRUE;
998}
999
1000/**
1001 * @internal
1002 *
1003 * This function copies input events.
1004 * We copy event info before adding it to history.
1005 * The memory is freed when we clear history.
1006 *
1007 * @param event the event to copy
1008 * @param event_type event type to copy
1009 *
1010 * @ingroup Elm_Gesture_Layer
1011 */
1012static void *
1013_copy_event_info(void *event, Evas_Callback_Type event_type)
1014{
1015 switch(event_type)
1016 {
1017 case EVAS_CALLBACK_MOUSE_DOWN:
1018 return COPY_EVENT_INFO((Evas_Event_Mouse_Down *) event);
1019 break;
1020 case EVAS_CALLBACK_MOUSE_MOVE:
1021 return COPY_EVENT_INFO((Evas_Event_Mouse_Move *) event);
1022 break;
1023 case EVAS_CALLBACK_MOUSE_UP:
1024 return COPY_EVENT_INFO((Evas_Event_Mouse_Up *) event);
1025 break;
1026 case EVAS_CALLBACK_MOUSE_WHEEL:
1027 return COPY_EVENT_INFO((Evas_Event_Mouse_Wheel *) event);
1028 break;
1029 case EVAS_CALLBACK_MULTI_DOWN:
1030 return COPY_EVENT_INFO((Evas_Event_Multi_Down *) event);
1031 break;
1032 case EVAS_CALLBACK_MULTI_MOVE:
1033 return COPY_EVENT_INFO((Evas_Event_Multi_Move *) event);
1034 break;
1035 case EVAS_CALLBACK_MULTI_UP:
1036 return COPY_EVENT_INFO((Evas_Event_Multi_Up *) event);
1037 break;
1038 case EVAS_CALLBACK_KEY_DOWN:
1039 return COPY_EVENT_INFO((Evas_Event_Key_Down *) event);
1040 break;
1041 case EVAS_CALLBACK_KEY_UP:
1042 return COPY_EVENT_INFO((Evas_Event_Key_Up *) event);
1043 break;
1044 default:
1045 return NULL;
1046 }
1047}
1048
1049static Eina_Bool
1050_event_history_add(Evas_Object *obj, void *event, Evas_Callback_Type event_type)
1051{
1052 Widget_Data *wd = elm_widget_data_get(obj);
1053 Event_History *ev;
1054 if (!wd) return EINA_FALSE;
1055
1056 ev = malloc(sizeof(Event_History));
1057 ev->event = _copy_event_info(event, event_type); /* Freed on event_history_clear */
1058 ev->event_type = event_type;
1059 wd->event_history_list = (Event_History *) eina_inlist_append(
1060 EINA_INLIST_GET(wd->event_history_list), EINA_INLIST_GET(ev));
1061
1062 return EINA_TRUE;
1063}
1064/* END - Event history list handling functions */
1065
1066static void
1067_del_hook(Evas_Object *obj)
1068{
1069 Widget_Data *wd = elm_widget_data_get(obj);
1070 if (!wd) return;
1071
1072 _event_history_clear(obj);
1073 eina_list_free(wd->pending);
1074
1075 Pointer_Event *data;
1076 EINA_LIST_FREE(wd->touched, data)
1077 free(data);
1078
1079 if (!elm_widget_disabled_get(obj))
1080 _unregister_callbacks(obj);
1081
1082 /* Free all gestures internal data structures */
1083 int i;
1084 for (i = 0; i < ELM_GESTURE_LAST; i++)
1085 if (wd->gesture[i])
1086 {
1087 if (wd->gesture[i]->data)
1088 free(wd->gesture[i]->data);
1089
1090 free(wd->gesture[i]);
1091 }
1092
1093 free(wd);
1094}
1095
1096static int
1097compare_match_fingers(const void *data1, const void *data2)
1098{ /* Compare coords of first item in list to cur coords */
1099 const Pointer_Event *pe1 = eina_list_data_get(data1);
1100 const Pointer_Event *pe2 = data2;
1101
1102 if (_inside(pe1->x, pe1->y, pe2->x, pe2->y))
1103 return 0;
1104 else if (pe1->x < pe2->x)
1105 return -1;
1106 else
1107 {
1108 if (pe1->x == pe2->x)
1109 return pe1->y - pe2->y;
1110 else
1111 return 1;
1112 }
1113}
1114
1115static int
1116compare_pe_device(const void *data1, const void *data2)
1117{ /* Compare device of first item in list to our pe device */
1118 const Pointer_Event *pe1 = eina_list_data_get(data1);
1119 const Pointer_Event *pe2 = data2;
1120
1121 /* Only match if last was a down event */
1122 if ((pe1->event_type != EVAS_CALLBACK_MULTI_DOWN) &&
1123 (pe1->event_type != EVAS_CALLBACK_MOUSE_DOWN))
1124 return 1;
1125
1126 if (pe1->device == pe2->device)
1127 return 0;
1128 else if (pe1->device < pe2->device)
1129 return -1;
1130 else
1131 return 1;
1132}
1133
1134static Eina_List*
1135_record_pointer_event(Taps_Type *st, Eina_List *pe_list, Pointer_Event *pe,
1136 Widget_Data *wd, void *event_info, Evas_Callback_Type event_type)
1137{ /* Keep copy of pe and record it in list */
1138 Pointer_Event *p = malloc(sizeof(Pointer_Event));
1139 memcpy(p, pe, sizeof(Pointer_Event));
1140 consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
1141
1142 st->sum_x += pe->x;
1143 st->sum_y += pe->y;
1144 st->n_taps++;
1145
1146 /* This will also update middle-point to report to user later */
1147 st->info.x = st->sum_x / st->n_taps;
1148 st->info.y = st->sum_y / st->n_taps;
1149 st->info.timestamp = pe->timestamp;
1150
1151 if (!pe_list)
1152 {
1153 pe_list = eina_list_append(pe_list, p);
1154 st->l = eina_list_append(st->l, pe_list);
1155 }
1156 else
1157 pe_list = eina_list_append(pe_list, p);
1158
1159 return pe_list;
1160}
1161
1162/**
1163 * @internal
1164 *
1165 * This function sets state a tap-gesture to END or ABORT
1166 *
1167 * @param data gesture info pointer
1168 *
1169 * @ingroup Elm_Gesture_Layer
1170 */
1171static void
1172_tap_gesture_finish(void *data)
1173{ /* This function will test each tap gesture when timer expires */
1174 Gesture_Info *gesture = data;
1175 Elm_Gesture_State s = ELM_GESTURE_STATE_END;
1176 /* Here we check if taps-gesture was completed successfuly */
1177 /* Count how many taps were recieved on each device then */
1178 /* determine if it matches n_taps_needed defined on START */
1179 Taps_Type *st = gesture->data;
1180 Eina_List *l;
1181 Eina_List *pe_list;
1182 EINA_LIST_FOREACH(st->l, l, pe_list)
1183 {
1184 if (eina_list_count(pe_list) != st->n_taps_needed)
1185 { /* No match taps number on device, ABORT */
1186 s = ELM_GESTURE_STATE_ABORT;
1187 break;
1188 }
1189 }
1190
1191 st->info.n = eina_list_count(st->l);
1192 _set_state(gesture, s, gesture->info, EINA_FALSE);
1193 _tap_gestures_test_reset(gesture);
1194}
1195
1196/**
1197 * @internal
1198 *
1199 * when this timer expires we finish tap gestures.
1200 *
1201 * @param data The gesture-layer object.
1202 * @return cancles callback for this timer.
1203 *
1204 * @ingroup Elm_Gesture_Layer
1205 */
1206static Eina_Bool
1207_multi_tap_timeout(void *data)
1208{
1209 Widget_Data *wd = elm_widget_data_get(data);
1210 if (!wd) return EINA_FALSE;
1211
1212 if (IS_TESTED(ELM_GESTURE_N_TAPS))
1213 _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TAPS]);
1214
1215 if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
1216 _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS]);
1217
1218 if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
1219 _tap_gesture_finish(wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS]);
1220
1221 _clear_if_finished(data);
1222 wd->dbl_timeout = NULL;
1223 return ECORE_CALLBACK_CANCEL;
1224}
1225
1226/**
1227 * @internal
1228 *
1229 * when this timer expires we START long tap gesture
1230 *
1231 * @param data The gesture-layer object.
1232 * @return cancles callback for this timer.
1233 *
1234 * @ingroup Elm_Gesture_Layer
1235 */
1236static Eina_Bool
1237_long_tap_timeout(void *data)
1238{
1239 Gesture_Info *gesture = data;
1240 Long_Tap_Type *st = gesture->data;
1241 st->timeout = NULL;
1242
1243 _set_state(gesture, ELM_GESTURE_STATE_START,
1244 gesture->data, EINA_FALSE);
1245
1246 return ECORE_CALLBACK_CANCEL;
1247}
1248
1249
1250/**
1251 * @internal
1252 *
1253 * This function checks if a tap gesture should start
1254 *
1255 * @param wd Gesture Layer Widget Data.
1256 * @param pe The recent input event as stored in pe struct.
1257 * @param event_info Original input event pointer.
1258 * @param event_type Type of original input event.
1259 * @param gesture what gesture is tested
1260 * @param how many taps for this gesture (1, 2 or 3)
1261 *
1262 * @return Flag to determine if we need to set a timer for finish
1263 *
1264 * @ingroup Elm_Gesture_Layer
1265 */
1266static Eina_Bool
1267_tap_gesture_start(Widget_Data *wd, Pointer_Event *pe,
1268 void *event_info, Evas_Callback_Type event_type,
1269 Gesture_Info *gesture, int taps)
1270{ /* Here we fill Tap struct */
1271 Taps_Type *st = gesture->data;
1272 if (!st)
1273 { /* Allocated once on first time */
1274 st = calloc(1, sizeof(Taps_Type));
1275 gesture->data = st;
1276 _tap_gestures_test_reset(gesture);
1277 }
1278
1279 Eina_List *pe_list = NULL;
1280 Pointer_Event *pe_down = NULL;
1281 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1282 switch (pe->event_type)
1283 {
1284 case EVAS_CALLBACK_MULTI_DOWN:
1285 case EVAS_CALLBACK_MOUSE_DOWN:
1286 /* Check if got tap on same cord was tapped before */
1287 pe_list = eina_list_search_unsorted(st->l, compare_match_fingers, pe);
1288
1289 if ((!pe_list) &&
1290 eina_list_search_unsorted(st->l, compare_pe_device, pe))
1291 { /* This device was touched in other cord before completion */
1292 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
1293 &st->info, EINA_FALSE);
1294 consume_event(wd, event_info, event_type, ev_flag);
1295
1296 return EINA_FALSE;
1297 }
1298
1299 pe_list = _record_pointer_event(st, pe_list, pe, wd, event_info, event_type);
1300 if ((pe->device == 0) && (eina_list_count(pe_list) == 1))
1301 { /* This is the first mouse down we got */
1302 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START,
1303 &st->info, EINA_FALSE);
1304 consume_event(wd, event_info, event_type, ev_flag);
1305
1306 st->n_taps_needed = taps * 2; /* count DOWN and UP */
1307
1308 return EINA_TRUE;
1309 }
1310
1311 break;
1312
1313 case EVAS_CALLBACK_MULTI_UP:
1314 case EVAS_CALLBACK_MOUSE_UP:
1315 pe_list = eina_list_search_unsorted(st->l, compare_pe_device, pe);
1316 if (!pe_list)
1317 return EINA_FALSE;
1318
1319 pe_list = _record_pointer_event(st, pe_list, pe, wd, event_info, event_type);
1320 break;
1321
1322 case EVAS_CALLBACK_MULTI_MOVE:
1323 case EVAS_CALLBACK_MOUSE_MOVE:
1324 /* Get first event in first list, this has to be a Mouse Down event */
1325 /* and verify that user didn't move out of this area before next tap */
1326 pe_list = eina_list_search_unsorted(st->l, compare_pe_device, pe);
1327 if (pe_list)
1328 {
1329 pe_down = eina_list_data_get(pe_list);
1330 if (!_inside(pe_down->x, pe_down->y, pe->x, pe->y))
1331 {
1332 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
1333 &st->info, EINA_FALSE);
1334 consume_event(wd, event_info, event_type, ev_flag);
1335 }
1336 }
1337 break;
1338
1339 default:
1340 return EINA_FALSE;
1341 }
1342
1343 return EINA_FALSE;
1344}
1345
1346
1347/**
1348 * @internal
1349 *
1350 * This function checks all click/tap and double/triple taps
1351 *
1352 * @param obj The gesture-layer object.
1353 * @param pe The recent input event as stored in pe struct.
1354 * @param event_info Original input event pointer.
1355 * @param event_type Type of original input event.
1356 *
1357 * @ingroup Elm_Gesture_Layer
1358 */
1359static void
1360_tap_gestures_test(Evas_Object *obj, Pointer_Event *pe,
1361 void *event_info, Evas_Callback_Type event_type)
1362{ /* Here we fill Recent_Taps struct and fire-up click/tap timers */
1363 Eina_Bool need_timer = EINA_FALSE;
1364 Widget_Data *wd = elm_widget_data_get(obj);
1365 if (!wd) return;
1366
1367 if (!pe) /* this happens when unhandled event arrived */
1368 return; /* see _make_pointer_event function */
1369
1370 if (IS_TESTED(ELM_GESTURE_N_TAPS))
1371 need_timer |= _tap_gesture_start(wd, pe, event_info, event_type,
1372 wd->gesture[ELM_GESTURE_N_TAPS], 1);
1373
1374 if (IS_TESTED(ELM_GESTURE_N_DOUBLE_TAPS))
1375 need_timer |= _tap_gesture_start(wd, pe, event_info, event_type,
1376 wd->gesture[ELM_GESTURE_N_DOUBLE_TAPS], 2);
1377
1378 if (IS_TESTED(ELM_GESTURE_N_TRIPLE_TAPS))
1379 need_timer |= _tap_gesture_start(wd, pe, event_info, event_type,
1380 wd->gesture[ELM_GESTURE_N_TRIPLE_TAPS], 3);
1381
1382 if ((need_timer) && (!wd->dbl_timeout))
1383 { /* Set a timer to finish these gestures */
1384 wd->dbl_timeout = ecore_timer_add(0.4, _multi_tap_timeout,
1385 obj);
1386 }
1387}
1388
1389/**
1390 * @internal
1391 *
1392 * This function computes center-point for long-tap gesture
1393 *
1394 * @param st Long Tap gesture info pointer
1395 * @param pe The recent input event as stored in pe struct.
1396 *
1397 * @ingroup Elm_Gesture_Layer
1398 */
1399static void
1400_compute_taps_center(Long_Tap_Type *st,
1401 Evas_Coord *x_out, Evas_Coord *y_out, Pointer_Event *pe)
1402{
1403 if (!eina_list_count(st->touched))
1404 return;
1405
1406 Eina_List *l;
1407 Pointer_Event *p;
1408 Evas_Coord x = 0, y = 0;
1409 EINA_LIST_FOREACH(st->touched, l, p)
1410 { /* Accumulate all then take avarage */
1411 if (p->device == pe->device)
1412 { /* This will take care of values coming from MOVE event */
1413 x += pe->x;
1414 y += pe->y;
1415 }
1416 else
1417 {
1418 x += p->x;
1419 y += p->y;
1420 }
1421 }
1422
1423 *x_out = x / eina_list_count(st->touched);
1424 *y_out = y / eina_list_count(st->touched);
1425}
1426
1427/**
1428 * @internal
1429 *
1430 * This function checks N long-tap gesture.
1431 *
1432 * @param obj The gesture-layer object.
1433 * @param pe The recent input event as stored in pe struct.
1434 * @param event_info Original input event pointer.
1435 * @param event_type Type of original input event.
1436 * @param g_type what Gesture we are testing.
1437 * @param taps How many click/taps we test for.
1438 *
1439 * @ingroup Elm_Gesture_Layer
1440 */
1441static void
1442_n_long_tap_test(Evas_Object *obj, Pointer_Event *pe,
1443 void *event_info, Evas_Callback_Type event_type,
1444 Elm_Gesture_Type g_type)
1445{ /* Here we fill Recent_Taps struct and fire-up click/tap timers */
1446 Widget_Data *wd = elm_widget_data_get(obj);
1447 if (!wd) return;
1448
1449 if (!pe) /* this happens when unhandled event arrived */
1450 return; /* see _make_pointer_event function */
1451 Gesture_Info *gesture = wd->gesture[g_type];
1452 if (!gesture) return;
1453
1454 Long_Tap_Type *st = gesture->data;
1455 if (!st)
1456 { /* Allocated once on first time */
1457 st = calloc(1, sizeof(Long_Tap_Type));
1458 gesture->data = st;
1459 _n_long_tap_test_reset(gesture);
1460 }
1461
1462 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1463 switch (pe->event_type)
1464 {
1465 case EVAS_CALLBACK_MULTI_DOWN:
1466 case EVAS_CALLBACK_MOUSE_DOWN:
1467 st->touched = _add_touched_device(st->touched, pe);
1468 st->info.n = eina_list_count(st->touched);
1469 if (st->info.n > st->max_touched)
1470 st->max_touched = st->info.n;
1471 else
1472 { /* User removed finger from touch, then put back - ABORT */
1473 if ((gesture->state == ELM_GESTURE_STATE_START) ||
1474 (gesture->state == ELM_GESTURE_STATE_MOVE))
1475 {
1476 ev_flag =_set_state(gesture, ELM_GESTURE_STATE_ABORT,
1477 &st->info, EINA_FALSE);
1478 consume_event(wd, event_info, event_type, ev_flag);
1479 }
1480 }
1481
1482 if ((pe->device == 0) && (eina_list_count(st->touched) == 1))
1483 { /* This is the first mouse down we got */
1484 st->info.timestamp = pe->timestamp;
1485
1486 /* To test long tap */
1487 /* When this timer expires, gesture STARTED */
1488 if (!st->timeout)
1489 st->timeout = ecore_timer_add(wd->long_tap_start_timeout,
1490 _long_tap_timeout, gesture);
1491 }
1492
1493 consume_event(wd, event_info, event_type, ev_flag);
1494 _compute_taps_center(st, &st->info.x, &st->info.y, pe);
1495 st->center_x = st->info.x;
1496 st->center_y = st->info.y;
1497 break;
1498
1499 case EVAS_CALLBACK_MULTI_UP:
1500 case EVAS_CALLBACK_MOUSE_UP:
1501 st->touched = _remove_touched_device(st->touched, pe);
1502 _compute_taps_center(st, &st->center_x, &st->center_y, pe);
1503 if (st->info.n &&
1504 ((gesture->state == ELM_GESTURE_STATE_START) ||
1505 (gesture->state == ELM_GESTURE_STATE_MOVE)))
1506 { /* Report END only for gesture that STARTed */
1507 if (eina_list_count(st->touched) == 0)
1508 { /* Report END only at last release event */
1509 ev_flag =_set_state(gesture, ELM_GESTURE_STATE_END,
1510 &st->info, EINA_FALSE);
1511 consume_event(wd, event_info, event_type, ev_flag);
1512 }
1513 }
1514 else
1515 { /* Stop test, user lifts finger before long-start */
1516 if (st->timeout) ecore_timer_del(st->timeout);
1517 st->timeout = NULL;
1518 ev_flag =_set_state(gesture, ELM_GESTURE_STATE_ABORT,
1519 &st->info, EINA_FALSE);
1520 consume_event(wd, event_info, event_type, ev_flag);
1521 }
1522
1523 break;
1524
1525 case EVAS_CALLBACK_MULTI_MOVE:
1526 case EVAS_CALLBACK_MOUSE_MOVE:
1527 if (st->info.n &&
1528 ((gesture->state == ELM_GESTURE_STATE_START) ||
1529 (gesture->state == ELM_GESTURE_STATE_MOVE)))
1530 { /* Report MOVE only if STARTED */
1531 Evas_Coord x = 0;
1532 Evas_Coord y = 0;
1533 Elm_Gesture_State state_to_report = ELM_GESTURE_STATE_MOVE;
1534
1535 _compute_taps_center(st, &x, &y, pe);
1536 /* ABORT if user moved fingers out of tap area */
1537#if defined(DEBUG_GESTURE_LAYER)
1538 printf("%s x,y=(%d,%d) st->info.x,st->info.y=(%d,%d)\n",__func__,x,y,st->info.x,st->info.y);
1539#endif
1540 if (!_inside(x, y, st->center_x, st->center_y))
1541 state_to_report = ELM_GESTURE_STATE_ABORT;
1542
1543 /* Report MOVE if gesture started */
1544 ev_flag = _set_state(gesture, state_to_report,
1545 &st->info, EINA_TRUE);
1546 consume_event(wd, event_info, event_type, ev_flag);
1547 }
1548 break;
1549
1550 default:
1551 return;
1552 }
1553}
1554
1555/**
1556 * @internal
1557 *
1558 * This function computes momentum for MOMENTUM, LINE and FLICK gestures
1559 * This momentum value will be sent to widget when gesture is completed.
1560 *
1561 * @param momentum pointer to buffer where we record momentum value.
1562 * @param x1 x coord where user started gesture.
1563 * @param y1 y coord where user started gesture.
1564 * @param x2 x coord where user completed gesture.
1565 * @param y2 y coord where user completed gesture.
1566 * @param t1x timestamp for X, when user started gesture.
1567 * @param t1y timestamp for Y, when user started gesture.
1568 * @param t2 timestamp when user completed gesture.
1569 *
1570 * @ingroup Elm_Gesture_Layer
1571 */
1572static void
1573_set_momentum(Elm_Gesture_Momentum_Info *momentum,
1574 Evas_Coord xx1, Evas_Coord yy1,
1575 Evas_Coord xx2, Evas_Coord yy2,
1576 unsigned int t1x, unsigned int t1y, unsigned int t2)
1577{
1578 Evas_Coord velx = 0, vely = 0, vel;
1579 Evas_Coord dx = xx2 - xx1;
1580 Evas_Coord dy = yy2 - yy1;
1581 int dtx = t2 - t1x;
1582 int dty = t2 - t1y;
1583 if (dtx > 0)
1584 velx = (dx * 1000) / dtx;
1585
1586 if (dty > 0)
1587 vely = (dy * 1000) / dty;
1588
1589 vel = sqrt((velx * velx) + (vely * vely));
1590
1591 if ((_elm_config->thumbscroll_friction > 0.0) &&
1592 (vel > _elm_config->thumbscroll_momentum_threshold))
1593 { /* report momentum */
1594 momentum->mx = velx;
1595 momentum->my = vely;
1596 }
1597 else
1598 {
1599 momentum->mx = 0;
1600 momentum->my = 0;
1601 }
1602}
1603
1604/**
1605 * @internal
1606 *
1607 * This function is used for computing rotation angle (DEG).
1608 *
1609 * @param x1 first finger x location.
1610 * @param y1 first finger y location.
1611 * @param x2 second finger x location.
1612 * @param y2 second finger y location.
1613 *
1614 * @return angle of the line between (x1,y1), (x2,y2) in Deg.
1615 * Angles now are given in DEG, not RAD.
1616 * ZERO angle at 12-oclock, growing clockwise.
1617 *
1618 * @ingroup Elm_Gesture_Layer
1619 */
1620static double
1621get_angle(Evas_Coord xx1, Evas_Coord yy1, Evas_Coord xx2, Evas_Coord yy2)
1622{
1623 double a, xx, yy, rt = (-1);
1624 xx = fabs(xx2 - xx1);
1625 yy = fabs(yy2 - yy1);
1626
1627 if (((int)xx) && ((int)yy))
1628 {
1629 rt = a = RAD2DEG(atan(yy / xx));
1630 if (xx1 < xx2)
1631 {
1632 if (yy1 < yy2) rt = 360 - a;
1633 else rt = a;
1634 }
1635 else
1636 {
1637 if (yy1 < yy2) rt = 180 + a;
1638 else rt = 180 - a;
1639 }
1640 }
1641
1642 if (rt < 0)
1643 { /* Do this only if rt is not set */
1644 if (((int)xx))
1645 { /* Horizontal line */
1646 if (xx2 < xx1) rt = 180;
1647 else rt = 0.0;
1648 }
1649 else
1650 { /* Vertical line */
1651 if (yy2 < yy1) rt = 90;
1652 else rt = 270;
1653 }
1654 }
1655
1656 /* Now we want to change from:
1657 * 90 0
1658 * original circle 180 0 We want: 270 90
1659 * 270 180
1660 */
1661 rt = 450 - rt;
1662 if (rt >= 360) rt -= 360;
1663
1664 return rt;
1665}
1666
1667/**
1668 * @internal
1669 *
1670 * This function is used for computing the magnitude and direction
1671 * of vector between two points.
1672 *
1673 * @param x1 first finger x location.
1674 * @param y1 first finger y location.
1675 * @param x2 second finger x location.
1676 * @param y2 second finger y location.
1677 * @param l length computed (output)
1678 * @param a angle computed (output)
1679 *
1680 * @ingroup Elm_Gesture_Layer
1681 */
1682static void
1683get_vector(Evas_Coord xx1, Evas_Coord yy1, Evas_Coord xx2, Evas_Coord yy2,
1684 Evas_Coord *l, double *a)
1685{
1686 Evas_Coord xx, yy;
1687 xx = xx2 - xx1;
1688 yy = yy2 - yy1;
1689 *l = (Evas_Coord) sqrt((xx * xx) + (yy * yy));
1690 *a = get_angle(xx1, yy1, xx2, yy2);
1691}
1692
1693static int
1694_get_direction(Evas_Coord xx1, Evas_Coord xx2)
1695{
1696 if (xx2 < xx1) return -1;
1697 if (xx2 > xx1) return 1;
1698 return 0;
1699}
1700/**
1701 * @internal
1702 *
1703 * This function tests momentum gesture.
1704 * @param obj The gesture-layer object.
1705 * @param pe The recent input event as stored in pe struct.
1706 * @param event_info recent input event.
1707 * @param event_type recent event type.
1708 * @param g_type what Gesture we are testing.
1709 *
1710 * @ingroup Elm_Gesture_Layer
1711 */
1712static void
1713_momentum_test(Evas_Object *obj, Pointer_Event *pe,
1714 void *event_info, Evas_Callback_Type event_type,
1715 Elm_Gesture_Type g_type)
1716{
1717 Widget_Data *wd = elm_widget_data_get(obj);
1718 if (!wd) return;
1719 Gesture_Info *gesture = wd->gesture[g_type];
1720 if (!gesture ) return;
1721
1722 /* When continues enable = TRUE a gesture may START on MOVE event */
1723 /* We don't allow this to happen with the if-statement below. */
1724 /* When continues enable = FALSE a gesture may START on DOWN only */
1725 /* Therefor it would NOT start on MOVE event. */
1726 /* NOTE that touched list is updated AFTER this function returns */
1727 /* so (count == 0) when we get here on first touch on surface. */
1728 if ((wd->glayer_continues_enable) && (!eina_list_count(wd->touched)))
1729 return; /* Got move on mouse-over move */
1730
1731 Momentum_Type *st = gesture->data;
1732 Elm_Gesture_State state_to_report = ELM_GESTURE_STATE_MOVE;
1733 if (!st)
1734 { /* Allocated once on first time */
1735 st = calloc(1, sizeof(Momentum_Type));
1736 gesture->data = st;
1737 _momentum_test_reset(gesture);
1738 }
1739
1740 if (!pe)
1741 return;
1742
1743 /* First make avarage of all touched devices to determine center point */
1744 Eina_List *l;
1745 Pointer_Event *p;
1746 Pointer_Event pe_local = *pe; /* Copy pe event info to local */
1747 unsigned int cnt = 1; /* We start counter counting current pe event */
1748 EINA_LIST_FOREACH(wd->touched, l, p)
1749 if (p->device != pe_local.device)
1750 {
1751 pe_local.x += p->x;
1752 pe_local.y += p->y;
1753 cnt++;
1754 }
1755
1756
1757 /* Compute avarage to get center point */
1758 pe_local.x /= cnt;
1759 pe_local.y /= cnt;
1760
1761 /* If user added finger - reset gesture */
1762 if ((st->info.n) && (st->info.n < cnt))
1763 state_to_report = ELM_GESTURE_STATE_ABORT;
1764
1765
1766 if (st->info.n < cnt)
1767 st->info.n = cnt;
1768
1769 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
1770 switch (event_type)
1771 {
1772 case EVAS_CALLBACK_MOUSE_DOWN:
1773 case EVAS_CALLBACK_MULTI_DOWN:
1774 case EVAS_CALLBACK_MOUSE_MOVE:
1775 case EVAS_CALLBACK_MULTI_MOVE:
1776 if (!st->t_st_x)
1777 {
1778 if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
1779 (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
1780 (wd->glayer_continues_enable)) /* start also on MOVE */
1781 { /* We start on MOVE when cont-enabled only */
1782 st->line_st.x = st->line_end.x = pe_local.x;
1783 st->line_st.y = st->line_end.y = pe_local.y;
1784 st->t_st_x = st->t_st_y = st->t_end = pe_local.timestamp;
1785 st->xdir = st->ydir = 0;
1786 st->info.x2 = st->info.x1 = pe_local.x;
1787 st->info.y2 = st->info.y1 = pe_local.y;
1788 st->info.tx = st->info.ty = pe_local.timestamp;
1789 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START,
1790 &st->info, EINA_FALSE);
1791 consume_event(wd, event_info, event_type, ev_flag);
1792 }
1793
1794 return;
1795 }
1796
1797
1798 if (st->t_up)
1799 {
1800 Eina_Bool force = EINA_TRUE; /* for move state */
1801 if ((st->t_up + ELM_GESTURE_MULTI_TIMEOUT) < pe_local.timestamp)
1802 { /* ABORT if got DOWN or MOVE event after UP+timeout */
1803 state_to_report = ELM_GESTURE_STATE_ABORT;
1804 force = EINA_FALSE;
1805 }
1806
1807 /* We report state but don't compute momentum now */
1808 ev_flag = _set_state(gesture, state_to_report, &st->info,
1809 force);
1810 consume_event(wd, event_info, event_type, ev_flag);
1811 return; /* Stop computing when user remove finger */
1812 }
1813
1814 if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
1815 { /* Too long of a wait, reset all values */
1816 st->line_st.x = pe_local.x;
1817 st->line_st.y = pe_local.y;
1818 st->t_st_y = st->t_st_x = pe_local.timestamp;
1819 st->info.tx = st->t_st_x;
1820 st->info.ty = st->t_st_y;
1821 st->xdir = st->ydir = 0;
1822 }
1823 else
1824 {
1825 int xdir, ydir;
1826 xdir = _get_direction(st->line_end.x, pe_local.x);
1827 ydir = _get_direction(st->line_end.y, pe_local.y);
1828 if (xdir && (xdir != st->xdir))
1829 {
1830 st->line_st.x = st->line_end.x;
1831 st->info.tx = st->t_st_x = st->t_end;
1832 st->xdir = xdir;
1833 }
1834
1835 if (ydir && (ydir != st->ydir))
1836 {
1837 st->line_st.y = st->line_end.y;
1838 st->info.ty = st->t_st_y = st->t_end;
1839 st->ydir = ydir;
1840 }
1841 }
1842
1843 st->info.x2 = st->line_end.x = pe_local.x;
1844 st->info.y2 = st->line_end.y = pe_local.y;
1845 st->t_end = pe_local.timestamp;
1846 _set_momentum(&st->info, st->line_st.x, st->line_st.y,
1847 pe_local.x, pe_local.y, st->t_st_x, st->t_st_y,
1848 pe_local.timestamp);
1849
1850 ev_flag = _set_state(gesture, state_to_report, &st->info,
1851 EINA_TRUE);
1852 consume_event(wd, event_info, event_type, ev_flag);
1853 break;
1854
1855
1856 case EVAS_CALLBACK_MOUSE_UP:
1857 case EVAS_CALLBACK_MULTI_UP:
1858 st->t_up = pe_local.timestamp; /* Record recent up event time */
1859 if ((cnt > 1) || /* Ignore if more fingers touch surface */
1860 (!st->t_st_x)) /* IGNORE if info was cleared, long press,move */
1861 return;
1862
1863 if ((pe_local.timestamp - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->t_end)
1864 { /* Too long of a wait, reset all values */
1865 st->line_st.x = pe_local.x;
1866 st->line_st.y = pe_local.y;
1867 st->t_st_y = st->t_st_x = pe_local.timestamp;
1868 st->xdir = st->ydir = 0;
1869 }
1870
1871 st->info.x2 = pe_local.x;
1872 st->info.y2 = pe_local.y;
1873 st->line_end.x = pe_local.x;
1874 st->line_end.y = pe_local.y;
1875 st->t_end = pe_local.timestamp;
1876
1877 if ((fabs(st->info.mx) > ELM_GESTURE_MINIMUM_MOMENTUM) ||
1878 (fabs(st->info.my) > ELM_GESTURE_MINIMUM_MOMENTUM))
1879 state_to_report = ELM_GESTURE_STATE_END;
1880 else
1881 state_to_report = ELM_GESTURE_STATE_ABORT;
1882
1883 ev_flag = _set_state(gesture, state_to_report, &st->info,
1884 EINA_FALSE);
1885 consume_event(wd, event_info, event_type, ev_flag);
1886 return;
1887
1888 default:
1889 return;
1890 }
1891}
1892
1893static int
1894compare_line_device(const void *data1, const void *data2)
1895{ /* Compare device component of line struct */
1896 const Line_Data *ln1 = data1;
1897 const int *device = data2;
1898
1899 if (ln1->t_st) /* Compare only with lines that started */
1900 return (ln1->device - (*device));
1901
1902 return (-1);
1903}
1904
1905/**
1906 * @internal
1907 *
1908 * This function construct line struct from input.
1909 * @param info pointer to store line momentum.
1910 * @param st line info to store input data.
1911 * @param pe The recent input event as stored in pe struct.
1912 *
1913 * @ingroup Elm_Gesture_Layer
1914 */
1915static Eina_Bool
1916_single_line_process(Elm_Gesture_Line_Info *info, Line_Data *st,
1917 Pointer_Event *pe, Evas_Callback_Type event_type)
1918{ /* Record events and set momentum for line pointed by st */
1919 if (!pe)
1920 return EINA_FALSE;
1921
1922 switch (event_type)
1923 {
1924 case EVAS_CALLBACK_MOUSE_DOWN:
1925 case EVAS_CALLBACK_MOUSE_MOVE:
1926 case EVAS_CALLBACK_MULTI_DOWN:
1927 case EVAS_CALLBACK_MULTI_MOVE:
1928 if (!st->t_st)
1929 { /* This happens only when line starts */
1930 st->line_st.x = pe->x;
1931 st->line_st.y = pe->y;
1932 st->t_st = pe->timestamp;
1933 st->device = pe->device;
1934 info->momentum.x1 = pe->x;
1935 info->momentum.y1 = pe->y;
1936 info->momentum.tx = pe->timestamp;
1937 info->momentum.ty = pe->timestamp;
1938
1939 return EINA_TRUE;
1940 }
1941
1942 break;
1943
1944 case EVAS_CALLBACK_MOUSE_UP:
1945 case EVAS_CALLBACK_MULTI_UP:
1946 /* IGNORE if line info was cleared, like long press, move */
1947 if (!st->t_st)
1948 return EINA_FALSE;
1949
1950 st->line_end.x = pe->x;
1951 st->line_end.y = pe->y;
1952 st->t_end = pe->timestamp;
1953 break;
1954
1955 default:
1956 return EINA_FALSE;
1957 }
1958
1959 if (!st->t_st)
1960 {
1961 _line_data_reset(st);
1962 return EINA_FALSE;
1963 }
1964
1965 info->momentum.x2 = pe->x;
1966 info->momentum.y2 = pe->y;
1967 _set_momentum(&info->momentum, st->line_st.x, st->line_st.y, pe->x, pe->y,
1968 st->t_st, st->t_st, pe->timestamp);
1969
1970 return EINA_TRUE;
1971}
1972
1973/**
1974 * @internal
1975 *
1976 * This function test for (n) line gesture.
1977 * @param obj The gesture-layer object.
1978 * @param pe The recent input event as stored in pe struct.
1979 * @param event_info Original input event pointer.
1980 * @param event_type Type of original input event.
1981 * @param g_type what Gesture we are testing.
1982 *
1983 * @ingroup Elm_Gesture_Layer
1984 */
1985static void
1986_n_line_test(Evas_Object *obj, Pointer_Event *pe, void *event_info,
1987 Evas_Callback_Type event_type, Elm_Gesture_Type g_type)
1988{
1989 if (!pe)
1990 return;
1991 Widget_Data *wd = elm_widget_data_get(obj);
1992 if (!wd) return;
1993 Gesture_Info *gesture = wd->gesture[g_type];
1994 if (!gesture ) return;
1995
1996 /* When continues enable = TRUE a gesture may START on MOVE event */
1997 /* We don't allow this to happen with the if-statement below. */
1998 /* When continues enable = FALSE a gesture may START on DOWN only */
1999 /* Therefor it would NOT start on MOVE event. */
2000 /* NOTE that touched list is updated AFTER this function returns */
2001 /* so (count == 0) when we get here on first touch on surface. */
2002 if ((wd->glayer_continues_enable) && (!eina_list_count(wd->touched)))
2003 return; /* Got move on mouse-over move */
2004
2005 Line_Type *st = gesture->data;
2006 if (!st)
2007 {
2008 st = calloc(1, sizeof(Line_Type));
2009 gesture->data = st;
2010 }
2011
2012 Line_Data *line = NULL;
2013 Eina_List *list = st->list;
2014 unsigned cnt = eina_list_count(list);
2015
2016 if (cnt)
2017 { /* list is not empty, locate this device on list */
2018 line = (Line_Data *) eina_list_search_unsorted(st->list,
2019 compare_line_device, &pe->device);
2020 }
2021
2022 if (!line)
2023 { /* List is empty or device not found, new line-struct on START only */
2024 if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2025 (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
2026 ((wd->glayer_continues_enable) && /* START on MOVE also */
2027 ((event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
2028 (event_type == EVAS_CALLBACK_MULTI_MOVE))))
2029 { /* Allocate new item on START only */
2030 line = calloc(1, sizeof(Line_Data));
2031 _line_data_reset(line);
2032 list = eina_list_append(list, line);
2033 st->list = list;
2034 }
2035 }
2036
2037 if (!line) /* This may happen on MOVE that comes before DOWN */
2038 return; /* No line-struct to work with, can't continue testing */
2039
2040 if (_single_line_process(&st->info, line, pe, event_type)) /* update st with input */
2041 consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_NONE);
2042
2043 /* Get direction and magnitude of the line */
2044 double angle;
2045 get_vector(line->line_st.x, line->line_st.y, pe->x, pe->y,
2046 &line->line_length, &angle);
2047
2048 /* These are used later to compare lines length */
2049 Evas_Coord shortest_line_len = line->line_length;
2050 Evas_Coord longest_line_len = line->line_length;
2051 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2052
2053 /* Now update line-state */
2054 if (line->t_st)
2055 { /* Analyze line only if line started */
2056 if (line->line_angle >= 0.0)
2057 { /* if line direction was set, we test if broke tolerance */
2058 double a = fabs(angle - line->line_angle);
2059
2060 double d = (tan(DEG2RAD(a))) * line->line_length; /* Distance from line */
2061#if defined(DEBUG_GESTURE_LAYER)
2062 printf("%s a=<%f> d=<%f>\n", __func__, a, d);
2063#endif
2064 if ((d > wd->line_distance_tolerance) || (a > wd->line_angular_tolerance))
2065 { /* Broke tolerance: abort line and start a new one */
2066 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
2067 &st->info, EINA_FALSE);
2068 consume_event(wd, event_info, event_type, ev_flag);
2069 return;
2070 }
2071
2072 if (wd->glayer_continues_enable)
2073 { /* We may finish line if momentum is zero */
2074 /* This is for continues-gesture */
2075 if ((!st->info.momentum.mx) && (!st->info.momentum.my))
2076 { /* Finish line on zero momentum for continues gesture */
2077 line->line_end.x = pe->x;
2078 line->line_end.y = pe->y;
2079 line->t_end = pe->timestamp;
2080 }
2081 }
2082 }
2083 else
2084 { /* Record the line angle as it broke minimum length for line */
2085 if (line->line_length >= wd->line_min_length)
2086 st->info.angle = line->line_angle = angle;
2087 }
2088
2089
2090 if (line->t_end)
2091 {
2092 if (line->line_angle < 0.0)
2093 { /* it's not a line, too short more close to a tap */
2094 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
2095 &st->info, EINA_FALSE);
2096 consume_event(wd, event_info, event_type, ev_flag);
2097 return;
2098 }
2099 }
2100 }
2101
2102 /* Count how many lines already started / ended */
2103 int started = 0;
2104 int ended = 0;
2105 unsigned int tm_start = pe->timestamp;
2106 unsigned int tm_end = pe->timestamp;
2107 Eina_List *l;
2108 Line_Data *t_line;
2109 double base_angle = ELM_GESTURE_NEGATIVE_ANGLE;
2110 Eina_Bool lines_parallel = EINA_TRUE;
2111 EINA_LIST_FOREACH(list, l, t_line)
2112 {
2113 if (base_angle < 0)
2114 base_angle = t_line->line_angle;
2115 else
2116 {
2117 if (t_line->line_angle >= 0)
2118 { /* Compare angle only with lines with direction defined */
2119 if (fabs(base_angle - t_line->line_angle) >
2120 wd->line_angular_tolerance)
2121 lines_parallel = EINA_FALSE;
2122 }
2123 }
2124
2125 if (t_line->line_length)
2126 { /* update only if this line is used */
2127 if (shortest_line_len > t_line->line_length)
2128 shortest_line_len = t_line->line_length;
2129
2130 if (longest_line_len < t_line->line_length)
2131 longest_line_len = t_line->line_length;
2132 }
2133
2134 if (t_line->t_st)
2135 {
2136 started++;
2137 if (t_line->t_st < tm_start)
2138 tm_start = t_line->t_st;
2139 }
2140
2141 if (t_line->t_end)
2142 {
2143 ended++;
2144 if (t_line->t_end < tm_end)
2145 tm_end = t_line->t_end;
2146 }
2147 }
2148
2149 st->info.momentum.n = started;
2150
2151
2152 if (ended &&
2153 ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
2154 (event_type == EVAS_CALLBACK_MULTI_DOWN)))
2155 { /* user lift one finger then starts again without line-end - ABORT */
2156 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2157 EINA_FALSE);
2158 consume_event(wd, event_info, event_type, ev_flag);
2159 return;
2160 }
2161
2162 if (!lines_parallel)
2163 { /* Lines are NOT at same direction, abort this gesture */
2164 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2165 EINA_FALSE);
2166 consume_event(wd, event_info, event_type, ev_flag);
2167 return;
2168 }
2169
2170
2171 /* We report ABORT if lines length are NOT matching when fingers are up */
2172 if ((longest_line_len - shortest_line_len) > (_elm_config->finger_size * 2))
2173 {
2174 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2175 EINA_FALSE);
2176 consume_event(wd, event_info, event_type, ev_flag);
2177 return;
2178 }
2179
2180 if ((g_type == ELM_GESTURE_N_FLICKS) && ((tm_end - tm_start) > wd->flick_time_limit_ms))
2181 { /* We consider FLICK as a fast line.ABORT if take too long to finish */
2182 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT, &st->info,
2183 EINA_FALSE);
2184 consume_event(wd, event_info, event_type, ev_flag);
2185 return;
2186 }
2187
2188 switch (event_type)
2189 {
2190 case EVAS_CALLBACK_MOUSE_UP:
2191 case EVAS_CALLBACK_MULTI_UP:
2192 if ((started) && (started == ended))
2193 {
2194 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END,
2195 &st->info, EINA_FALSE);
2196 consume_event(wd, event_info, event_type, ev_flag);
2197 }
2198
2199 return;
2200
2201 case EVAS_CALLBACK_MOUSE_DOWN:
2202 case EVAS_CALLBACK_MULTI_DOWN:
2203 case EVAS_CALLBACK_MOUSE_MOVE:
2204 case EVAS_CALLBACK_MULTI_MOVE:
2205 if (started)
2206 {
2207 if (wd->glayer_continues_enable && (started == ended))
2208 { /* For continues gesture */
2209 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END,
2210 &st->info, EINA_FALSE);
2211 consume_event(wd, event_info, event_type, ev_flag);
2212 }
2213 else
2214 { /* When continues, may START on MOVE event too */
2215 Elm_Gesture_State s = ELM_GESTURE_STATE_MOVE;
2216
2217 /* This happens when: on n > 1 lines then one finger up */
2218 /* caused abort, then put finger down. */
2219 /* This will stop line from starting again. */
2220 /* Number of lines, MUST match touched-device in list */
2221 if ((!wd->glayer_continues_enable) &&
2222 (eina_list_count(st->list) < eina_list_count(wd->touched)))
2223 s = ELM_GESTURE_STATE_ABORT;
2224
2225 if (gesture->state == ELM_GESTURE_STATE_UNDEFINED)
2226 s = ELM_GESTURE_STATE_START;
2227
2228 ev_flag = _set_state(gesture, s, &st->info, EINA_TRUE);
2229 consume_event(wd, event_info, event_type, ev_flag);
2230 }
2231 }
2232 break;
2233
2234 default:
2235 return; /* Unhandeld event type */
2236 }
2237}
2238
2239/**
2240 * @internal
2241 *
2242 * This function is used to check if rotation gesture started.
2243 * @param st Contains current rotation values from user input.
2244 * @return TRUE/FALSE if we need to set rotation START.
2245 *
2246 * @ingroup Elm_Gesture_Layer
2247 */
2248static Eina_Bool
2249rotation_broke_tolerance(Rotate_Type *st)
2250{
2251 if (st->info.base_angle < 0)
2252 return EINA_FALSE; /* Angle has to be computed first */
2253
2254 if (st->rotate_angular_tolerance < 0)
2255 return EINA_TRUE;
2256
2257 double low = st->info.base_angle - st->rotate_angular_tolerance;
2258 double high = st->info.base_angle + st->rotate_angular_tolerance;
2259 double t = st->info.angle;
2260
2261 if (low < 0)
2262 {
2263 low += 180;
2264 high += 180;
2265
2266 if (t < 180)
2267 t += 180;
2268 else
2269 t -= 180;
2270 }
2271
2272 if (high > 360)
2273 {
2274 low -= 180;
2275 high -= 180;
2276
2277 if (t < 180)
2278 t += 180;
2279 else
2280 t -= 180;
2281 }
2282
2283#if defined(DEBUG_GESTURE_LAYER)
2284 printf("%s angle=<%f> low=<%f> high=<%f>\n", __func__, t, low, high);
2285#endif
2286 if ((t < low) || (t > high))
2287 { /* This marks that roation action has started */
2288 st->rotate_angular_tolerance = ELM_GESTURE_NEGATIVE_ANGLE;
2289 st->info.base_angle = st->info.angle; /* Avoid jump in angle value */
2290 return EINA_TRUE;
2291 }
2292
2293 return EINA_FALSE;
2294}
2295
2296/**
2297 * @internal
2298 *
2299 * This function is used for computing the gap between fingers.
2300 * It returns the length and center point between fingers.
2301 *
2302 * @param x1 first finger x location.
2303 * @param y1 first finger y location.
2304 * @param x2 second finger x location.
2305 * @param y2 second finger y location.
2306 * @param x Gets center point x cord (output)
2307 * @param y Gets center point y cord (output)
2308 *
2309 * @return length of the line between (x1,y1), (x2,y2) in pixels.
2310 *
2311 * @ingroup Elm_Gesture_Layer
2312 */
2313static Evas_Coord
2314get_finger_gap_length(Evas_Coord xx1, Evas_Coord yy1,
2315 Evas_Coord xx2, Evas_Coord yy2,
2316 Evas_Coord *x, Evas_Coord *y)
2317{
2318 double a, b, xx, yy, gap;
2319 xx = fabs(xx2 - xx1);
2320 yy = fabs(yy2 - yy1);
2321 gap = sqrt((xx * xx) + (yy * yy));
2322
2323 /* START - Compute zoom center point */
2324 /* The triangle defined as follows:
2325 * B
2326 * / |
2327 * / |
2328 * gap / | a
2329 * / |
2330 * A-----C
2331 * b
2332 * http://en.wikipedia.org/wiki/Trigonometric_functions
2333 *************************************/
2334 if (((int)xx) && ((int)yy))
2335 {
2336 double A = atan((yy / xx));
2337#if defined(DEBUG_GESTURE_LAYER)
2338 printf("xx=<%f> yy=<%f> A=<%f>\n", xx, yy, A);
2339#endif
2340 a = (Evas_Coord) ((gap / 2) * sin(A));
2341 b = (Evas_Coord) ((gap / 2) * cos(A));
2342 *x = (Evas_Coord) ((xx2 > xx1) ? (xx1 + b) : (xx2 + b));
2343 *y = (Evas_Coord) ((yy2 > yy1) ? (yy1 + a) : (yy2 + a));
2344 }
2345 else
2346 {
2347 if ((int)xx)
2348 { /* horiz line, take half width */
2349#if defined(DEBUG_GESTURE_LAYER)
2350 printf("==== HORIZ ====\n");
2351#endif
2352 *x = (Evas_Coord) ((xx1 + xx2) / 2);
2353 *y = (Evas_Coord) (yy1);
2354 }
2355
2356 if ((int)yy)
2357 { /* vert line, take half width */
2358#if defined(DEBUG_GESTURE_LAYER)
2359 printf("==== VERT ====\n");
2360#endif
2361 *x = (Evas_Coord) (xx1);
2362 *y = (Evas_Coord) ((yy1 + yy2) / 2);
2363 }
2364 }
2365 /* END - Compute zoom center point */
2366
2367 return (Evas_Coord) gap;
2368}
2369
2370/**
2371 * @internal
2372 *
2373 * This function is used for computing zoom value.
2374 *
2375 * @param st Pointer to zoom data based on user input.
2376 * @param tm_end Recent input event timestamp.
2377 * @param zoom_val Current computed zoom value.
2378 *
2379 * @return zoom momentum
2380 *
2381 * @ingroup Elm_Gesture_Layer
2382 */
2383static double
2384_zoom_momentum_get(Zoom_Type *st, unsigned int tm_end, double zoom_val)
2385{
2386 unsigned int tm_total;
2387 if (!st->m_st_tm)
2388 { /* Init, and we don't start computing momentum yet */
2389 st->m_st_tm = st->m_prev_tm = tm_end;
2390 st->m_base = zoom_val;
2391 return 0.0;
2392 }
2393
2394 if ((tm_end - ELM_GESTURE_MOMENTUM_DELAY) < st->m_st_tm)
2395 return 0.0; /* we don't start to compute momentum yet */
2396
2397 if (st->dir)
2398 { /* if direction was already defined, check if changed */
2399 if (((st->dir < 0) && (zoom_val > st->info.zoom)) ||
2400 ((st->dir > 0) && (zoom_val < st->info.zoom)))
2401 { /* Direction changed, reset momentum */
2402 st->m_st_tm = 0;
2403 st->dir = (-st->dir);
2404 return 0.0;
2405 }
2406 }
2407 else
2408 st->dir = (zoom_val > st->info.zoom) ? 1 : -1; /* init */
2409
2410 if ((tm_end - ELM_GESTURE_MOMENTUM_TIMEOUT) > st->m_prev_tm)
2411 {
2412 st->m_st_tm = 0; /* Rest momentum when waiting too long */
2413 return 0.0;
2414 }
2415
2416 st->m_prev_tm = tm_end;
2417 tm_total = tm_end - st->m_st_tm;
2418
2419 if (tm_total)
2420 return ((zoom_val - st->m_base) * 1000) / tm_total;
2421 else
2422 return 0.0;
2423}
2424
2425/**
2426 * @internal
2427 *
2428 * This function is used for computing zoom value.
2429 *
2430 * @param st Pointer to zoom data based on user input.
2431 * @param x1 first finger x location.
2432 * @param y1 first finger y location.
2433 * @param x2 second finger x location.
2434 * @param y2 second finger y location.
2435 * @param factor zoom-factor, used to determine how fast zoom works.
2436 *
2437 * @return zoom value, when 1.0 means no zoom, 0.5 half size...
2438 *
2439 * @ingroup Elm_Gesture_Layer
2440 */
2441static double
2442compute_zoom(Zoom_Type *st,
2443 Evas_Coord xx1, Evas_Coord yy1,
2444 Evas_Coord xx2, Evas_Coord yy2,
2445 double zoom_finger_factor)
2446{
2447 double rt = 1.0;
2448 unsigned int tm_end = (st->zoom_mv.timestamp > st->zoom_mv1.timestamp) ?
2449 st->zoom_mv.timestamp : st->zoom_mv1.timestamp;
2450
2451 Evas_Coord diam = get_finger_gap_length(xx1, yy1, xx2, yy2,
2452 &st->info.x, &st->info.y);
2453
2454 st->info.radius = diam / 2;
2455
2456 if (!st->zoom_base)
2457 {
2458 st->zoom_base = diam;
2459 return st->info.zoom;
2460 }
2461
2462 if (st->zoom_distance_tolerance)
2463 { /* zoom tolerance <> ZERO, means zoom action NOT started yet */
2464 if (diam < (st->zoom_base - st->zoom_distance_tolerance))
2465 { /* avoid jump with zoom value when break tolerance */
2466 st->zoom_base -= st->zoom_distance_tolerance;
2467 st->zoom_distance_tolerance = 0;
2468 }
2469
2470 if (diam > (st->zoom_base + st->zoom_distance_tolerance))
2471 { /* avoid jump with zoom value when break tolerance */
2472 st->zoom_base += st->zoom_distance_tolerance;
2473 st->zoom_distance_tolerance = 0;
2474 }
2475
2476 return rt;
2477 }
2478
2479 /* We use factor only on the difference between gap-base */
2480 /* if gap=120, base=100, we get ((120-100)/100)=0.2*factor */
2481 rt = ((1.0) + ((((float) diam - (float) st->zoom_base) /
2482 (float) st->zoom_base) * zoom_finger_factor));
2483
2484 /* Momentum: zoom per second: */
2485 st->info.momentum = _zoom_momentum_get(st, tm_end, rt);
2486
2487 return rt;
2488}
2489
2490/**
2491 * @internal
2492 *
2493 * This function handles zoom with mouse wheel.
2494 * thats a combination of wheel + CTRL key.
2495 * @param obj The gesture-layer object.
2496 * @param event_info Original input event pointer.
2497 * @param event_type Type of original input event.
2498 * @param g_type what Gesture we are testing.
2499 *
2500 * @ingroup Elm_Gesture_Layer
2501 */
2502static void
2503_zoom_with_wheel_test(Evas_Object *obj, void *event_info,
2504 Evas_Callback_Type event_type, Elm_Gesture_Type g_type)
2505{
2506 Widget_Data *wd = elm_widget_data_get(obj);
2507 if (!wd) return;
2508 if (!wd->gesture[g_type]) return;
2509
2510 Gesture_Info *gesture_zoom = wd->gesture[g_type];
2511 Zoom_Type *st = gesture_zoom->data;
2512 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2513 if (!st)
2514 { /* Allocated once on first time, used for zoom intermediate data */
2515 st = calloc(1, sizeof(Zoom_Type));
2516 gesture_zoom->data = st;
2517 _zoom_test_reset(gesture_zoom);
2518 }
2519
2520 switch (event_type)
2521 {
2522 case EVAS_CALLBACK_KEY_UP:
2523 {
2524 Evas_Event_Key_Up *p = event_info;
2525 if ((!strcmp(p->keyname, "Control_L")) ||
2526 (!strcmp(p->keyname, "Control_R")))
2527 { /* Test if we ended a zoom gesture when releasing CTRL */
2528 if ((st->zoom_wheel) &&
2529 ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
2530 (gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
2531 { /* User released CTRL after zooming */
2532 st->info.momentum = _zoom_momentum_get(st,
2533 p->timestamp, st->info.zoom);
2534
2535 ev_flag = _set_state(gesture_zoom,
2536 ELM_GESTURE_STATE_END, &st->info, EINA_FALSE);
2537 consume_event(wd, event_info, event_type, ev_flag);
2538
2539 return;
2540 }
2541 }
2542 break;
2543 }
2544
2545 case EVAS_CALLBACK_MOUSE_WHEEL:
2546 {
2547 Eina_Bool force;
2548 Elm_Gesture_State s;
2549 if (!evas_key_modifier_is_set(
2550 ((Evas_Event_Mouse_Wheel *) event_info)->modifiers,
2551 "Control"))
2552 { /* if using wheel witout CTRL after starting zoom */
2553 if ((st->zoom_wheel) &&
2554 ((gesture_zoom->state == ELM_GESTURE_STATE_START) ||
2555 (gesture_zoom->state == ELM_GESTURE_STATE_MOVE)))
2556 {
2557 ev_flag = _set_state(gesture_zoom,
2558 ELM_GESTURE_STATE_END, &st->info, EINA_FALSE);
2559 consume_event(wd, event_info, event_type, ev_flag);
2560
2561 return;
2562 }
2563 else
2564 return; /* Ignore mouse-wheel without control */
2565 }
2566
2567 /* Using mouse wheel with CTRL for zoom */
2568 if (st->zoom_wheel || (st->zoom_distance_tolerance == 0))
2569 { /* (zoom_wheel == NULL) and (zoom_distance_tolerance == 0)
2570 we continue a zoom gesture */
2571 force = EINA_TRUE;
2572 s = ELM_GESTURE_STATE_MOVE;
2573 }
2574 else
2575 { /* On first wheel event, report START */
2576 Evas_Modifier_Mask mask = evas_key_modifier_mask_get(
2577 evas_object_evas_get(wd->target), "Control");
2578 force = EINA_FALSE;
2579 s = ELM_GESTURE_STATE_START;
2580 if (!evas_object_key_grab(wd->target, "Control_L", mask, 0, EINA_FALSE))
2581 ERR("Failed to Grabbed CTRL_L");
2582 if (!evas_object_key_grab(wd->target, "Control_R", mask, 0, EINA_FALSE))
2583 ERR("Failed to Grabbed CTRL_R");
2584 }
2585
2586 st->zoom_distance_tolerance = 0; /* Cancel tolerance */
2587 st->zoom_wheel = (Evas_Event_Mouse_Wheel *) event_info;
2588 st->info.x = st->zoom_wheel->canvas.x;
2589 st->info.y = st->zoom_wheel->canvas.y;
2590
2591 if (st->zoom_wheel->z < 0) /* zoom in */
2592 st->info.zoom += (wd->zoom_finger_factor * wd->zoom_wheel_factor);
2593
2594 if (st->zoom_wheel->z > 0) /* zoom out */
2595 st->info.zoom -= (wd->zoom_finger_factor * wd->zoom_wheel_factor);
2596
2597 if (st->info.zoom < 0.0)
2598 st->info.zoom = 0.0;
2599
2600 st->info.momentum = _zoom_momentum_get(st,
2601 st->zoom_wheel->timestamp, st->info.zoom);
2602
2603 ev_flag = _set_state(gesture_zoom, s, &st->info, force);
2604 consume_event(wd, event_info, event_type, ev_flag);
2605 break;
2606 }
2607
2608 default:
2609 return;
2610 }
2611}
2612
2613/**
2614 * @internal
2615 *
2616 * This function is used to test zoom gesture.
2617 * user may combine zoom, rotation together.
2618 * so its possible that both will be detected from input.
2619 * (both are two-finger movement-oriented gestures)
2620 *
2621 * @param obj The gesture-layer object.
2622 * @param event_info Pointer to recent input event.
2623 * @param event_type Recent input event type.
2624 * @param g_type what Gesture we are testing.
2625 *
2626 * @ingroup Elm_Gesture_Layer
2627 */
2628static void
2629_zoom_test(Evas_Object *obj, Pointer_Event *pe, void *event_info,
2630 Evas_Callback_Type event_type, Elm_Gesture_Type g_type)
2631{
2632 if (!pe)
2633 return;
2634 Widget_Data *wd = elm_widget_data_get(obj);
2635 if (!wd) return;
2636 if (!wd->gesture[g_type]) return;
2637
2638 Gesture_Info *gesture_zoom = wd->gesture[g_type];
2639 Zoom_Type *st = gesture_zoom->data;
2640
2641 if (!st)
2642 { /* Allocated once on first time, used for zoom data */
2643 st = calloc(1, sizeof(Zoom_Type));
2644 gesture_zoom->data = st;
2645 _zoom_test_reset(gesture_zoom);
2646 }
2647
2648
2649 /* Start - new zoom testing, letting all fingers start */
2650 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2651 switch (event_type)
2652 {
2653 case EVAS_CALLBACK_MOUSE_MOVE:
2654 case EVAS_CALLBACK_MULTI_MOVE:
2655 /* if non-continues mode and gesture NOT started, ignore MOVE */
2656 if ((!wd->glayer_continues_enable) &&
2657 (!st->zoom_st.timestamp))
2658 return;
2659
2660 case EVAS_CALLBACK_MOUSE_DOWN:
2661 case EVAS_CALLBACK_MULTI_DOWN:
2662 { /* Here we take care of zoom-start and zoom move */
2663 Eina_List *l;
2664 Pointer_Event *p;
2665
2666 if (eina_list_count(wd->touched) > 2)
2667 { /* Process zoom only when 2 fingers on surface */
2668 ev_flag = _set_state(gesture_zoom,
2669 ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
2670 consume_event(wd, event_info, event_type, ev_flag);
2671
2672 return;
2673 }
2674
2675 if (!st->zoom_st.timestamp)
2676 { /* Now scan touched-devices list and find other finger */
2677 EINA_LIST_FOREACH(wd->touched, l, p)
2678 { /* Device of other finger <> pe device */
2679 if (p->device != pe->device)
2680 break;
2681 }
2682
2683 if (!p) /* Single finger on touch */
2684 return;
2685
2686 /* Record down fingers */
2687 consume_event(wd, event_info, event_type, ev_flag);
2688 memcpy(&st->zoom_st, pe, sizeof(Pointer_Event));
2689 memcpy(&st->zoom_st1, p, sizeof(Pointer_Event));
2690
2691 /* Set mv field as well to be ready for MOVE events */
2692 memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
2693 memcpy(&st->zoom_mv1, p, sizeof(Pointer_Event));
2694
2695 /* Here we have zoom_st, zoom_st1 set, report START */
2696 /* Set zoom-base after BOTH down events recorded */
2697 /* Compute length of line between fingers zoom start */
2698 st->info.zoom = 1.0;
2699 st->zoom_base = get_finger_gap_length(st->zoom_st1.x,
2700 st->zoom_st1.y, st->zoom_st.x, st->zoom_st.y,
2701 &st->info.x, &st->info.y);
2702
2703 st->info.radius = st->zoom_base / 2;
2704
2705 if ((gesture_zoom->state != ELM_GESTURE_STATE_START) &&
2706 (gesture_zoom->state != ELM_GESTURE_STATE_MOVE))
2707 { /* zoom started with mouse-wheel, don't report twice */
2708 ev_flag = _set_state(gesture_zoom,
2709 ELM_GESTURE_STATE_START, &st->info, EINA_FALSE);
2710 consume_event(wd, event_info, event_type, ev_flag);
2711 }
2712
2713 return; /* Zoom started */
2714 } /* End of ZOOM_START handling */
2715
2716
2717 /* if we got here, we have (exacally) two fingers on surfce */
2718 /* we also after START, report MOVE */
2719 /* First detect which finger moved */
2720 if (pe->device == st->zoom_mv.device)
2721 memcpy(&st->zoom_mv, pe, sizeof(Pointer_Event));
2722 else if (pe->device == st->zoom_mv1.device)
2723 memcpy(&st->zoom_mv1, pe, sizeof(Pointer_Event));
2724
2725 /* Compute change in zoom as fingers move */
2726 st->info.zoom = compute_zoom(st,
2727 st->zoom_mv.x, st->zoom_mv.y,
2728 st->zoom_mv1.x, st->zoom_mv1.y,
2729 wd->zoom_finger_factor);
2730
2731 if (!st->zoom_distance_tolerance)
2732 { /* Zoom broke tolerance, report move */
2733 double d = st->info.zoom - st->next_step;
2734 if (d < 0.0)
2735 d = (-d);
2736
2737 if (d >= wd->zoom_step)
2738 { /* Report move in steps */
2739 st->next_step = st->info.zoom;
2740
2741 ev_flag = _set_state(gesture_zoom,
2742 ELM_GESTURE_STATE_MOVE,
2743 &st->info, EINA_TRUE);
2744 consume_event(wd, event_info, event_type, ev_flag);
2745 }
2746 } /* End of ZOOM_MOVE handling */
2747
2748 return;
2749 }
2750
2751 case EVAS_CALLBACK_MOUSE_UP:
2752 case EVAS_CALLBACK_MULTI_UP:
2753 /* Reset timestamp of finger-up.This is used later
2754 by _zoom_test_reset() to retain finger-down data */
2755 consume_event(wd, event_info, event_type, ev_flag);
2756 if (((st->zoom_wheel) || (st->zoom_base)) &&
2757 (st->zoom_distance_tolerance == 0))
2758 {
2759 ev_flag = _set_state(gesture_zoom, ELM_GESTURE_STATE_END,
2760 &st->info, EINA_FALSE);
2761 consume_event(wd, event_info, event_type, ev_flag);
2762
2763 return;
2764 }
2765
2766 /* if we got here not a ZOOM */
2767 if (gesture_zoom->state != ELM_GESTURE_STATE_UNDEFINED)
2768 { /* Must be != undefined, if gesture started */
2769 ev_flag = _set_state(gesture_zoom,
2770 ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
2771 consume_event(wd, event_info, event_type, ev_flag);
2772 }
2773
2774 _zoom_test_reset(gesture_zoom);
2775
2776 return;
2777
2778 default:
2779 return;
2780 }
2781}
2782
2783static void
2784_get_rotate_properties(Rotate_Type *st,
2785 Evas_Coord xx1, Evas_Coord yy1,
2786 Evas_Coord xx2, Evas_Coord yy2,
2787 double *angle)
2788{ /* FIXME: Fix momentum computation, it's wrong */
2789 double prev_angle = *angle;
2790 st->info.radius = get_finger_gap_length(xx1, yy1, xx2, yy2,
2791 &st->info.x, &st->info.y) / 2;
2792
2793 *angle = get_angle(xx1, yy1, xx2, yy2);
2794
2795 if (angle == &st->info.angle)
2796 { /* Fingers are moving, compute momentum */
2797 unsigned int tm_start =
2798 (st->rotate_st.timestamp > st->rotate_st1.timestamp)
2799 ? st->rotate_st.timestamp : st->rotate_st1.timestamp;
2800 unsigned int tm_end =
2801 (st->rotate_mv.timestamp > st->rotate_mv1.timestamp)
2802 ? st->rotate_mv.timestamp : st->rotate_mv1.timestamp;
2803
2804 unsigned int tm_total = tm_end - tm_start;
2805 if (tm_total)
2806 { /* Momentum computed as:
2807 accumulated roation angle (deg) divided by time */
2808 double m = 0;;
2809 if (((prev_angle < 90) && ((*angle) > 270)) ||
2810 ((prev_angle > 270) && ((*angle) < 90)))
2811 { /* We circle passing ZERO point */
2812 prev_angle = (*angle);
2813 }
2814 else m = prev_angle - (*angle);
2815
2816 st->accum_momentum += m;
2817
2818 if ((tm_end - st->prev_momentum_tm) < 100)
2819 st->prev_momentum += m;
2820 else
2821 {
2822 if (fabs(st->prev_momentum) < 0.002)
2823 st->accum_momentum = 0.0; /* reset momentum */
2824
2825 st->prev_momentum = 0.0; /* Start again */
2826 }
2827
2828 st->prev_momentum_tm = tm_end;
2829 st->info.momentum = (st->accum_momentum * 1000) / tm_total;
2830 }
2831 }
2832 else
2833 st->info.momentum = 0;
2834}
2835
2836/**
2837 * @internal
2838 *
2839 * This function is used to test rotation gesture.
2840 * user may combine zoom, rotation together.
2841 * so its possible that both will be detected from input.
2842 * (both are two-finger movement-oriented gestures)
2843 *
2844 * @param obj The gesture-layer object.
2845 * @param event_info Pointer to recent input event.
2846 * @param event_type Recent input event type.
2847 * @param g_type what Gesture we are testing.
2848 *
2849 * @ingroup Elm_Gesture_Layer
2850 */
2851static void
2852_rotate_test(Evas_Object *obj, Pointer_Event *pe, void *event_info,
2853 Evas_Callback_Type event_type, Elm_Gesture_Type g_type)
2854{
2855 if (!pe)
2856 return;
2857
2858 Widget_Data *wd = elm_widget_data_get(obj);
2859 if (!wd) return;
2860 if (!wd->gesture[g_type]) return;
2861
2862 Gesture_Info *gesture = wd->gesture[g_type];
2863 Rotate_Type *st;
2864 if (gesture)
2865 {
2866 st = gesture->data;
2867 if (!st)
2868 { /* Allocated once on first time */
2869 st = calloc(1, sizeof(Rotate_Type));
2870 gesture->data = st;
2871 _rotate_test_reset(gesture);
2872 }
2873 }
2874
2875 Evas_Event_Flags ev_flag = EVAS_EVENT_FLAG_NONE;
2876 switch (event_type)
2877 {
2878 case EVAS_CALLBACK_MOUSE_MOVE:
2879 case EVAS_CALLBACK_MULTI_MOVE:
2880 /* if non-continues mode and gesture NOT started, ignore MOVE */
2881 if ((!wd->glayer_continues_enable) &&
2882 (!st->rotate_st.timestamp))
2883 return;
2884
2885 case EVAS_CALLBACK_MOUSE_DOWN:
2886 case EVAS_CALLBACK_MULTI_DOWN:
2887 { /* Here we take care of rotate-start and rotate move */
2888 Eina_List *l;
2889 Pointer_Event *p;
2890
2891 if (eina_list_count(wd->touched) > 2)
2892 { /* Process rotate only when 2 fingers on surface */
2893 ev_flag = _set_state(gesture,
2894 ELM_GESTURE_STATE_ABORT, &st->info, EINA_FALSE);
2895 consume_event(wd, event_info, event_type, ev_flag);
2896
2897 return;
2898 }
2899
2900 if (!st->rotate_st.timestamp)
2901 { /* Now scan touched-devices list and find other finger */
2902 EINA_LIST_FOREACH(wd->touched, l, p)
2903 { /* Device of other finger <> pe device */
2904 if (p->device != pe->device)
2905 break;
2906 }
2907
2908 if (!p)
2909 return; /* Single finger on touch */
2910
2911 /* Record down fingers */
2912 consume_event(wd, event_info, event_type, ev_flag);
2913 memcpy(&st->rotate_st, pe, sizeof(Pointer_Event));
2914 memcpy(&st->rotate_st1, p, sizeof(Pointer_Event));
2915
2916 /* Set mv field as well to be ready for MOVE events */
2917 memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
2918 memcpy(&st->rotate_mv1, p, sizeof(Pointer_Event));
2919
2920 /* Here we have rotate_st, rotate_st1 set, report START */
2921 /* Set rotate-base after BOTH down events recorded */
2922 /* Compute length of line between fingers rotate start */
2923 _get_rotate_properties(st,
2924 st->rotate_st.x, st->rotate_st.y,
2925 st->rotate_st1.x, st->rotate_st1.y,
2926 &st->info.base_angle);
2927
2928 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_START,
2929 &st->info, EINA_FALSE);
2930 consume_event(wd, event_info, event_type, ev_flag);
2931
2932 return; /* Rotate started */
2933 } /* End of ROTATE_START handling */
2934
2935
2936 /* if we got here, we have (exacally) two fingers on surfce */
2937 /* we also after START, report MOVE */
2938 /* First detect which finger moved */
2939 if (pe->device == st->rotate_mv.device)
2940 memcpy(&st->rotate_mv, pe, sizeof(Pointer_Event));
2941 else if (pe->device == st->rotate_mv1.device)
2942 memcpy(&st->rotate_mv1, pe, sizeof(Pointer_Event));
2943
2944 /* Compute change in rotate as fingers move */
2945 _get_rotate_properties(st,
2946 st->rotate_mv.x, st->rotate_mv.y,
2947 st->rotate_mv1.x, st->rotate_mv1.y,
2948 &st->info.angle);
2949
2950 if (rotation_broke_tolerance(st))
2951 { /* Rotation broke tolerance, report move */
2952 double d = st->info.angle - st->next_step;
2953 if (d < 0)
2954 d = (-d);
2955
2956 if (d >= wd->rotate_step)
2957 { /* Report move in steps */
2958 st->next_step = st->info.angle;
2959
2960 ev_flag = _set_state(gesture,
2961 ELM_GESTURE_STATE_MOVE, &st->info, EINA_TRUE);
2962 consume_event(wd, event_info, event_type, ev_flag);
2963 }
2964 } /* End of ROTATE_MOVE handling */
2965
2966 return;
2967 }
2968
2969 case EVAS_CALLBACK_MOUSE_UP:
2970 case EVAS_CALLBACK_MULTI_UP:
2971 consume_event(wd, event_info, event_type, ev_flag);
2972 /* Reset timestamp of finger-up.This is used later
2973 by rotate_test_reset() to retain finger-down data */
2974 if (st->rotate_angular_tolerance < 0)
2975 {
2976 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_END,
2977 &st->info, EINA_FALSE);
2978 consume_event(wd, event_info, event_type, ev_flag);
2979
2980 return;
2981 }
2982
2983 if (gesture->state != ELM_GESTURE_STATE_UNDEFINED)
2984 { /* Must be != undefined, if gesture started */
2985 ev_flag = _set_state(gesture, ELM_GESTURE_STATE_ABORT,
2986 &st->info, EINA_FALSE);
2987 consume_event(wd, event_info, event_type, ev_flag);
2988 }
2989
2990 _rotate_test_reset(gesture);
2991 return;
2992
2993 default:
2994 return;
2995 }
2996}
2997
2998/**
2999 * @internal
3000 *
3001 * This function is used to save input events in an abstract struct
3002 * to be used later by getsure-testing functions.
3003 *
3004 * @param data The gesture-layer object.
3005 * @param event_info Pointer to recent input event.
3006 * @param event_type Recent input event type.
3007 * @param pe The abstract data-struct (output).
3008 *
3009 * @ingroup Elm_Gesture_Layer
3010 */
3011static Eina_Bool
3012_make_pointer_event(void *data, void *event_info,
3013 Evas_Callback_Type event_type, Pointer_Event *pe)
3014{
3015 Widget_Data *wd = elm_widget_data_get(data);
3016 if (!wd) return EINA_FALSE;
3017
3018 memset(pe, '\0', sizeof(*pe));
3019 switch (event_type)
3020 {
3021 case EVAS_CALLBACK_MOUSE_DOWN:
3022 pe->x = ((Evas_Event_Mouse_Down *) event_info)->canvas.x;
3023 pe->y = ((Evas_Event_Mouse_Down *) event_info)->canvas.y;
3024 pe->timestamp = ((Evas_Event_Mouse_Down *) event_info)->timestamp;
3025 pe->device = ELM_MOUSE_DEVICE;
3026 break;
3027
3028 case EVAS_CALLBACK_MOUSE_UP:
3029 pe->x = ((Evas_Event_Mouse_Up *) event_info)->canvas.x;
3030 pe->y = ((Evas_Event_Mouse_Up *) event_info)->canvas.y;
3031 pe->timestamp = ((Evas_Event_Mouse_Up *) event_info)->timestamp;
3032 pe->device = ELM_MOUSE_DEVICE;
3033 break;
3034
3035 case EVAS_CALLBACK_MOUSE_MOVE:
3036 pe->x = ((Evas_Event_Mouse_Move *) event_info)->cur.canvas.x;
3037 pe->y = ((Evas_Event_Mouse_Move *) event_info)->cur.canvas.y;
3038 pe->timestamp = ((Evas_Event_Mouse_Move *) event_info)->timestamp;
3039 pe->device = ELM_MOUSE_DEVICE;
3040 break;
3041
3042 case EVAS_CALLBACK_MULTI_DOWN:
3043 pe->x = ((Evas_Event_Multi_Down *) event_info)->canvas.x;
3044 pe->y = ((Evas_Event_Multi_Down *) event_info)->canvas.y;
3045 pe->timestamp = ((Evas_Event_Multi_Down *) event_info)->timestamp;
3046 pe->device = ((Evas_Event_Multi_Down *) event_info)->device;
3047 break;
3048
3049 case EVAS_CALLBACK_MULTI_UP:
3050 pe->x = ((Evas_Event_Multi_Up *) event_info)->canvas.x;
3051 pe->y = ((Evas_Event_Multi_Up *) event_info)->canvas.y;
3052 pe->timestamp = ((Evas_Event_Multi_Up *) event_info)->timestamp;
3053 pe->device = ((Evas_Event_Multi_Up *) event_info)->device;
3054 break;
3055
3056 case EVAS_CALLBACK_MULTI_MOVE:
3057 pe->x = ((Evas_Event_Multi_Move *) event_info)->cur.canvas.x;
3058 pe->y = ((Evas_Event_Multi_Move *) event_info)->cur.canvas.y;
3059 pe->timestamp = ((Evas_Event_Multi_Move *) event_info)->timestamp;
3060 pe->device = ((Evas_Event_Multi_Move *) event_info)->device;
3061 break;
3062
3063 default:
3064 return EINA_FALSE;
3065 }
3066
3067 pe->event_type = event_type;
3068 return EINA_TRUE;
3069}
3070
3071/**
3072 * @internal
3073 *
3074 * This function restartes line, flick, zoom and rotate gestures
3075 * when gesture-layer continues-gestures enabled.
3076 * Example of continues-gesture:
3077 * When doing a line, user stops moving finger but keeps fingers on touch.
3078 * This will cause line-end, then as user continues moving his finger
3079 * it re-starts line gesture.
3080 * When continue mode is disabled, user has to lift finger from touch
3081 * to end a gesture. Them touch-again to start a new one.
3082 *
3083 * @param data The gesture-layer object.
3084 * @param wd gesture layer widget data.
3085 * @param states_reset flag that marks gestures were reset in history clear.
3086 *
3087 * @ingroup Elm_Gesture_Layer
3088 */
3089static void
3090continues_gestures_restart(void *data, Eina_Bool states_reset)
3091{
3092 Widget_Data *wd = elm_widget_data_get(data);
3093 if (!wd) return;
3094
3095 /* Run through events to restart gestures */
3096 Gesture_Info *g;
3097 Eina_Bool n_momentum, n_lines, n_flicks, zoom, rotate;
3098 /* We turn-on flag for finished, aborted, not-started gestures */
3099 g = wd->gesture[ELM_GESTURE_MOMENTUM];
3100 n_momentum = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3101 && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3102 if (n_momentum)
3103 {
3104 _momentum_test_reset(wd->gesture[ELM_GESTURE_MOMENTUM]);
3105 _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3106 SET_TEST_BIT(g);
3107 }
3108
3109 g = wd->gesture[ELM_GESTURE_N_LINES];
3110 n_lines = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3111 && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3112 if (n_lines)
3113 {
3114 _line_test_reset(wd->gesture[ELM_GESTURE_N_LINES]);
3115 _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3116 SET_TEST_BIT(g);
3117 }
3118
3119 g = wd->gesture[ELM_GESTURE_N_FLICKS];
3120 n_flicks = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3121 && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3122 if (n_flicks)
3123 {
3124 _line_test_reset(wd->gesture[ELM_GESTURE_N_FLICKS]);
3125 _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3126 SET_TEST_BIT(g);
3127 }
3128
3129 g = wd->gesture[ELM_GESTURE_ZOOM];
3130 zoom = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3131 && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3132 if (zoom)
3133 {
3134 _zoom_test_reset(wd->gesture[ELM_GESTURE_ZOOM]);
3135 _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3136 SET_TEST_BIT(g);
3137 }
3138
3139 g = wd->gesture[ELM_GESTURE_ROTATE];
3140 rotate = (g) ? ((states_reset) | ((g->state != ELM_GESTURE_STATE_START)
3141 && (g->state != ELM_GESTURE_STATE_MOVE))) : EINA_FALSE;
3142 if (rotate)
3143 {
3144 _rotate_test_reset(wd->gesture[ELM_GESTURE_ROTATE]);
3145 _set_state(g, ELM_GESTURE_STATE_UNDEFINED, NULL, EINA_FALSE);
3146 SET_TEST_BIT(g);
3147 }
3148}
3149
3150/**
3151 * @internal
3152 *
3153 * This function the core-function where input handling is done.
3154 * Here we get user input and stream it to gesture testing.
3155 * We notify user about any gestures with new state:
3156 * Valid states are:
3157 * START - gesture started.
3158 * MOVE - gesture is ongoing.
3159 * END - gesture was completed.
3160 * ABORT - gesture was aborted after START, MOVE (will NOT be completed)
3161 *
3162 * We also check if a gesture was detected, then reset event history
3163 * If no gestures were found we reset gesture test flag
3164 * after streaming event-history to widget.
3165 * (stream to the widget all events not consumed as a gesture)
3166 *
3167 * @param data The gesture-layer object.
3168 * @param event_info Pointer to recent input event.
3169 * @param event_type Recent input event type.
3170 *
3171 * @ingroup Elm_Gesture_Layer
3172 */
3173static void
3174_event_process(void *data, Evas_Object *obj __UNUSED__,
3175 void *event_info, Evas_Callback_Type event_type)
3176{
3177 Pointer_Event _pe;
3178 Pointer_Event *pe = NULL;
3179 Widget_Data *wd = elm_widget_data_get(data);
3180
3181#if defined(DEBUG_GESTURE_LAYER)
3182 int i;
3183 Gesture_Info *g;
3184 printf("Gesture | State | is tested\n");
3185 for (i = ELM_GESTURE_N_TAPS; i < ELM_GESTURE_LAST; i++)
3186 {
3187 g = wd->gesture[i];
3188 if (g)
3189 printf(" %d %d %d\n", i, g->state, g->test);
3190 }
3191#endif
3192
3193 /* Start testing candidate gesture from here */
3194 if (_make_pointer_event(data, event_info, event_type, &_pe))
3195 pe = &_pe;
3196
3197 if (IS_TESTED(ELM_GESTURE_N_LONG_TAPS))
3198 _n_long_tap_test(data, pe, event_info, event_type,
3199 ELM_GESTURE_N_LONG_TAPS);
3200
3201 /* This takes care of single, double and tripple tap */
3202 _tap_gestures_test(data, pe, event_info, event_type);
3203
3204 if (IS_TESTED(ELM_GESTURE_MOMENTUM))
3205 _momentum_test(data, pe, event_info, event_type,
3206 ELM_GESTURE_MOMENTUM);
3207
3208 if (IS_TESTED(ELM_GESTURE_N_LINES))
3209 _n_line_test(data, pe, event_info, event_type, ELM_GESTURE_N_LINES);
3210
3211 if (IS_TESTED(ELM_GESTURE_N_FLICKS))
3212 _n_line_test(data, pe, event_info, event_type, ELM_GESTURE_N_FLICKS);
3213
3214 if (_elm_config->glayer_zoom_finger_enable && IS_TESTED(ELM_GESTURE_ZOOM))
3215 _zoom_test(data, pe, event_info, event_type, ELM_GESTURE_ZOOM);
3216
3217 if (IS_TESTED(ELM_GESTURE_ZOOM))
3218 _zoom_with_wheel_test(data, event_info, event_type, ELM_GESTURE_ZOOM);
3219
3220 if (_elm_config->glayer_rotate_finger_enable && IS_TESTED(ELM_GESTURE_ROTATE))
3221 _rotate_test(data, pe, event_info, event_type, ELM_GESTURE_ROTATE);
3222
3223 if (_get_event_flag(event_info, event_type) & EVAS_EVENT_FLAG_ON_HOLD)
3224 _event_history_add(data, event_info, event_type);
3225 else if ((event_type == EVAS_CALLBACK_MOUSE_UP) ||
3226 (event_type == EVAS_CALLBACK_MULTI_UP))
3227 {
3228 Eina_List *pending = _device_is_pending(wd->pending, event_info, event_type);
3229 if (pending)
3230 {
3231 consume_event(wd, event_info, event_type, EVAS_EVENT_FLAG_ON_HOLD);
3232 _event_history_add(data, event_info, event_type);
3233 }
3234 }
3235
3236 /* we maintain list of touched devices */
3237 /* We also use move to track current device x.y pos */
3238 if ((event_type == EVAS_CALLBACK_MOUSE_DOWN) ||
3239 (event_type == EVAS_CALLBACK_MULTI_DOWN) ||
3240 (event_type == EVAS_CALLBACK_MOUSE_MOVE) ||
3241 (event_type == EVAS_CALLBACK_MULTI_MOVE))
3242 {
3243 wd->touched = _add_touched_device(wd->touched, pe);
3244 }
3245 else if ((event_type == EVAS_CALLBACK_MOUSE_UP) ||
3246 (event_type == EVAS_CALLBACK_MULTI_UP))
3247 {
3248 wd->touched = _remove_touched_device(wd->touched, pe);
3249 }
3250
3251 /* Report current states and clear history if needed */
3252 Eina_Bool states_reset = _clear_if_finished(data);
3253 if (wd->glayer_continues_enable)
3254 continues_gestures_restart(data, states_reset);
3255}
3256
3257
3258/**
3259 * For all _mouse_* / multi_* functions wethen send this event to
3260 * _event_process function.
3261 *
3262 * @param data The gesture-layer object.
3263 * @param event_info Pointer to recent input event.
3264 *
3265 * @ingroup Elm_Gesture_Layer
3266 */
3267static void
3268_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3269 void *event_info)
3270{
3271 Widget_Data *wd = elm_widget_data_get(data);
3272 if (!wd) return;
3273 if (((Evas_Event_Mouse_Down *) event_info)->button != 1)
3274 return; /* We only process left-click at the moment */
3275
3276 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_DOWN);
3277}
3278
3279static void
3280_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3281 void *event_info)
3282{
3283 Widget_Data *wd = elm_widget_data_get(data);
3284 if (!wd) return;
3285
3286 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_MOVE);
3287}
3288
3289static void
3290_key_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3291 void *event_info)
3292{
3293 Widget_Data *wd = elm_widget_data_get(data);
3294 if (!wd) return;
3295
3296 _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_DOWN);
3297}
3298
3299static void
3300_key_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3301 void *event_info)
3302{
3303 Widget_Data *wd = elm_widget_data_get(data);
3304 if (!wd) return;
3305
3306 _event_process(data, obj, event_info, EVAS_CALLBACK_KEY_UP);
3307}
3308
3309static void
3310_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3311 void *event_info)
3312{
3313 Widget_Data *wd = elm_widget_data_get(data);
3314 if (!wd) return;
3315
3316 if (((Evas_Event_Mouse_Up *) event_info)->button != 1)
3317 return; /* We only process left-click at the moment */
3318
3319 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_UP);
3320}
3321
3322static void
3323_mouse_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3324 void *event_info)
3325{
3326 Widget_Data *wd = elm_widget_data_get(data);
3327 if (!wd) return;
3328
3329 _event_process(data, obj, event_info, EVAS_CALLBACK_MOUSE_WHEEL);
3330}
3331
3332static void
3333_multi_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3334 void *event_info)
3335{
3336 Widget_Data *wd = elm_widget_data_get(data);
3337 if (!wd) return;
3338
3339 _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_DOWN);
3340}
3341
3342static void
3343_multi_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3344 void *event_info)
3345{
3346 Widget_Data *wd = elm_widget_data_get(data);
3347 if (!wd) return;
3348
3349 _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_MOVE);
3350}
3351
3352static void
3353_multi_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
3354 void *event_info)
3355{
3356 Widget_Data *wd = elm_widget_data_get(data);
3357 if (!wd) return;
3358
3359 _event_process(data, obj, event_info, EVAS_CALLBACK_MULTI_UP);
3360}
3361
3362EAPI Eina_Bool
3363elm_gesture_layer_hold_events_get(const Evas_Object *obj)
3364{
3365 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3366
3367 Widget_Data *wd = elm_widget_data_get(obj);
3368 if (!wd) return EINA_FALSE;
3369
3370 return !wd->repeat_events;
3371}
3372
3373EAPI void
3374elm_gesture_layer_hold_events_set(Evas_Object *obj, Eina_Bool hold_events)
3375{
3376 ELM_CHECK_WIDTYPE(obj, widtype);
3377
3378 Widget_Data *wd = elm_widget_data_get(obj);
3379 if (!wd) return;
3380
3381 wd->repeat_events = !(!!hold_events);
3382}
3383
3384EAPI double
3385elm_gesture_layer_zoom_step_get(const Evas_Object *obj)
3386{
3387 ELM_CHECK_WIDTYPE(obj, widtype) 0;
3388
3389 Widget_Data *wd = elm_widget_data_get(obj);
3390 if (!wd) return 0;
3391
3392 return wd->zoom_step;
3393}
3394
3395EAPI void
3396elm_gesture_layer_zoom_step_set(Evas_Object *obj, double step)
3397{
3398 ELM_CHECK_WIDTYPE(obj, widtype);
3399
3400 Widget_Data *wd = elm_widget_data_get(obj);
3401 if (!wd) return;
3402
3403 if (step < 0) return;
3404
3405 wd->zoom_step = step;
3406}
3407
3408EAPI double
3409elm_gesture_layer_rotate_step_get(const Evas_Object *obj)
3410{
3411 ELM_CHECK_WIDTYPE(obj, widtype) 0;
3412
3413 Widget_Data *wd = elm_widget_data_get(obj);
3414 if (!wd) return 0;
3415
3416 return wd->rotate_step;
3417}
3418
3419EAPI void
3420elm_gesture_layer_rotate_step_set(Evas_Object *obj, double step)
3421{
3422 ELM_CHECK_WIDTYPE(obj, widtype);
3423
3424 Widget_Data *wd = elm_widget_data_get(obj);
3425 if (!wd) return;
3426
3427 if (step < 0) return;
3428
3429 wd->rotate_step = step;
3430}
3431
3432EAPI Eina_Bool
3433elm_gesture_layer_attach(Evas_Object *obj, Evas_Object *target)
3434{
3435 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3436
3437 Widget_Data *wd = elm_widget_data_get(obj);
3438 if (!wd) return EINA_FALSE;
3439
3440 if (!target) return EINA_FALSE;
3441
3442 /* if was attached before, unregister callbacks first */
3443 if (wd->target)
3444 _unregister_callbacks(obj);
3445
3446 wd->target = target;
3447
3448 _register_callbacks(obj);
3449 return EINA_TRUE;
3450}
3451
3452EAPI void
3453elm_gesture_layer_cb_set(Evas_Object *obj, Elm_Gesture_Type idx,
3454 Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data)
3455{
3456 ELM_CHECK_WIDTYPE(obj, widtype);
3457
3458 Widget_Data *wd = elm_widget_data_get(obj);
3459 Gesture_Info *p;
3460 if (!wd) return;
3461
3462 if (!wd->gesture[idx])
3463 wd->gesture[idx] = calloc(1, sizeof(Gesture_Info));
3464 if (!wd->gesture[idx]) return;
3465
3466 p = wd->gesture[idx];
3467 p->obj = obj;
3468 p->g_type = idx;
3469 p->fn[cb_type].cb = cb;
3470 p->fn[cb_type].user_data = data;
3471 p->state = ELM_GESTURE_STATE_UNDEFINED;
3472 SET_TEST_BIT(p);
3473}
3474
3475static void
3476_disable_hook(Evas_Object *obj)
3477{
3478 if (elm_widget_disabled_get(obj))
3479 _unregister_callbacks(obj);
3480 else
3481 _register_callbacks(obj);
3482}
3483
3484EAPI Evas_Object *
3485elm_gesture_layer_add(Evas_Object *parent)
3486{
3487 Evas_Object *obj;
3488 Evas *e;
3489 Widget_Data *wd;
3490
3491 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3492
3493 ELM_SET_WIDTYPE(widtype, "gesture_layer");
3494 elm_widget_type_set(obj, "gesture_layer");
3495 elm_widget_sub_object_add(parent, obj);
3496 elm_widget_data_set(obj, wd);
3497 elm_widget_del_hook_set(obj, _del_hook);
3498 elm_widget_disable_hook_set(obj, _disable_hook);
3499
3500 wd->target = NULL;
3501 wd->line_min_length =_elm_config->glayer_line_min_length * _elm_config->finger_size;
3502 wd->zoom_distance_tolerance = _elm_config->glayer_zoom_distance_tolerance * _elm_config->finger_size;
3503 wd->line_distance_tolerance = _elm_config->glayer_line_distance_tolerance * _elm_config->finger_size;
3504 wd->zoom_finger_factor = _elm_config->glayer_zoom_finger_factor;
3505 wd->zoom_wheel_factor = _elm_config->glayer_zoom_wheel_factor; /* mouse wheel zoom steps */
3506 wd->rotate_angular_tolerance = _elm_config->glayer_rotate_angular_tolerance;
3507 wd->line_angular_tolerance = _elm_config->glayer_line_angular_tolerance;
3508 wd->flick_time_limit_ms = _elm_config->glayer_flick_time_limit_ms;
3509 wd->long_tap_start_timeout = _elm_config->glayer_long_tap_start_timeout;
3510 wd->repeat_events = EINA_TRUE;
3511 wd->glayer_continues_enable = _elm_config->glayer_continues_enable;
3512
3513#if defined(DEBUG_GESTURE_LAYER)
3514 printf("size of Gestures = <%d>\n", sizeof(wd->gesture));
3515 printf("initial values:\n\tzoom_finger_factor=<%f>\n\tzoom_distance_tolerance=<%d>\n\tline_min_length=<%d>\n\tline_distance_tolerance=<%d>\n\tzoom_wheel_factor=<%f>\n\trotate_angular_tolerance=<%f>\n\twd->line_angular_tolerance=<%f>\n\twd->flick_time_limit_ms=<%d>\n\twd->long_tap_start_timeout=<%f>\n\twd->zoom_step=<%f>\n\twd->rotate_step=<%f>\n\twd->glayer_continues_enable=<%d>\n ", wd->zoom_finger_factor, wd->zoom_distance_tolerance, wd->line_min_length, wd->line_distance_tolerance, wd->zoom_wheel_factor, wd->rotate_angular_tolerance, wd->line_angular_tolerance, wd->flick_time_limit_ms, wd->long_tap_start_timeout, wd->zoom_step, wd->rotate_step, wd->glayer_continues_enable);
3516#endif
3517 memset(wd->gesture, 0, sizeof(wd->gesture));
3518
3519 return obj;
3520}
diff --git a/libraries/elementary/src/lib/elm_gesture_layer.h b/libraries/elementary/src/lib/elm_gesture_layer.h
new file mode 100644
index 0000000..b24babb
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_gesture_layer.h
@@ -0,0 +1,336 @@
1/**
2 * @defgroup Elm_Gesture_Layer Gesture Layer
3 * @ingroup Elementary
4 *
5 * Gesture Layer Usage:
6 *
7 * Use Gesture Layer to detect gestures.
8 * The advantage is that you don't have to implement
9 * gesture detection, just set callbacks of gesture state.
10 * By using gesture layer we make standard interface.
11 *
12 * In order to use Gesture Layer you start with @ref elm_gesture_layer_add
13 * with a parent object parameter.
14 * Next 'activate' gesture layer with a @ref elm_gesture_layer_attach
15 * call. Usually with same object as target (2nd parameter).
16 *
17 * Now you need to tell gesture layer what gestures you follow.
18 * This is done with @ref elm_gesture_layer_cb_set call.
19 * By setting the callback you actually saying to gesture layer:
20 * I would like to know when the gesture @ref Elm_Gesture_Type
21 * switches to state @ref Elm_Gesture_State.
22 *
23 * Next, you need to implement the actual action that follows the input
24 * in your callback.
25 *
26 * Note that if you like to stop being reported about a gesture, just set
27 * all callbacks referring this gesture to NULL.
28 * (again with @ref elm_gesture_layer_cb_set)
29 *
30 * The information reported by gesture layer to your callback is depending
31 * on @ref Elm_Gesture_Type:
32 * @ref Elm_Gesture_Taps_Info is the info reported for tap gestures:
33 * @ref ELM_GESTURE_N_TAPS, @ref ELM_GESTURE_N_LONG_TAPS,
34 * @ref ELM_GESTURE_N_DOUBLE_TAPS, @ref ELM_GESTURE_N_TRIPLE_TAPS.
35 *
36 * @ref Elm_Gesture_Momentum_Info is info reported for momentum gestures:
37 * @ref ELM_GESTURE_MOMENTUM.
38 *
39 * @ref Elm_Gesture_Line_Info is the info reported for line gestures:
40 * (this also contains @ref Elm_Gesture_Momentum_Info internal structure)
41 * @ref ELM_GESTURE_N_LINES, @ref ELM_GESTURE_N_FLICKS.
42 * Note that we consider a flick as a line-gesture that should be completed
43 * in flick-time-limit as defined in @ref Config.
44 *
45 * @ref Elm_Gesture_Zoom_Info is the info reported for @ref ELM_GESTURE_ZOOM gesture.
46 *
47 * @ref Elm_Gesture_Rotate_Info is the info reported for @ref ELM_GESTURE_ROTATE gesture.
48 *
49 *
50 * Gesture Layer Tweaks:
51 *
52 * Note that line, flick, gestures can start without the need to remove fingers from surface.
53 * When user fingers rests on same-spot gesture is ended and starts again when fingers moved.
54 *
55 * Setting glayer_continues_enable to false in @ref Config will change this behavior
56 * so gesture starts when user touches (a *DOWN event) touch-surface
57 * and ends when no fingers touches surface (a *UP event).
58 *
59 * Supported elm_object common APIs.
60 * @li @ref elm_object_disabled_set
61 * @li @ref elm_object_disabled_get
62 *
63 */
64
65/**
66 * Enum of supported gesture types.
67 * @ingroup Elm_Gesture_Layer
68 */
69typedef enum
70{
71 ELM_GESTURE_FIRST = 0,
72
73 ELM_GESTURE_N_TAPS, /**< N fingers single taps */
74 ELM_GESTURE_N_LONG_TAPS, /**< N fingers single long-taps */
75 ELM_GESTURE_N_DOUBLE_TAPS, /**< N fingers double-single taps */
76 ELM_GESTURE_N_TRIPLE_TAPS, /**< N fingers triple-single taps */
77
78 ELM_GESTURE_MOMENTUM, /**< Reports momentum in the direction of move */
79
80 ELM_GESTURE_N_LINES, /**< N fingers line gesture */
81 ELM_GESTURE_N_FLICKS, /**< N fingers flick gesture */
82
83 ELM_GESTURE_ZOOM, /**< Zoom */
84 ELM_GESTURE_ROTATE, /**< Rotate */
85
86 ELM_GESTURE_LAST
87} Elm_Gesture_Type;
88
89/**
90 * @enum _Elm_Gesture_State
91 * Enum of gesture states.
92 * @ingroup Elm_Gesture_Layer
93 */
94typedef enum
95{
96 ELM_GESTURE_STATE_UNDEFINED = -1, /**< Gesture not STARTed */
97 ELM_GESTURE_STATE_START, /**< Gesture STARTed */
98 ELM_GESTURE_STATE_MOVE, /**< Gesture is ongoing */
99 ELM_GESTURE_STATE_END, /**< Gesture completed */
100 ELM_GESTURE_STATE_ABORT /**< Ongoing gesture was ABORTed */
101} Elm_Gesture_State;
102
103/**
104 * @struct _Elm_Gesture_Taps_Info
105 * Struct holds taps info for user
106 * @ingroup Elm_Gesture_Layer
107 */
108struct _Elm_Gesture_Taps_Info
109{
110 Evas_Coord x, y; /**< Holds center point between fingers */
111 unsigned int n; /**< Number of fingers tapped */
112 unsigned int timestamp; /**< event timestamp */
113};
114
115/**
116 * @typedef Elm_Gesture_Taps_Info
117 * holds taps info for user
118 * @ingroup Elm_Gesture_Layer
119 */
120typedef struct _Elm_Gesture_Taps_Info Elm_Gesture_Taps_Info;
121
122/**
123 * @struct _Elm_Gesture_Momentum_Info
124 * Struct holds momentum info for user
125 * x1 and y1 are not necessarily in sync
126 * x1 holds x value of x direction starting point
127 * and same holds for y1.
128 * This is noticeable when doing V-shape movement
129 * @ingroup Elm_Gesture_Layer
130 */
131struct _Elm_Gesture_Momentum_Info /* Report line ends, timestamps, and momentum computed */
132{Evas_Coord x1; /**< Final-swipe direction starting point on X */
133 Evas_Coord y1; /**< Final-swipe direction starting point on Y */
134 Evas_Coord x2; /**< Final-swipe direction ending point on X */
135 Evas_Coord y2; /**< Final-swipe direction ending point on Y */
136
137 unsigned int tx; /**< Timestamp of start of final x-swipe */
138 unsigned int ty; /**< Timestamp of start of final y-swipe */
139
140 Evas_Coord mx; /**< Momentum on X */
141 Evas_Coord my; /**< Momentum on Y */
142
143 unsigned int n; /**< Number of fingers */
144};
145
146/**
147 * @typedef Elm_Gesture_Momentum_Info
148 * holds momentum info for user
149 * @ingroup Elm_Gesture_Layer
150 */
151typedef struct _Elm_Gesture_Momentum_Info Elm_Gesture_Momentum_Info;
152
153/**
154 * @struct _Elm_Gesture_Line_Info
155 * Struct holds line info for user
156 * @ingroup Elm_Gesture_Layer
157 */
158struct _Elm_Gesture_Line_Info /* Report line ends, timestamps, and momentum computed */
159{Elm_Gesture_Momentum_Info momentum; /**< Line momentum info */
160 double angle; /**< Angle (direction) of lines */
161};
162
163/**
164 * @typedef Elm_Gesture_Line_Info
165 * Holds line info for user
166 * @ingroup Elm_Gesture_Layer
167 */
168typedef struct _Elm_Gesture_Line_Info Elm_Gesture_Line_Info;
169
170/**
171 * @struct _Elm_Gesture_Zoom_Info
172 * Struct holds zoom info for user
173 * @ingroup Elm_Gesture_Layer
174 */
175struct _Elm_Gesture_Zoom_Info
176{
177 Evas_Coord x, y; /**< Holds zoom center point reported to user */
178 Evas_Coord radius; /**< Holds radius between fingers reported to user */
179 double zoom; /**< Zoom value: 1.0 means no zoom */
180 double momentum; /**< Zoom momentum: zoom growth per second (NOT YET SUPPORTED) */
181};
182
183/**
184 * @typedef Elm_Gesture_Zoom_Info
185 * Holds zoom info for user
186 * @ingroup Elm_Gesture_Layer
187 */
188typedef struct _Elm_Gesture_Zoom_Info Elm_Gesture_Zoom_Info;
189
190/**
191 * @struct _Elm_Gesture_Rotate_Info
192 * Struct holds rotation info for user
193 * @ingroup Elm_Gesture_Layer
194 */
195struct _Elm_Gesture_Rotate_Info
196{
197 Evas_Coord x, y; /**< Holds zoom center point reported to user */
198 Evas_Coord radius; /**< Holds radius between fingers reported to user */
199 double base_angle; /**< Holds start-angle */
200 double angle; /**< Rotation value: 0.0 means no rotation */
201 double momentum; /**< Rotation momentum: rotation done per second (NOT YET SUPPORTED) */
202};
203
204/**
205 * @typedef Elm_Gesture_Rotate_Info
206 * Holds rotation info for user
207 * @ingroup Elm_Gesture_Layer
208 */
209typedef struct _Elm_Gesture_Rotate_Info Elm_Gesture_Rotate_Info;
210
211/**
212 * @typedef Elm_Gesture_Event_Cb
213 * User callback used to stream gesture info from gesture layer
214 * @param data user data
215 * @param event_info gesture report info
216 * Returns a flag field to be applied on the causing event.
217 * You should probably return EVAS_EVENT_FLAG_ON_HOLD if your widget acted
218 * upon the event, in an irreversible way.
219 *
220 * @ingroup Elm_Gesture_Layer
221 */
222typedef Evas_Event_Flags (*Elm_Gesture_Event_Cb)(void *data, void *event_info);
223
224/**
225 * Use function to set callbacks to be notified about
226 * change of state of gesture.
227 * When a user registers a callback with this function
228 * this means this gesture has to be tested.
229 *
230 * When ALL callbacks for a gesture are set to NULL
231 * it means user isn't interested in gesture-state
232 * and it will not be tested.
233 *
234 * @param obj gesture-layer.
235 * @param idx The gesture you would like to track its state.
236 * @param cb callback function pointer.
237 * @param cb_type what event this callback tracks: START, MOVE, END, ABORT.
238 * @param data user info to be sent to callback (usually, Smart Data)
239 *
240 * @ingroup Elm_Gesture_Layer
241 */
242EAPI void elm_gesture_layer_cb_set(Evas_Object *obj, Elm_Gesture_Type idx, Elm_Gesture_State cb_type, Elm_Gesture_Event_Cb cb, void *data);
243
244/**
245 * Call this function to get repeat-events settings.
246 *
247 * @param obj gesture-layer.
248 *
249 * @return repeat events settings.
250 * @see elm_gesture_layer_hold_events_set()
251 * @ingroup Elm_Gesture_Layer
252 */
253EAPI Eina_Bool elm_gesture_layer_hold_events_get(const Evas_Object *obj);
254
255/**
256 * This function is to make gesture-layer repeat events.
257 * Set this if you like to get the raw events only if gestures were not
258 * detected.
259 * Clear this if you like gesture layer to forward events as testing gestures.
260 *
261 * @param obj gesture layer.
262 * @param hold_events hold events or not.
263 *
264 * @ingroup Elm_Gesture_Layer
265 */
266EAPI void elm_gesture_layer_hold_events_set(Evas_Object *obj, Eina_Bool hold_events);
267
268/**
269 * This function sets step-value for zoom action.
270 * Set step to any positive value.
271 * Cancel step setting by setting to 0
272 *
273 * @param obj gesture-layer.
274 * @param step new zoom step value.
275 *
276 * @see elm_gesture_layer_zoom_step_get()
277 * @ingroup Elm_Gesture_Layer
278 */
279EAPI void elm_gesture_layer_zoom_step_set(Evas_Object *obj, double step);
280
281/**
282 * This function returns step-value for zoom action.
283 *
284 * @param obj gesture-layer.
285 * @return zoom step value.
286 *
287 * @see elm_gesture_layer_zoom_step_set()
288 * @ingroup Elm_Gesture_Layer
289 */
290EAPI double elm_gesture_layer_zoom_step_get(const Evas_Object *obj);
291
292/**
293 * This function sets step-value for rotate action.
294 * Set step to any positive value.
295 * Cancel step setting by setting to 0
296 *
297 * @param obj gesture-layer.
298 * @param step new rotate step value.
299 *
300 * @ingroup Elm_Gesture_Layer
301 */
302EAPI void elm_gesture_layer_rotate_step_set(Evas_Object *obj, double step);
303
304/**
305 * This function returns step-value for rotate action.
306 *
307 * @param obj gesture-layer.
308 * @return rotate step value.
309 *
310 * @ingroup Elm_Gesture_Layer
311 */
312EAPI double elm_gesture_layer_rotate_step_get(const Evas_Object *obj);
313
314/**
315 * This function called to attach gesture-layer to an Evas_Object.
316 * @param obj gesture-layer.
317 * @param target Pointer to underlying object (AKA Target)
318 *
319 * @return TRUE, FALSE on success, failure.
320 *
321 * @ingroup Elm_Gesture_Layer
322 */
323EAPI Eina_Bool elm_gesture_layer_attach(Evas_Object *obj, Evas_Object *target);
324
325/**
326 * Call this function to construct a new gesture-layer object.
327 * This does not activate the gesture layer. You have to
328 * call elm_gesture_layer_attach in order to 'activate' gesture-layer.
329 *
330 * @param parent the parent object.
331 *
332 * @return new gesture-layer object.
333 *
334 * @ingroup Elm_Gesture_Layer
335 */
336EAPI Evas_Object *elm_gesture_layer_add(Evas_Object *parent);
diff --git a/libraries/elementary/src/lib/elm_getting_started.h b/libraries/elementary/src/lib/elm_getting_started.h
new file mode 100644
index 0000000..9b11a54
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_getting_started.h
@@ -0,0 +1,197 @@
1/**
2 * @defgroup Start Getting Started
3 * @ingroup Elementary
4 *
5 * To write an Elementary app, you can get started with the following:
6 *
7 * @code
8 * #include <Elementary.h>
9 * EAPI_MAIN int
10 * elm_main(int argc, char **argv)
11 * {
12 * // create window(s) here and do any application init
13 * elm_run(); // run main loop
14 * elm_shutdown(); // after mainloop finishes running, shutdown
15 * return 0; // exit 0 for exit code
16 * }
17 * ELM_MAIN()
18 * @endcode
19 *
20 * To use autotools (which helps in many ways in the long run, like being able
21 * to immediately create releases of your software directly from your tree
22 * and ensure everything needed to build it is there) you will need a
23 * configure.ac, Makefile.am and autogen.sh file.
24 *
25 * configure.ac:
26 *
27 * @verbatim
28 * AC_INIT(myapp, 0.0.0, myname@mydomain.com)
29 * AC_PREREQ(2.52)
30 * AC_CONFIG_SRCDIR(configure.ac)
31 * AM_CONFIG_HEADER(config.h)
32 * AC_PROG_CC
33 * AM_INIT_AUTOMAKE(1.6 dist-bzip2)
34 * PKG_CHECK_MODULES([ELEMENTARY], elementary)
35 * AC_OUTPUT(Makefile)
36 * @endverbatim
37 *
38 * Makefile.am:
39 *
40 * @verbatim
41 * AUTOMAKE_OPTIONS = 1.4 foreign
42 * MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.h.in configure depcomp install-sh missing
43 *
44 * INCLUDES = -I$(top_srcdir)
45 *
46 * bin_PROGRAMS = myapp
47 *
48 * myapp_SOURCES = main.c
49 * myapp_LDADD = @ELEMENTARY_LIBS@
50 * myapp_CFLAGS = @ELEMENTARY_CFLAGS@
51 * @endverbatim
52 *
53 * autogen.sh:
54 *
55 * @verbatim
56 *#!/bin/sh
57 * echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1
58 * echo "Running autoheader..." ; autoheader || exit 1
59 * echo "Running autoconf..." ; autoconf || exit 1
60 * echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
61 * ./configure "$@"
62 * @endverbatim
63 *
64 * To generate all the things needed to bootstrap just run:
65 *
66 * @verbatim
67 * ./autogen.sh
68 * @endverbatim
69 *
70 * This will generate Makefile.in's, the configure script and everything else.
71 * After this it works like all normal autotools projects:
72 * @verbatim
73 * ./configure
74 * make
75 * sudo make install
76 * @endverbatim
77 *
78 * Note sudo was assumed to get root permissions, as this would install in
79 * /usr/local which is system-owned. Use any way you like to gain root, or
80 * specify a different prefix with configure:
81 *
82 * @verbatim
83 * ./configure --prefix=$HOME/mysoftware
84 * @endverbatim
85 *
86 * Also remember that autotools buys you some useful commands like:
87 * @verbatim
88 * make uninstall
89 * @endverbatim
90 *
91 * This uninstalls the software after it was installed with "make install".
92 * It is very useful to clear up what you built if you wish to clean the
93 * system.
94 *
95 * @verbatim
96 * make distcheck
97 * @endverbatim
98 *
99 * This firstly checks if your build tree is "clean" and ready for
100 * distribution. It also builds a tarball (myapp-0.0.0.tar.gz) that is
101 * ready to upload and distribute to the world, that contains the generated
102 * Makefile.in's and configure script. The users do not need to run
103 * autogen.sh - just configure and on. They don't need autotools installed.
104 * This tarball also builds cleanly, has all the sources it needs to build
105 * included (that is sources for your application, not libraries it depends
106 * on like Elementary). It builds cleanly in a buildroot and does not
107 * contain any files that are temporarily generated like binaries and other
108 * build-generated files, so the tarball is clean, and no need to worry
109 * about cleaning up your tree before packaging.
110 *
111 * @verbatim
112 * make clean
113 * @endverbatim
114 *
115 * This cleans up all build files (binaries, objects etc.) from the tree.
116 *
117 * @verbatim
118 * make distclean
119 * @endverbatim
120 *
121 * This cleans out all files from the build and from configure's output too.
122 *
123 * @verbatim
124 * make maintainer-clean
125 * @endverbatim
126 *
127 * This deletes all the files autogen.sh will produce so the tree is clean
128 * to be put into a revision-control system (like CVS, SVN or GIT for example).
129 *
130 * There is a more advanced way of making use of the quicklaunch infrastructure
131 * in Elementary (which will not be covered here due to its more advanced
132 * nature).
133 *
134 * Now let's actually create an interactive "Hello World" gui that you can
135 * click the ok button to exit. It's more code because this now does something
136 * much more significant, but it's still very simple:
137 *
138 * @code
139 * #include <Elementary.h>
140 *
141 * static void
142 * on_done(void *data, Evas_Object *obj, void *event_info)
143 * {
144 * // quit the mainloop (elm_run function will return)
145 * elm_exit();
146 * }
147 *
148 * EAPI_MAIN int
149 * elm_main(int argc, char **argv)
150 * {
151 * Evas_Object *win, *box, *lab, *btn;
152 *
153 * // new window - do the usual and give it a name (hello) and title (Hello)
154 * win = elm_win_util_standard_add("hello", "Hello");
155 * // when the user clicks "close" on a window there is a request to delete
156 * evas_object_smart_callback_add(win, "delete,request", on_done, NULL);
157 *
158 * // add a box object - default is vertical. a box holds children in a row,
159 * // either horizontally or vertically. nothing more.
160 * box = elm_box_add(win);
161 * // make the box horizontal
162 * elm_box_horizontal_set(box, EINA_TRUE);
163 * // add object as a resize object for the window (controls window minimum
164 * // size as well as gets resized if window is resized)
165 * elm_win_resize_object_add(win, box);
166 * evas_object_show(box);
167 *
168 * // add a label widget, set the text and put it in the pad frame
169 * lab = elm_label_add(win);
170 * // set default text of the label
171 * elm_object_text_set(lab, "Hello out there world!");
172 * // pack the label at the end of the box
173 * elm_box_pack_end(box, lab);
174 * evas_object_show(lab);
175 *
176 * // add an ok button
177 * btn = elm_button_add(win);
178 * // set default text of button to "OK"
179 * elm_object_text_set(btn, "OK");
180 * // pack the button at the end of the box
181 * elm_box_pack_end(box, btn);
182 * evas_object_show(btn);
183 * // call on_done when button is clicked
184 * evas_object_smart_callback_add(btn, "clicked", on_done, NULL);
185 *
186 * // now we are done, show the window
187 * evas_object_show(win);
188 *
189 * // run the mainloop and process events and callbacks
190 * elm_run();
191 * elm_shutdown();
192 * return 0;
193 * }
194 * ELM_MAIN()
195 * @endcode
196 *
197 */
diff --git a/libraries/elementary/src/lib/elm_glview.c b/libraries/elementary/src/lib/elm_glview.c
new file mode 100644
index 0000000..339f23f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_glview.c
@@ -0,0 +1,462 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *glview_image;
9
10 Elm_GLView_Mode mode;
11 Elm_GLView_Resize_Policy scale_policy;
12 Elm_GLView_Render_Policy render_policy;
13
14 Evas_GL *evasgl;
15 Evas_GL_Config *config;
16 Evas_GL_Surface *surface;
17 Evas_GL_Context *context;
18
19 Evas_Coord w, h;
20
21 Elm_GLView_Func_Cb init_func;
22 Elm_GLView_Func_Cb del_func;
23 Elm_GLView_Func_Cb resize_func;
24 Elm_GLView_Func_Cb render_func;
25
26 Ecore_Idle_Enterer *render_idle_enterer;
27
28 Eina_Bool initialized;
29 Eina_Bool resized;
30};
31
32static const char *widtype = NULL;
33static void _del_hook(Evas_Object *obj);
34static void _on_focus_hook(void *data, Evas_Object *obj);
35
36static const char SIG_FOCUSED[] = "focused";
37static const char SIG_UNFOCUSED[] = "unfocused";
38
39static void
40_del_hook(Evas_Object *obj)
41{
42 Widget_Data *wd = elm_widget_data_get(obj);
43 if (!wd) return;
44
45 // Call delete func if it's registered
46 if (wd->del_func)
47 {
48 evas_gl_make_current(wd->evasgl, wd->surface, wd->context);
49 wd->del_func(obj);
50 }
51
52 if (wd->render_idle_enterer) ecore_idle_enterer_del(wd->render_idle_enterer);
53
54 if (wd->surface) evas_gl_surface_destroy(wd->evasgl, wd->surface);
55 if (wd->context) evas_gl_context_destroy(wd->evasgl, wd->context);
56 if (wd->config) evas_gl_config_free(wd->config);
57 if (wd->evasgl) evas_gl_free(wd->evasgl);
58
59 free(wd);
60}
61
62static void
63_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
64{
65 Widget_Data *wd = elm_widget_data_get(obj);
66 if (!wd) return;
67
68 if (elm_widget_focus_get(obj))
69 {
70 evas_object_focus_set(wd->glview_image, EINA_TRUE);
71 evas_object_smart_callback_call(obj, SIG_FOCUSED, NULL);
72 }
73 else
74 {
75 evas_object_focus_set(wd->glview_image, EINA_FALSE);
76 evas_object_smart_callback_call(obj, SIG_UNFOCUSED, NULL);
77 }
78}
79
80static void
81_glview_update_surface(Evas_Object *obj)
82{
83 Widget_Data *wd = elm_widget_data_get(obj);
84 if (!wd) return;
85
86 if (wd->surface)
87 {
88 evas_object_image_native_surface_set(wd->glview_image, NULL);
89 evas_gl_surface_destroy(wd->evasgl, wd->surface);
90 wd->surface = NULL;
91 }
92
93 evas_object_image_size_set(wd->glview_image, wd->w, wd->h);
94
95 if (!wd->surface)
96 {
97 Evas_Native_Surface ns;
98
99 wd->surface = evas_gl_surface_create(wd->evasgl, wd->config,
100 wd->w, wd->h);
101 evas_gl_native_surface_get(wd->evasgl, wd->surface, &ns);
102 evas_object_image_native_surface_set(wd->glview_image, &ns);
103 elm_glview_changed_set(obj);
104 }
105}
106
107static void
108_glview_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
109{
110 Widget_Data *wd = elm_widget_data_get(data);
111 Evas_Coord w, h;
112
113 if (!wd) return;
114
115 wd->resized = EINA_TRUE;
116
117 if (wd->scale_policy == ELM_GLVIEW_RESIZE_POLICY_RECREATE)
118 {
119 evas_object_geometry_get(wd->glview_image, NULL, NULL, &w, &h);
120 if ((w == 0) || (h == 0))
121 {
122 w = 64;
123 h = 64;
124 }
125 if ((wd->w == w) && (wd->h == h)) return;
126 wd->w = w;
127 wd->h = h;
128 _glview_update_surface(data);
129 }
130}
131
132static Eina_Bool
133_render_cb(void *obj)
134{
135 Widget_Data *wd = elm_widget_data_get(obj);
136 if (!wd) return EINA_FALSE;
137
138 // Do a make current
139 if (!evas_gl_make_current(wd->evasgl, wd->surface, wd->context))
140 {
141 wd->render_idle_enterer = NULL;
142 ERR("Failed doing make current.\n");
143 return EINA_FALSE;
144 }
145
146 // Call the init function if it hasn't been called already
147 if (!wd->initialized)
148 {
149 if (wd->init_func) wd->init_func(obj);
150 wd->initialized = EINA_TRUE;
151 }
152
153 if (wd->resized)
154 {
155 if (wd->resize_func) wd->resize_func(obj);
156 wd->resized = EINA_FALSE;
157 }
158
159 // Call the render function
160 if (wd->render_func) wd->render_func(obj);
161
162 // Depending on the policy return true or false
163 if (wd->render_policy == ELM_GLVIEW_RENDER_POLICY_ON_DEMAND)
164 return EINA_TRUE;
165 else if (wd->render_policy == ELM_GLVIEW_RENDER_POLICY_ALWAYS)
166 {
167 // Return false so it only runs once
168 wd->render_idle_enterer = NULL;
169 return EINA_FALSE;
170 }
171 else
172 {
173 ERR("Invalid Render Policy.\n");
174 wd->render_idle_enterer = NULL;
175 return EINA_FALSE;
176 }
177 return EINA_TRUE;
178}
179
180static void
181_set_render_policy_callback(Evas_Object *obj)
182{
183 Widget_Data *wd = elm_widget_data_get(obj);
184
185 switch (wd->render_policy)
186 {
187 case ELM_GLVIEW_RENDER_POLICY_ON_DEMAND:
188 // Delete idle_enterer if it for some reason is around
189 if (wd->render_idle_enterer)
190 {
191 ecore_idle_enterer_del(wd->render_idle_enterer);
192 wd->render_idle_enterer = NULL;
193 }
194
195 // Set pixel getter callback
196 evas_object_image_pixels_get_callback_set
197 (wd->glview_image, (Evas_Object_Image_Pixels_Get_Cb)_render_cb, obj);
198 break;
199 case ELM_GLVIEW_RENDER_POLICY_ALWAYS:
200 // Unset the pixel getter callback if set already
201 evas_object_image_pixels_get_callback_set(wd->glview_image, NULL, NULL);
202
203 break;
204 default:
205 ERR("Invalid Render Policy.\n");
206 return;
207 }
208}
209
210EAPI Evas_Object *
211elm_glview_add(Evas_Object *parent)
212{
213 Evas_Object *obj;
214 Evas *e;
215 Widget_Data *wd;
216
217 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
218
219 ELM_SET_WIDTYPE(widtype, "glview");
220 elm_widget_type_set(obj, "glview");
221 elm_widget_sub_object_add(parent, obj);
222 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
223 elm_widget_data_set(obj, wd);
224 elm_widget_del_hook_set(obj, _del_hook);
225
226 // Evas_GL
227 wd->evasgl = evas_gl_new(e);
228 if (!wd->evasgl)
229 {
230 ERR("Failed Creating an Evas GL Object.\n");
231 return NULL;
232 }
233
234 // Create a default config
235 wd->config = evas_gl_config_new();
236 if (!wd->config)
237 {
238 ERR("Failed Creating a Config Object.\n");
239 evas_gl_free(wd->evasgl);
240 return NULL;
241 }
242 wd->config->color_format = EVAS_GL_RGB_888;
243
244 // Create image to render Evas_GL Surface
245 wd->glview_image = evas_object_image_filled_add(e);
246 evas_object_image_size_set(wd->glview_image, 1, 1);
247 evas_object_event_callback_add(wd->glview_image, EVAS_CALLBACK_RESIZE,
248 _glview_resize, obj);
249 elm_widget_resize_object_set(obj, wd->glview_image);
250 evas_object_show(wd->glview_image);
251
252 // Initialize variables
253 wd->mode = 0;
254 wd->scale_policy = ELM_GLVIEW_RESIZE_POLICY_RECREATE;
255 wd->render_policy = ELM_GLVIEW_RENDER_POLICY_ON_DEMAND;
256 wd->surface = NULL;
257
258 // Initialize it to (64,64) (It's an arbitrary value)
259 wd->w = 64;
260 wd->h = 64;
261
262 // Initialize the rest of the values
263 wd->init_func = NULL;
264 wd->del_func = NULL;
265 wd->render_func = NULL;
266 wd->render_idle_enterer = NULL;
267 wd->initialized = EINA_FALSE;
268 wd->resized = EINA_FALSE;
269
270 // Create Context
271 if (!wd->context)
272 {
273 wd->context = evas_gl_context_create(wd->evasgl, NULL);
274 if (!wd->context)
275 {
276 ERR("Error Creating an Evas_GL Context.\n");
277 return NULL;
278 }
279 }
280 return obj;
281}
282
283EAPI Evas_GL_API *
284elm_glview_gl_api_get(const Evas_Object *obj)
285{
286 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
287 Widget_Data *wd = elm_widget_data_get(obj);
288 if (!wd) return NULL;
289
290 return evas_gl_api_get(wd->evasgl);
291}
292
293EAPI Eina_Bool
294elm_glview_mode_set(Evas_Object *obj, Elm_GLView_Mode mode)
295{
296 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
297 Widget_Data *wd = elm_widget_data_get(obj);
298 if (!wd) return EINA_FALSE;
299
300 // Set the configs
301 if (mode & ELM_GLVIEW_ALPHA)
302 wd->config->color_format = EVAS_GL_RGBA_8888;
303 else
304 wd->config->color_format = EVAS_GL_RGB_888;
305
306 if (mode & ELM_GLVIEW_DEPTH)
307 wd->config->depth_bits = EVAS_GL_DEPTH_BIT_24;
308 else
309 wd->config->depth_bits = EVAS_GL_DEPTH_NONE;
310
311 if (mode & ELM_GLVIEW_STENCIL)
312 wd->config->stencil_bits = EVAS_GL_STENCIL_BIT_8;
313 else
314 wd->config->stencil_bits = EVAS_GL_STENCIL_NONE;
315
316 if (mode & ELM_GLVIEW_DIRECT)
317 wd->config->options_bits = EVAS_GL_OPTIONS_DIRECT;
318 else
319 wd->config->options_bits = EVAS_GL_OPTIONS_NONE;
320
321 // Check for Alpha Channel and enable it
322 if (mode & ELM_GLVIEW_ALPHA)
323 evas_object_image_alpha_set(wd->glview_image, EINA_TRUE);
324 else
325 evas_object_image_alpha_set(wd->glview_image, EINA_FALSE);
326
327 wd->mode = mode;
328
329 elm_glview_changed_set(obj);
330
331 return EINA_TRUE;
332}
333
334EAPI Eina_Bool
335elm_glview_resize_policy_set(Evas_Object *obj, Elm_GLView_Resize_Policy policy)
336{
337 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
338 Widget_Data *wd = elm_widget_data_get(obj);
339 if (!wd) return EINA_FALSE;
340
341 if (policy == wd->scale_policy) return EINA_TRUE;
342 switch (policy)
343 {
344 case ELM_GLVIEW_RESIZE_POLICY_RECREATE:
345 case ELM_GLVIEW_RESIZE_POLICY_SCALE:
346 wd->scale_policy = policy;
347 _glview_update_surface(obj);
348 elm_glview_changed_set(obj);
349 return EINA_TRUE;
350 default:
351 ERR("Invalid Scale Policy.\n");
352 return EINA_FALSE;
353 }
354}
355
356EAPI Eina_Bool
357elm_glview_render_policy_set(Evas_Object *obj, Elm_GLView_Render_Policy policy)
358{
359 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
360 Widget_Data *wd = elm_widget_data_get(obj);
361 if (!wd) return EINA_FALSE;
362
363 if ((policy != ELM_GLVIEW_RENDER_POLICY_ON_DEMAND) &&
364 (policy != ELM_GLVIEW_RENDER_POLICY_ALWAYS))
365 {
366 ERR("Invalid Render Policy.\n");
367 return EINA_FALSE;
368 }
369 if (wd->render_policy == policy) return EINA_TRUE;
370 wd->render_policy = policy;
371 _set_render_policy_callback(obj);
372 _glview_update_surface(obj);
373 return EINA_TRUE;
374}
375
376EAPI void
377elm_glview_size_set(Evas_Object *obj, int w, int h)
378{
379 ELM_CHECK_WIDTYPE(obj, widtype);
380 Widget_Data *wd = elm_widget_data_get(obj);
381 if (!wd) return;
382
383 if ((w == wd->w) && (h == wd->h)) return;
384 wd->w = w;
385 wd->h = h;
386 _glview_update_surface(obj);
387 elm_glview_changed_set(obj);
388}
389
390EAPI void
391elm_glview_size_get(const Evas_Object *obj, int *w, int *h)
392{
393 ELM_CHECK_WIDTYPE(obj, widtype);
394 Widget_Data *wd = elm_widget_data_get(obj);
395 if (!wd) return;
396
397 if (w) *w = wd->w;
398 if (h) *h = wd->h;
399}
400
401EAPI void
402elm_glview_init_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func)
403{
404 ELM_CHECK_WIDTYPE(obj, widtype);
405 Widget_Data *wd = elm_widget_data_get(obj);
406 if (!wd) return;
407
408 wd->initialized = EINA_FALSE;
409 wd->init_func = func;
410}
411
412EAPI void
413elm_glview_del_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func)
414{
415 ELM_CHECK_WIDTYPE(obj, widtype);
416 Widget_Data *wd = elm_widget_data_get(obj);
417 if (!wd) return;
418
419 wd->del_func = func;
420}
421
422EAPI void
423elm_glview_resize_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func)
424{
425 ELM_CHECK_WIDTYPE(obj, widtype);
426 Widget_Data *wd = elm_widget_data_get(obj);
427 if (!wd)
428 {
429 ERR("Invalid Widget Object.\n");
430 return;
431 }
432
433 wd->resize_func = func;
434}
435
436EAPI void
437elm_glview_render_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func)
438{
439 ELM_CHECK_WIDTYPE(obj, widtype);
440 Widget_Data *wd = elm_widget_data_get(obj);
441 if (!wd) return;
442
443 wd->render_func = func;
444 _set_render_policy_callback(obj);
445}
446
447EAPI void
448elm_glview_changed_set(Evas_Object *obj)
449{
450 ELM_CHECK_WIDTYPE(obj, widtype);
451 Widget_Data *wd = elm_widget_data_get(obj);
452 if (!wd) return;
453
454 evas_object_image_pixels_dirty_set(wd->glview_image, EINA_TRUE);
455 if (wd->render_policy == ELM_GLVIEW_RENDER_POLICY_ALWAYS)
456 {
457 if (!wd->render_idle_enterer)
458 wd->render_idle_enterer = ecore_idle_enterer_before_add((Ecore_Task_Cb)_render_cb, obj);
459 }
460}
461
462/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/elm_glview.h b/libraries/elementary/src/lib/elm_glview.h
new file mode 100644
index 0000000..30dff2b
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_glview.h
@@ -0,0 +1,226 @@
1/**
2 * @defgroup GLView GLView
3 * @ingroup Elementary
4 *
5 * A GLView widget allows for simple GL rendering in elementary environment.
6 * GLView hides all the complicated evas_gl details so that the user only
7 * has to deal with registering a few callback functions for rendering
8 * to a surface using OpenGL APIs.
9 *
10 * Below is an illustrative example of how to use GLView and and OpenGL
11 * to render in elementary environment.
12 * @ref glview_example_01_page
13 *
14 */
15
16typedef void (*Elm_GLView_Func_Cb)(Evas_Object *obj);
17
18typedef enum _Elm_GLView_Mode
19{
20 ELM_GLVIEW_NONE = 0,
21 ELM_GLVIEW_ALPHA = (1<<1), /**< Alpha channel enabled rendering mode */
22 ELM_GLVIEW_DEPTH = (1<<2), /**< Depth buffer enabled rendering mode */
23 ELM_GLVIEW_STENCIL = (1<<3), /**< Stencil buffer enabled rendering mode */
24 ELM_GLVIEW_DIRECT = (1<<4) /**< Direct rendering optimization hint */
25} Elm_GLView_Mode;
26
27/**
28 * Defines a policy for the glview resizing.
29 *
30 * The resizing policy tells glview what to do with the underlying
31 * surface when resize happens. ELM_GLVIEW_RESIZE_POLICY_RECREATE
32 * will destroy the current surface and recreate the surface to the
33 * new size. ELM_GLVIEW_RESIZE_POLICY_SCALE will instead keep the
34 * current surface but only display the result at the desired size
35 * scaled.
36 *
37 * @note Default is ELM_GLVIEW_RESIZE_POLICY_RECREATE
38 */
39typedef enum
40{
41 ELM_GLVIEW_RESIZE_POLICY_RECREATE = 1, /**< Resize the internal surface along with the image */
42 ELM_GLVIEW_RESIZE_POLICY_SCALE = 2 /**< Only resize the internal image and not the surface */
43} Elm_GLView_Resize_Policy;
44
45/**
46 * Defines a policy for gl rendering.
47 *
48 * The rendering policy tells glview where to run the gl rendering code.
49 * ELM_GLVIEW_RENDER_POLICY_ON_DEMAND tells glview to call the rendering
50 * calls on demand, which means that the rendering code gets called
51 * only when it is visible.
52 *
53 * @note Default is ELM_GLVIEW_RENDER_POLICY_ON_DEMAND
54 */
55typedef enum
56{
57 ELM_GLVIEW_RENDER_POLICY_ON_DEMAND = 1, /**< Render only when there is a need for redrawing */
58 ELM_GLVIEW_RENDER_POLICY_ALWAYS = 2 /**< Render always even when it is not visible */
59} Elm_GLView_Render_Policy;
60
61/**
62 * Add a new glview to the parent
63 *
64 * @param parent The parent object
65 * @return The new object or NULL if it cannot be created
66 *
67 * @ingroup GLView
68 */
69EAPI Evas_Object *elm_glview_add(Evas_Object *parent);
70
71/**
72 * Sets the size of the glview
73 *
74 * @param obj The glview object
75 * @param w width of the glview object
76 * @param h height of the glview object
77 *
78 * @ingroup GLView
79 */
80EAPI void elm_glview_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
81
82/**
83 * Gets the size of the glview.
84 *
85 * @param obj The glview object
86 * @param w width of the glview object
87 * @param h height of the glview object
88 *
89 * Note that this function returns the actual image size of the
90 * glview. This means that when the scale policy is set to
91 * ELM_GLVIEW_RESIZE_POLICY_SCALE, it'll return the non-scaled
92 * size.
93 *
94 * @ingroup GLView
95 */
96EAPI void elm_glview_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
97
98/**
99 * Gets the gl api struct for gl rendering
100 *
101 * @param obj The glview object
102 * @return The api object or NULL if it cannot be created
103 *
104 * @ingroup GLView
105 */
106EAPI Evas_GL_API *elm_glview_gl_api_get(const Evas_Object *obj);
107
108/**
109 * Set the mode of the GLView. Supports alpha, depth, stencil.
110 *
111 * @param obj The glview object
112 * @param mode The mode Options OR'ed enabling Alpha, Depth, Stencil, Direct.
113 * @return True if set properly.
114 *
115 * Direct is a hint for the elm_glview to render directly to the window
116 * given that the right conditions are met. Otherwise it falls back
117 * to rendering to an offscreen buffer before it gets composited to the
118 * window.
119 *
120 * @ingroup GLView
121 */
122EAPI Eina_Bool elm_glview_mode_set(Evas_Object *obj, Elm_GLView_Mode mode);
123
124/**
125 * Set the resize policy for the glview object.
126 *
127 * @param obj The glview object.
128 * @param policy The scaling policy.
129 *
130 * By default, the resize policy is set to ELM_GLVIEW_RESIZE_POLICY_RECREATE.
131 * When resize is called it destroys the previous surface and recreates the
132 * newly specified size. If the policy is set to
133 * ELM_GLVIEW_RESIZE_POLICY_SCALE, however, glview only scales the image
134 * object and not the underlying GL Surface.
135 *
136 * @ingroup GLView
137 */
138EAPI Eina_Bool elm_glview_resize_policy_set(Evas_Object *obj, Elm_GLView_Resize_Policy policy);
139
140/**
141 * Set the render policy for the glview object.
142 *
143 * @param obj The glview object.
144 * @param policy The render policy.
145 *
146 * By default, the render policy is set to ELM_GLVIEW_RENDER_POLICY_ON_DEMAND.
147 * This policy is set such that during the render loop, glview is only
148 * redrawn if it needs to be redrawn. (i.e. when it is visible) If the policy
149 * is set to ELM_GLVIEWW_RENDER_POLICY_ALWAYS, it redraws regardless of
150 * whether it is visible or needs redrawing.
151 *
152 * @ingroup GLView
153 */
154EAPI Eina_Bool elm_glview_render_policy_set(Evas_Object *obj, Elm_GLView_Render_Policy policy);
155
156/**
157 * Set the init function that runs once in the main loop.
158 *
159 * @param obj The glview object.
160 * @param func The init function to be registered.
161 *
162 * The registered init function gets called once during the render loop.
163 * This function allows glview to hide all the rendering context/surface
164 * details and have the user just call GL calls that they desire
165 * for initialization GL calls.
166 *
167 * @ingroup GLView
168 */
169EAPI void elm_glview_init_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
170
171/**
172 * Set the render function that runs in the main loop.
173 *
174 * @param obj The glview object.
175 * @param func The delete function to be registered.
176 *
177 * The registered del function gets called when GLView object is deleted.
178 * This function allows glview to hide all the rendering context/surface
179 * details and have the user just call GL calls that they desire
180 * when delete happens.
181 *
182 * @ingroup GLView
183 */
184EAPI void elm_glview_del_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
185
186/**
187 * Set the resize function that gets called when resize happens.
188 *
189 * @param obj The glview object.
190 * @param func The resize function to be registered.
191 *
192 * The resize function gets called during the render loop.
193 * This function allows glview to hide all the rendering context/surface
194 * details and have the user just call GL calls that they desire
195 * when resize happens.
196 *
197 * @ingroup GLView
198 */
199EAPI void elm_glview_resize_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
200
201/**
202 * Set the render function that runs in the main loop.
203 *
204 * The render function gets called in the main loop but whether it runs
205 * depends on the rendering policy and whether elm_glview_changed_set()
206 * gets called.
207 *
208 * @param obj The glview object.
209 * @param func The render function to be registered.
210 *
211 * @ingroup GLView
212 */
213EAPI void elm_glview_render_func_set(Evas_Object *obj, Elm_GLView_Func_Cb func);
214
215/**
216 * Notifies that there has been changes in the GLView.
217 *
218 * @param obj The glview object.
219 *
220 * @ingroup GLView
221 */
222EAPI void elm_glview_changed_set(Evas_Object *obj);
223
224/**
225 * @}
226 */
diff --git a/libraries/elementary/src/lib/elm_grid.c b/libraries/elementary/src/lib/elm_grid.c
new file mode 100644
index 0000000..22f1b23
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_grid.c
@@ -0,0 +1,177 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *obj, *grd;
9};
10
11static const char *widtype = NULL;
12static void _del_hook(Evas_Object *obj);
13static void _theme_hook(Evas_Object *obj);
14
15static void
16_del_hook(Evas_Object *obj)
17{
18 Widget_Data *wd = elm_widget_data_get(obj);
19 if (!wd) return;
20 free(wd);
21}
22
23static Eina_Bool
24_elm_grid_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
25{
26 Widget_Data *wd = elm_widget_data_get(obj);
27 const Eina_List *items;
28 void *(*list_data_get) (const Eina_List *list);
29 Eina_List *(*list_free) (Eina_List *list);
30
31 if ((!wd) || (!wd->grd))
32 return EINA_FALSE;
33
34 /* Focus chain */
35 /* TODO: Change this to use other chain */
36 if ((items = elm_widget_focus_custom_chain_get(obj)))
37 {
38 list_data_get = eina_list_data_get;
39 list_free = NULL;
40 }
41 else
42 {
43 items = evas_object_grid_children_get(wd->grd);
44 list_data_get = eina_list_data_get;
45 list_free = eina_list_free;
46
47 if (!items) return EINA_FALSE;
48 }
49
50 Eina_Bool ret = elm_widget_focus_list_next_get(obj, items, list_data_get,
51 dir, next);
52
53 if (list_free)
54 list_free((Eina_List *)items);
55
56 return ret;
57}
58
59static void
60_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
61{
62 Widget_Data *wd = elm_widget_data_get(obj);
63 if ((!wd) || (!wd->grd)) return;
64 evas_object_grid_mirrored_set(wd->grd, rtl);
65}
66
67static void
68_theme_hook(Evas_Object *obj)
69{
70 _elm_widget_mirrored_reload(obj);
71 _mirrored_set(obj, elm_widget_mirrored_get(obj));
72}
73
74EAPI Evas_Object *
75elm_grid_add(Evas_Object *parent)
76{
77 Evas_Object *obj;
78 Evas *e;
79 Widget_Data *wd;
80
81 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
82 ELM_SET_WIDTYPE(widtype, "grid");
83 elm_widget_type_set(obj, "grid");
84 elm_widget_sub_object_add(parent, obj);
85 elm_widget_data_set(obj, wd);
86 elm_widget_del_hook_set(obj, _del_hook);
87 elm_widget_focus_next_hook_set(obj, _elm_grid_focus_next_hook);
88 elm_widget_can_focus_set(obj, EINA_FALSE);
89 elm_widget_theme_hook_set(obj, _theme_hook);
90
91 wd->grd = evas_object_grid_add(e);
92 evas_object_grid_size_set(wd->grd, 100, 100);
93 elm_widget_resize_object_set(obj, wd->grd);
94
95 _mirrored_set(obj, elm_widget_mirrored_get(obj));
96 return obj;
97}
98
99EAPI void
100elm_grid_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
101{
102 ELM_CHECK_WIDTYPE(obj, widtype);
103 Widget_Data *wd = elm_widget_data_get(obj);
104 if (!wd) return;
105 evas_object_grid_size_set(wd->grd, w, h);
106}
107
108EAPI void
109elm_grid_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
110{
111 ELM_CHECK_WIDTYPE(obj, widtype);
112 Widget_Data *wd = elm_widget_data_get(obj);
113 if (!wd) return;
114 evas_object_grid_size_get(wd->grd, w, h);
115}
116
117EAPI void
118elm_grid_pack(Evas_Object *obj, Evas_Object *subobj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
119{
120 ELM_CHECK_WIDTYPE(obj, widtype);
121 Widget_Data *wd = elm_widget_data_get(obj);
122 if (!wd) return;
123 elm_widget_sub_object_add(obj, subobj);
124 evas_object_grid_pack(wd->grd, subobj, x, y, w, h);
125}
126
127EAPI void
128elm_grid_unpack(Evas_Object *obj, Evas_Object *subobj)
129{
130 ELM_CHECK_WIDTYPE(obj, widtype);
131 Widget_Data *wd = elm_widget_data_get(obj);
132 if (!wd) return;
133 elm_widget_sub_object_del(obj, subobj);
134 evas_object_grid_unpack(wd->grd, subobj);
135}
136
137EAPI void
138elm_grid_clear(Evas_Object *obj, Eina_Bool clear)
139{
140 Eina_List *chld;
141 Evas_Object *o;
142 ELM_CHECK_WIDTYPE(obj, widtype);
143 Widget_Data *wd = elm_widget_data_get(obj);
144 if (!wd) return;
145 chld = evas_object_grid_children_get(wd->grd);
146 EINA_LIST_FREE(chld, o) elm_widget_sub_object_del(obj, o);
147 evas_object_grid_clear(wd->grd, clear);
148}
149
150EAPI void
151elm_grid_pack_set(Evas_Object *subobj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
152{
153 Evas_Object *obj = elm_widget_parent_widget_get(subobj);
154 ELM_CHECK_WIDTYPE(obj, widtype);
155 Widget_Data *wd = elm_widget_data_get(obj);
156 if (!wd) return;
157 evas_object_grid_pack(wd->grd, subobj, x, y, w, h);
158}
159
160EAPI void
161elm_grid_pack_get(Evas_Object *subobj, int *x, int *y, int *w, int *h)
162{
163 Evas_Object *obj = elm_widget_parent_widget_get(subobj);
164 ELM_CHECK_WIDTYPE(obj, widtype);
165 Widget_Data *wd = elm_widget_data_get(obj);
166 if (!wd) return;
167 evas_object_grid_pack_get(wd->grd, subobj, x, y, w, h);
168}
169
170EAPI Eina_List *
171elm_grid_children_get(const Evas_Object *obj)
172{
173 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
174 Widget_Data *wd = elm_widget_data_get(obj);
175 if (!wd) return NULL;
176 return evas_object_grid_children_get(wd->grd);
177}
diff --git a/libraries/elementary/src/lib/elm_grid.h b/libraries/elementary/src/lib/elm_grid.h
new file mode 100644
index 0000000..8168023
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_grid.h
@@ -0,0 +1,125 @@
1/**
2 * @defgroup Grid Grid
3 * @ingroup Elementary
4 *
5 * The grid is a grid layout widget that lays out a series of children as a
6 * fixed "grid" of widgets using a given percentage of the grid width and
7 * height each using the child object.
8 *
9 * The Grid uses a "Virtual resolution" that is stretched to fill the grid
10 * widgets size itself. The default is 100 x 100, so that means the
11 * position and sizes of children will effectively be percentages (0 to 100)
12 * of the width or height of the grid widget
13 *
14 * @{
15 */
16
17/**
18 * Add a new grid to the parent
19 *
20 * @param parent The parent object
21 * @return The new object or NULL if it cannot be created
22 *
23 * @ingroup Grid
24 */
25EAPI Evas_Object *elm_grid_add(Evas_Object *parent);
26
27/**
28 * Set the virtual size of the grid
29 *
30 * @param obj The grid object
31 * @param w The virtual width of the grid
32 * @param h The virtual height of the grid
33 *
34 * @ingroup Grid
35 */
36EAPI void elm_grid_size_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
37
38/**
39 * Get the virtual size of the grid
40 *
41 * @param obj The grid object
42 * @param w Pointer to integer to store the virtual width of the grid
43 * @param h Pointer to integer to store the virtual height of the grid
44 *
45 * @ingroup Grid
46 */
47EAPI void elm_grid_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
48
49/**
50 * Pack child at given position and size
51 *
52 * @param obj The grid object
53 * @param subobj The child to pack
54 * @param x The virtual x coord at which to pack it
55 * @param y The virtual y coord at which to pack it
56 * @param w The virtual width at which to pack it
57 * @param h The virtual height at which to pack it
58 *
59 * @ingroup Grid
60 */
61EAPI void elm_grid_pack(Evas_Object *obj, Evas_Object *subobj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
62
63/**
64 * Unpack a child from a grid object
65 *
66 * @param obj The grid object
67 * @param subobj The child to unpack
68 *
69 * @ingroup Grid
70 */
71EAPI void elm_grid_unpack(Evas_Object *obj, Evas_Object *subobj);
72
73/**
74 * Faster way to remove all child objects from a grid object.
75 *
76 * @param obj The grid object
77 * @param clear If true, it will delete just removed children
78 *
79 * @ingroup Grid
80 */
81EAPI void elm_grid_clear(Evas_Object *obj, Eina_Bool clear);
82
83/**
84 * Set packing of an existing child at to position and size
85 *
86 * @param subobj The child to set packing of
87 * @param x The virtual x coord at which to pack it
88 * @param y The virtual y coord at which to pack it
89 * @param w The virtual width at which to pack it
90 * @param h The virtual height at which to pack it
91 *
92 * @ingroup Grid
93 */
94EAPI void elm_grid_pack_set(Evas_Object *subobj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
95
96/**
97 * Get packing of a child
98 *
99 * @param subobj The child to query
100 * @param x Pointer to integer to store the virtual x coord
101 * @param y Pointer to integer to store the virtual y coord
102 * @param w Pointer to integer to store the virtual width
103 * @param h Pointer to integer to store the virtual height
104 *
105 * @ingroup Grid
106 */
107EAPI void elm_grid_pack_get(Evas_Object *subobj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
108
109/**
110 * Get the list of the children for the grid.
111 *
112 * @param obj The grid object
113 *
114 * @note This is a duplicate of the list kept by the grid internally.
115 It's up to the user to destroy it when it no longer needs it.
116 It's possible to remove objects from the grid when walking this
117 list, but these removals won't be reflected on it.
118 *
119 * @ingroup Grid
120 */
121EAPI Eina_List *elm_grid_children_get(const Evas_Object *obj);
122
123/**
124 * @}
125 */
diff --git a/libraries/elementary/src/lib/elm_hover.c b/libraries/elementary/src/lib/elm_hover.c
new file mode 100644
index 0000000..ec92a9c
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_hover.c
@@ -0,0 +1,852 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Content_Info Content_Info;
6
7#ifndef MAX
8# define MAX(a, b) (((a) > (b)) ? (a) : (b))
9#endif
10
11#define ELM_HOVER_PARTS_FOREACH unsigned int i = 0; \
12 for (i = 0; i < sizeof(wd->subs) / sizeof(wd->subs[0]); i++)
13
14static const char *_directions[] = {
15 "left",
16 "top-left",
17 "top",
18 "top-right",
19 "right",
20 "bottom-right",
21 "bottom",
22 "bottom-left",
23 "middle"
24};
25
26#define _HOV_LEFT (_directions[0])
27#define _HOV_TOP_LEFT (_directions[1])
28#define _HOV_TOP (_directions[2])
29#define _HOV_TOP_RIGHT (_directions[2])
30#define _HOV_RIGHT (_directions[4])
31#define _HOV_BOTTOM_RIGHT (_directions[5])
32#define _HOV_BOTTOM (_directions[6])
33#define _HOV_BOTTOM_LEFT (_directions[7])
34#define _HOV_MIDDLE (_directions[8])
35
36struct _Content_Info
37{
38 const char *swallow;
39 Evas_Object *obj;
40};
41
42struct _Widget_Data
43{
44 Evas_Object *hov, *cov;
45 Evas_Object *offset, *size;
46 Evas_Object *parent, *target;
47 Evas_Object *smt_sub;
48 Content_Info subs[sizeof(_directions)/sizeof(_directions[0])];
49};
50
51static const char *widtype = NULL;
52static void _del_pre_hook(Evas_Object *obj);
53static void _del_hook(Evas_Object *obj);
54static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
55static void _theme_hook(Evas_Object *obj);
56static void _sizing_eval(Evas_Object *obj);
57static void _reval_content(Evas_Object *obj);
58static void _sub_del(void *data, Evas_Object *obj, void *event_info);
59static void _hov_show_do(Evas_Object *obj);
60static void _hov_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
61static void _hov_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
62static void _hov_show(void *data, Evas *e, Evas_Object *obj, void *event_info);
63static void _hov_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
64static void _on_focus_hook(void *data, Evas_Object *obj);
65static void _elm_hover_sub_obj_placement_eval_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
66static void _elm_hover_sub_obj_placement_eval(Evas_Object *obj);
67static void _content_set_hook(Evas_Object *obj, const char *swallow, Evas_Object *content);
68static Evas_Object * _content_get_hook(const Evas_Object *obj, const char *swallow);
69static Evas_Object * _content_unset_hook(Evas_Object *obj, const char *swallow);
70
71static const char SIG_CLICKED[] = "clicked";
72static const char SIG_SMART_LOCATION_CHANGED[] = "smart,changed";
73static const Evas_Smart_Cb_Description _signals[] = {
74 {SIG_CLICKED, ""},
75 {SIG_SMART_LOCATION_CHANGED, ""},
76 {NULL, NULL}
77};
78
79static void
80_del_pre_hook(Evas_Object *obj)
81{
82 Widget_Data *wd = elm_widget_data_get(obj);
83 if (!wd)
84 return;
85
86 if (evas_object_visible_get(obj))
87 evas_object_smart_callback_call(obj, SIG_CLICKED, NULL);
88 elm_hover_target_set(obj, NULL);
89 elm_hover_parent_set(obj, NULL);
90 evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_MOVE, _hov_move, obj);
91 evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_RESIZE, _hov_resize, obj);
92 evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_SHOW, _hov_show, obj);
93 evas_object_event_callback_del_full(wd->hov, EVAS_CALLBACK_HIDE, _hov_hide, obj);
94}
95
96static void
97_del_hook(Evas_Object *obj)
98{
99 Widget_Data *wd = elm_widget_data_get(obj);
100 if (!wd) return;
101 free(wd);
102}
103
104static void
105_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
106{
107 Widget_Data *wd = elm_widget_data_get(obj);
108 if (!wd) return;
109 if (elm_widget_focus_get(obj))
110 {
111 edje_object_signal_emit(wd->cov, "elm,action,focus", "elm");
112 evas_object_focus_set(wd->cov, EINA_TRUE);
113 }
114 else
115 {
116 edje_object_signal_emit(wd->cov, "elm,action,unfocus", "elm");
117 evas_object_focus_set(wd->cov, EINA_FALSE);
118 }
119}
120
121static void
122_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
123{
124 Widget_Data *wd = elm_widget_data_get(obj);
125 if (!wd) return;
126 edje_object_mirrored_set(wd->cov, rtl);
127}
128
129static void
130_theme_hook(Evas_Object *obj)
131{
132 Widget_Data *wd = elm_widget_data_get(obj);
133 if (!wd) return;
134 _elm_widget_mirrored_reload(obj);
135 _mirrored_set(obj, elm_widget_mirrored_get(obj));
136 // FIXME: hover contents doesn't seem to propagate resizes properly
137 _elm_theme_object_set(obj, wd->cov, "hover", "base", elm_widget_style_get(obj));
138 edje_object_scale_set(wd->cov, elm_widget_scale_get(obj) *
139 _elm_config->scale);
140
141 if (wd->smt_sub)
142 _elm_hover_sub_obj_placement_eval(obj);
143 else
144 _reval_content(obj);
145 _sizing_eval(obj);
146 if (evas_object_visible_get(wd->cov)) _hov_show_do(obj);
147}
148
149static void
150_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
151{
152 Widget_Data *wd;
153
154 wd = elm_widget_data_get(obj);
155 if (!wd)
156 return;
157
158 edje_object_signal_emit(wd->cov, emission, source);
159}
160
161static void
162_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
163{
164 Widget_Data *wd;
165
166 wd = elm_widget_data_get(obj);
167 if (!wd)
168 return;
169
170 edje_object_signal_callback_add(wd->hov, emission, source, func_cb, data);
171}
172
173static void
174_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
175{
176 Widget_Data *wd;
177
178 wd = elm_widget_data_get(obj);
179
180 edje_object_signal_callback_del_full(wd->hov, emission, source, func_cb,
181 data);
182}
183
184static void
185_elm_hover_left_space_calc(Widget_Data *wd, Evas_Coord *spc_l, Evas_Coord *spc_t, Evas_Coord *spc_r, Evas_Coord *spc_b)
186{
187 Evas_Coord x = 0, y = 0, w = 0, h = 0, x2 = 0, y2 = 0, w2 = 0, h2 = 0;
188
189 if (wd->parent)
190 evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
191 if (wd->target)
192 evas_object_geometry_get(wd->target, &x2, &y2, &w2, &h2);
193
194 *spc_l = x2 - x;
195 *spc_r = (x + w) - (x2 + w2);
196 if (*spc_l < 0)
197 *spc_l = 0;
198 if (*spc_r < 0)
199 *spc_r = 0;
200
201 *spc_t = y2 - y;
202 *spc_b = (y + h) - (y2 + h2);
203 if (*spc_t < 0)
204 *spc_t = 0;
205 if (*spc_b < 0)
206 *spc_b = 0;
207}
208
209static void
210_sizing_eval(Evas_Object *obj)
211{
212 Widget_Data *wd = elm_widget_data_get(obj);
213 Evas_Coord ofs_x, x = 0, y = 0, w = 0, h = 0, x2 = 0, y2 = 0, w2 = 0, h2 = 0;
214 if (!wd) return;
215 if (wd->parent) evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
216 if (wd->hov) evas_object_geometry_get(wd->hov, &x2, &y2, &w2, &h2);
217
218 if (elm_widget_mirrored_get(obj))
219 ofs_x = w - (x2 - x) - w2;
220 else
221 ofs_x = x2 - x;
222
223 evas_object_move(wd->cov, x, y);
224 evas_object_resize(wd->cov, w, h);
225 evas_object_size_hint_min_set(wd->offset, ofs_x, y2 - y);
226 evas_object_size_hint_min_set(wd->size, w2, h2);
227 edje_object_part_swallow(wd->cov, "elm.swallow.offset", wd->offset);
228 edje_object_part_swallow(wd->cov, "elm.swallow.size", wd->size);
229}
230
231static void
232_reval_content(Evas_Object *obj)
233{
234 Widget_Data *wd = elm_widget_data_get(obj);
235 if (!wd)
236 return;
237
238 ELM_HOVER_PARTS_FOREACH
239 {
240 char buf[1024];
241 snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", wd->subs[i].swallow);
242 edje_object_part_swallow(wd->cov, buf, wd->subs[i].obj);
243 }
244}
245
246static const char *
247_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)
248{
249 Evas_Coord c_w = 0, c_h = 0, mid_w, mid_h;
250 int max;
251
252 evas_object_size_hint_min_get(wd->smt_sub, &c_w, &c_h);
253 mid_w = c_w / 2;
254 mid_h = c_h / 2;
255
256 if (spc_l > spc_r)
257 goto left;
258
259 max = MAX(spc_t, spc_r);
260 max = MAX(max, spc_b);
261
262 if (max == spc_t)
263 {
264 if (mid_w > spc_l)
265 return _HOV_TOP_RIGHT;
266
267 return _HOV_TOP;
268 }
269
270 if (max == spc_r)
271 {
272 if (mid_h > spc_t)
273 return _HOV_BOTTOM_RIGHT;
274 else if (mid_h > spc_b)
275 return _HOV_TOP_RIGHT;
276
277 return _HOV_RIGHT;
278 }
279
280 if (mid_h > spc_l)
281 return _HOV_BOTTOM_RIGHT;
282
283 return _HOV_BOTTOM;
284
285left:
286 max = MAX(spc_t, spc_l);
287 max = MAX(max, spc_b);
288
289 if (max == spc_t)
290 {
291 if (mid_w > spc_r)
292 return _HOV_TOP_LEFT;
293
294 return _HOV_TOP;
295 }
296
297 if (max == spc_l)
298 {
299 if (mid_h > spc_t)
300 return _HOV_BOTTOM_LEFT;
301 else if (mid_h > spc_b)
302 return _HOV_TOP_LEFT;
303
304 return _HOV_LEFT;
305 }
306
307 if (mid_h > spc_r)
308 return _HOV_BOTTOM_LEFT;
309
310 return _HOV_BOTTOM;
311}
312
313static void
314_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
315{
316 Widget_Data *wd;
317 Evas_Object *sub;
318
319 sub = event_info;
320 wd = elm_widget_data_get(obj);
321 if (!wd)
322 return;
323
324 if (wd->smt_sub)
325 {
326 if (wd->smt_sub == sub)
327 wd->smt_sub = NULL;
328 }
329 else
330 {
331 ELM_HOVER_PARTS_FOREACH
332 {
333 if (wd->subs[i].obj == sub)
334 {
335 wd->subs[i].obj = NULL;
336 break;
337 }
338 }
339 }
340}
341
342static void
343_hov_show_do(Evas_Object *obj)
344{
345 Widget_Data *wd = elm_widget_data_get(obj);
346 if (!wd)
347 return;
348
349 if (wd->cov)
350 {
351 evas_object_show(wd->cov);
352 edje_object_signal_emit(wd->cov, "elm,action,show", "elm");
353 }
354
355 ELM_HOVER_PARTS_FOREACH
356 {
357 char buf[1024];
358
359 if (wd->subs[i].obj)
360 {
361 snprintf(buf, sizeof(buf), "elm,action,slot,%s,show",
362 wd->subs[i].swallow);
363 edje_object_signal_emit(wd->cov, buf, "elm");
364 }
365 }
366}
367
368static void
369_hov_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
370{
371 _sizing_eval(data);
372}
373
374static void
375_hov_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
376{
377 _sizing_eval(data);
378}
379
380static void
381_hov_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
382{
383 _hov_show_do(data);
384}
385
386static void
387_hov_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
388{
389 Widget_Data *wd = elm_widget_data_get(data);
390 if (!wd) return;
391 if (wd->cov)
392 {
393 edje_object_signal_emit(wd->cov, "elm,action,hide", "elm");
394 evas_object_hide(wd->cov);
395 }
396
397 ELM_HOVER_PARTS_FOREACH
398 {
399 char buf[1024];
400
401 if (wd->subs[i].obj)
402 {
403 snprintf(buf, sizeof(buf), "elm,action,slot,%s,hide",
404 wd->subs[i].swallow);
405 edje_object_signal_emit(wd->cov, buf, "elm");
406 }
407 }
408}
409
410static void
411_target_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
412{
413 Widget_Data *wd = elm_widget_data_get(data);
414 if (!wd) return;
415 wd->target = NULL;
416}
417
418static void
419_target_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
420{
421 Widget_Data *wd = elm_widget_data_get(data);
422 if (!wd)
423 return;
424
425 _sizing_eval(data);
426 _elm_hover_sub_obj_placement_eval(data);
427}
428
429static void
430_signal_dismiss(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
431{
432 Widget_Data *wd = elm_widget_data_get(data);
433 if (!wd) return;
434 evas_object_hide(data);
435 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
436}
437
438static void
439_parent_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
440{
441 _sizing_eval(data);
442}
443
444static void
445_parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
446{
447 _sizing_eval(data);
448}
449
450static void
451_parent_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
452{
453}
454
455static void
456_parent_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
457{
458 Widget_Data *wd = elm_widget_data_get(data);
459 if (!wd) return;
460 evas_object_hide(wd->cov);
461}
462
463static void
464_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
465{
466 Widget_Data *wd = elm_widget_data_get(data);
467 if (!wd) return;
468 elm_hover_parent_set(data, NULL);
469 _sizing_eval(data);
470}
471
472EAPI Evas_Object *
473elm_hover_add(Evas_Object *parent)
474{
475 Evas_Object *obj;
476 Evas *e;
477 Widget_Data *wd;
478
479 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
480
481 ELM_SET_WIDTYPE(widtype, "hover");
482 elm_widget_type_set(obj, "hover");
483 elm_widget_sub_object_add(parent, obj);
484 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
485 elm_widget_data_set(obj, wd);
486 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
487 elm_widget_theme_hook_set(obj, _theme_hook);
488 elm_widget_del_hook_set(obj, _del_hook);
489 elm_widget_can_focus_set(obj, EINA_TRUE);
490 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
491 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
492 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
493 elm_widget_content_set_hook_set(obj, _content_set_hook);
494 elm_widget_content_get_hook_set(obj, _content_get_hook);
495 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
496
497 ELM_HOVER_PARTS_FOREACH
498 wd->subs[i].swallow = _directions[i];
499
500 wd->hov = evas_object_rectangle_add(e);
501 evas_object_pass_events_set(wd->hov, EINA_TRUE);
502 evas_object_color_set(wd->hov, 0, 0, 0, 0);
503 elm_widget_resize_object_set(obj, wd->hov);
504 evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_MOVE, _hov_move, obj);
505 evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_RESIZE, _hov_resize, obj);
506 evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_SHOW, _hov_show, obj);
507 evas_object_event_callback_add(wd->hov, EVAS_CALLBACK_HIDE, _hov_hide, obj);
508
509 wd->cov = edje_object_add(e);
510 _elm_theme_object_set(obj, wd->cov, "hover", "base", "default");
511 elm_widget_sub_object_add(obj, wd->cov);
512 edje_object_signal_callback_add(wd->cov, "elm,action,dismiss", "",
513 _signal_dismiss, obj);
514
515 wd->offset = evas_object_rectangle_add(e);
516 evas_object_pass_events_set(wd->offset, EINA_TRUE);
517 evas_object_color_set(wd->offset, 0, 0, 0, 0);
518 elm_widget_sub_object_add(obj, wd->offset);
519
520 wd->size = evas_object_rectangle_add(e);
521 evas_object_pass_events_set(wd->size, EINA_TRUE);
522 evas_object_color_set(wd->size, 0, 0, 0, 0);
523 elm_widget_sub_object_add(obj, wd->size);
524
525 edje_object_part_swallow(wd->cov, "elm.swallow.offset", wd->offset);
526 edje_object_part_swallow(wd->cov, "elm.swallow.size", wd->size);
527
528 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
529
530 elm_hover_parent_set(obj, parent);
531 evas_object_smart_callbacks_descriptions_set(obj, _signals);
532
533 _mirrored_set(obj, elm_widget_mirrored_get(obj));
534 _sizing_eval(obj);
535 return obj;
536}
537
538EAPI void
539elm_hover_target_set(Evas_Object *obj, Evas_Object *target)
540{
541 ELM_CHECK_WIDTYPE(obj, widtype);
542 Widget_Data *wd = elm_widget_data_get(obj);
543
544 if (wd->target)
545 {
546 evas_object_event_callback_del_full(wd->target, EVAS_CALLBACK_DEL,
547 _target_del, obj);
548 evas_object_event_callback_del_full(wd->target, EVAS_CALLBACK_MOVE,
549 _target_move, obj);
550 }
551 wd->target = target;
552 if (wd->target)
553 {
554 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_DEL,
555 _target_del, obj);
556 evas_object_event_callback_add(wd->target, EVAS_CALLBACK_MOVE,
557 _target_move, obj);
558 elm_widget_hover_object_set(target, obj);
559 _sizing_eval(obj);
560 }
561}
562
563
564EAPI void
565elm_hover_parent_set(Evas_Object *obj, Evas_Object *parent)
566{
567 ELM_CHECK_WIDTYPE(obj, widtype);
568 Widget_Data *wd = elm_widget_data_get(obj);
569 if (!wd) return;
570 if (wd->parent)
571 {
572 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
573 _parent_move, obj);
574 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
575 _parent_resize, obj);
576 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_SHOW,
577 _parent_show, obj);
578 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
579 _parent_hide, obj);
580 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
581 _parent_del, obj);
582 }
583 wd->parent = parent;
584 if (wd->parent)
585 {
586 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_MOVE,
587 _parent_move, obj);
588 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE,
589 _parent_resize, obj);
590 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_SHOW,
591 _parent_show, obj);
592 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_HIDE,
593 _parent_hide, obj);
594 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL,
595 _parent_del, obj);
596 // elm_widget_sub_object_add(parent, obj);
597 }
598 _sizing_eval(obj);
599}
600
601EAPI Evas_Object *
602elm_hover_target_get(const Evas_Object *obj)
603{
604 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
605 Widget_Data *wd = elm_widget_data_get(obj);
606 if (!wd) return NULL;
607
608 return wd->target;
609}
610
611EAPI Evas_Object *
612elm_hover_parent_get(const Evas_Object *obj)
613{
614 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
615 Widget_Data *wd = elm_widget_data_get(obj);
616 if (!wd) return NULL;
617
618 return wd->parent;
619}
620
621static void
622_elm_hover_subs_del(Widget_Data *wd)
623{
624 ELM_HOVER_PARTS_FOREACH
625 {
626 if (wd->subs[i].obj)
627 {
628 evas_object_del(wd->subs[i].obj);
629 wd->subs[i].obj = NULL;
630 }
631 }
632}
633
634static void
635_elm_hover_sub_obj_placement_eval(Evas_Object *obj)
636{
637 Evas_Coord spc_l, spc_r, spc_t, spc_b;
638 const char *smart_dir;
639 Widget_Data *wd;
640 char buf[1024];
641
642 wd = elm_widget_data_get(obj);
643 if (!wd->smt_sub)
644 return;
645
646 _elm_hover_left_space_calc(wd, &spc_l, &spc_t, &spc_r, &spc_b);
647
648 edje_object_part_unswallow(wd->cov, wd->smt_sub);
649
650 smart_dir = _elm_hover_smart_content_location_get(wd, spc_l, spc_t, spc_r,
651 spc_b);
652 evas_object_smart_callback_call(obj, SIG_SMART_LOCATION_CHANGED,
653 (void *)smart_dir);
654
655 if (elm_widget_mirrored_get(obj))
656 {
657 if (smart_dir == _HOV_BOTTOM_LEFT)
658 smart_dir = _HOV_BOTTOM_RIGHT;
659 else if (smart_dir == _HOV_BOTTOM_RIGHT)
660 smart_dir = _HOV_BOTTOM_LEFT;
661 else if (smart_dir == _HOV_RIGHT)
662 smart_dir = _HOV_LEFT;
663 else if (smart_dir == _HOV_LEFT)
664 smart_dir = _HOV_RIGHT;
665 else if (smart_dir == _HOV_TOP_RIGHT)
666 smart_dir = _HOV_TOP_LEFT;
667 else if (smart_dir == _HOV_TOP_LEFT)
668 smart_dir = _HOV_TOP_RIGHT;
669 }
670 snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", smart_dir);
671 edje_object_part_swallow(wd->cov, buf, wd->smt_sub);
672}
673
674static void
675_elm_hover_sub_obj_placement_eval_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
676{
677 _elm_hover_sub_obj_placement_eval(data);
678}
679
680static void
681_elm_hover_sub_obj_unparent(Evas_Object *obj)
682{
683 Widget_Data *wd;
684 Evas_Object *smt_sub;
685
686 wd = elm_widget_data_get(obj);
687 if (!wd) return;
688
689 smt_sub = wd->smt_sub;
690 elm_widget_sub_object_del(obj, wd->smt_sub);
691 evas_object_event_callback_del_full(smt_sub,
692 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
693 _elm_hover_sub_obj_placement_eval_cb,
694 obj);
695 edje_object_part_unswallow(wd->cov, smt_sub);
696}
697
698EAPI const char *
699elm_hover_best_content_location_get(const Evas_Object *obj, Elm_Hover_Axis pref_axis)
700{
701 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
702
703 Evas_Coord spc_l, spc_r, spc_t, spc_b;
704 Widget_Data *wd;
705
706 wd = elm_widget_data_get(obj);
707 if (!wd)
708 return NULL;
709
710 _elm_hover_left_space_calc(wd, &spc_l, &spc_t, &spc_r, &spc_b);
711
712 if (pref_axis == ELM_HOVER_AXIS_HORIZONTAL)
713 {
714 if (spc_l < spc_r) return _HOV_RIGHT;
715 else return _HOV_LEFT;
716 }
717 else if (pref_axis == ELM_HOVER_AXIS_VERTICAL)
718 {
719 if (spc_t < spc_b) return _HOV_BOTTOM;
720 else return _HOV_TOP;
721 }
722
723 if (spc_l < spc_r)
724 {
725 if (spc_t > spc_r) return _HOV_TOP;
726 else if (spc_b > spc_r) return _HOV_BOTTOM;
727 return _HOV_RIGHT;
728 }
729 if (spc_t > spc_r) return _HOV_TOP;
730 else if (spc_b > spc_r) return _HOV_BOTTOM;
731 return _HOV_LEFT;
732}
733
734EAPI void
735elm_hover_dismiss(Evas_Object *obj)
736{
737 Widget_Data *wd;
738 ELM_CHECK_WIDTYPE(obj, widtype);
739 wd = elm_widget_data_get(obj);
740 if (!wd) return;
741
742 edje_object_signal_emit(wd->cov, "elm,action,dismiss", "");
743}
744
745static void
746_content_set_hook(Evas_Object *obj, const char *swallow, Evas_Object *content)
747{
748 ELM_CHECK_WIDTYPE(obj, widtype);
749 Widget_Data *wd = elm_widget_data_get(obj);
750 if (!wd) return;
751
752 if (!strcmp(swallow, "smart"))
753 {
754 if (wd->smt_sub != content)
755 {
756 _elm_hover_subs_del(wd);
757 wd->smt_sub = content;
758 }
759
760 if (content)
761 {
762 elm_widget_sub_object_add(obj, content);
763 evas_object_event_callback_add(wd->smt_sub,
764 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
765 _elm_hover_sub_obj_placement_eval_cb,
766 obj);
767
768 _elm_hover_sub_obj_placement_eval(obj);
769 }
770
771 goto end;
772 }
773
774 if (wd->smt_sub)
775 {
776 evas_object_del(wd->smt_sub);
777 wd->smt_sub = NULL;
778 }
779
780 ELM_HOVER_PARTS_FOREACH
781 {
782 if (!strcmp(swallow, wd->subs[i].swallow))
783 {
784 if (content == wd->subs[i].obj)
785 return;
786 evas_object_del(wd->subs[i].obj);
787 wd->subs[i].obj = NULL;
788
789 if (content)
790 {
791 char buf[1024];
792
793 snprintf(buf, sizeof(buf), "elm.swallow.slot.%s", swallow);
794 elm_widget_sub_object_add(obj, content);
795 edje_object_part_swallow(wd->cov, buf, content);
796 wd->subs[i].obj = content;
797 }
798 break;
799 }
800 }
801end:
802 _sizing_eval(obj);
803}
804
805static Evas_Object *
806_content_get_hook(const Evas_Object *obj, const char *swallow)
807{
808 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
809
810 Widget_Data *wd = elm_widget_data_get(obj);
811 if (!wd) return NULL;
812
813 if (!strcmp(swallow, "smart"))
814 return wd->smt_sub;
815
816 ELM_HOVER_PARTS_FOREACH
817 if (!strcmp(swallow, wd->subs[i].swallow))
818 return wd->subs[i].obj;
819
820 return NULL;
821}
822
823static Evas_Object *
824_content_unset_hook(Evas_Object *obj, const char *swallow)
825{
826 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
827
828 Widget_Data *wd = elm_widget_data_get(obj);
829 if (!wd) return NULL;
830
831 if (!strcmp(swallow, "smart"))
832 {
833 if (!wd->smt_sub) return NULL;
834 Evas_Object *content = wd->smt_sub;
835 _elm_hover_sub_obj_unparent(obj);
836 return content;
837 }
838
839 ELM_HOVER_PARTS_FOREACH
840 {
841 if (!strcmp(swallow, wd->subs[i].swallow))
842 {
843 if (!wd->subs[i].obj) return NULL;
844 Evas_Object *content = wd->subs[i].obj;
845 elm_widget_sub_object_del(obj, wd->subs[i].obj);
846 edje_object_part_unswallow(wd->cov, content);
847 return content;
848 }
849 }
850
851 return NULL;
852}
diff --git a/libraries/elementary/src/lib/elm_hover.h b/libraries/elementary/src/lib/elm_hover.h
new file mode 100644
index 0000000..1413098
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_hover.h
@@ -0,0 +1,199 @@
1/**
2 * @defgroup Hover Hover
3 * @ingroup Elementary
4 *
5 * @image html img/widget/hover/preview-00.png
6 * @image latex img/widget/hover/preview-00.eps
7 *
8 * A Hover object will hover over its @p parent object at the @p target
9 * location. Anything in the background will be given a darker coloring to
10 * indicate that the hover object is on top (at the default theme). When the
11 * hover is clicked it is dismissed(hidden), if the contents of the hover are
12 * clicked that @b doesn't cause the hover to be dismissed.
13 *
14 * A Hover object has two parents. One parent that owns it during creation
15 * and the other parent being the one over which the hover object spans.
16 *
17 *
18 * @note The hover object will take up the entire space of @p target
19 * object.
20 *
21 * Elementary has the following styles for the hover widget:
22 * @li default
23 * @li popout
24 * @li menu
25 * @li hoversel_vertical
26 *
27 * The following are the available position for content:
28 * @li left
29 * @li top-left
30 * @li top
31 * @li top-right
32 * @li right
33 * @li bottom-right
34 * @li bottom
35 * @li bottom-left
36 * @li middle
37 * @li smart
38 *
39 * Signals that you can add callbacks for are:
40 * @li "clicked" - the user clicked the empty space in the hover to dismiss
41 * @li "smart,changed" - a content object placed under the "smart"
42 * policy was replaced to a new slot direction.
43 *
44 * Default content parts of the hover widget that you can use for are:
45 * @li "left"
46 * @li "top-left"
47 * @li "top"
48 * @li "top-right"
49 * @li "right"
50 * @li "bottom-right"
51 * @li "bottom"
52 * @li "bottom-left"
53 * @li "middle"
54 * @li "smart"
55 *
56 * @note These content parts indicates the direction that the content will be
57 * displayed
58 *
59 * All directions may have contents at the same time, except for
60 * "smart". This is a special placement hint and its use case
61 * depends of the calculations coming from
62 * elm_hover_best_content_location_get(). Its use is for cases when
63 * one desires only one hover content, but with a dynamic special
64 * placement within the hover area. The content's geometry, whenever
65 * it changes, will be used to decide on a best location, not
66 * extrapolating the hover's parent object view to show it in (still
67 * being the hover's target determinant of its medium part -- move and
68 * resize it to simulate finger sizes, for example). If one of the
69 * directions other than "smart" are used, a previously content set
70 * using it will be deleted, and vice-versa.
71 *
72 * Supported elm_object common APIs.
73 * @li @ref elm_object_signal_emit
74 * @li @ref elm_object_signal_callback_add
75 * @li @ref elm_object_signal_callback_del
76 * @li @ref elm_object_part_content_set
77 * @li @ref elm_object_part_content_get
78 * @li @ref elm_object_part_content_unset
79 *
80 * See @ref tutorial_hover for more information.
81 *
82 * @{
83 */
84
85/**
86 * @typedef Elm_Hover_Axis
87 *
88 * The orientation axis for the hover object
89 */
90typedef enum
91{
92 ELM_HOVER_AXIS_NONE, /**< ELM_HOVER_AXIS_NONE -- no preferred orientation */
93 ELM_HOVER_AXIS_HORIZONTAL, /**< ELM_HOVER_AXIS_HORIZONTAL -- horizontal */
94 ELM_HOVER_AXIS_VERTICAL, /**< ELM_HOVER_AXIS_VERTICAL -- vertical */
95 ELM_HOVER_AXIS_BOTH /**< ELM_HOVER_AXIS_BOTH -- both */
96} Elm_Hover_Axis;
97
98/**
99 * @brief Adds a hover object to @p parent
100 *
101 * @param parent The parent object
102 * @return The hover object or NULL if one could not be created
103 *
104 * @ingroup Hover
105 */
106EAPI Evas_Object *elm_hover_add(Evas_Object *parent);
107
108/**
109 * @brief Sets the target object for the hover.
110 *
111 * @param obj The hover object
112 * @param target The object to center the hover onto.
113 *
114 * This function will cause the hover to be centered on the target object.
115 *
116 * @ingroup Hover
117 */
118EAPI void elm_hover_target_set(Evas_Object *obj, Evas_Object *target);
119
120/**
121 * @brief Gets the target object for the hover.
122 *
123 * @param obj The hover object
124 * @return The target object for the hover.
125 *
126 * @see elm_hover_target_set()
127 *
128 * @ingroup Hover
129 */
130EAPI Evas_Object *elm_hover_target_get(const Evas_Object *obj);
131
132/**
133 * @brief Sets the parent object for the hover.
134 *
135 * @param obj The hover object
136 * @param parent The object to locate the hover over.
137 *
138 * This function will cause the hover to take up the entire space that the
139 * parent object fills.
140 *
141 * @ingroup Hover
142 */
143EAPI void elm_hover_parent_set(Evas_Object *obj, Evas_Object *parent);
144
145/**
146 * @brief Gets the parent object for the hover.
147 *
148 * @param obj The hover object
149 * @return The parent object to locate the hover over.
150 *
151 * @see elm_hover_parent_set()
152 *
153 * @ingroup Hover
154 */
155EAPI Evas_Object *elm_hover_parent_get(const Evas_Object *obj);
156
157/**
158 * @brief Returns the best swallow location for content in the hover.
159 *
160 * @param obj The hover object
161 * @param pref_axis The preferred orientation axis for the hover object to use
162 * @return The edje location to place content into the hover or @c
163 * NULL, on errors.
164 *
165 * Best is defined here as the location at which there is the most available
166 * space.
167 *
168 * @p pref_axis may be one of
169 * - @c ELM_HOVER_AXIS_NONE -- no preferred orientation
170 * - @c ELM_HOVER_AXIS_HORIZONTAL -- horizontal
171 * - @c ELM_HOVER_AXIS_VERTICAL -- vertical
172 * - @c ELM_HOVER_AXIS_BOTH -- both
173 *
174 * If ELM_HOVER_AXIS_HORIZONTAL is chosen the returned position will
175 * necessarily be along the horizontal axis("left" or "right"). If
176 * ELM_HOVER_AXIS_VERTICAL is chosen the returned position will necessarily
177 * be along the vertical axis("top" or "bottom"). Choosing
178 * ELM_HOVER_AXIS_BOTH or ELM_HOVER_AXIS_NONE has the same effect and the
179 * returned position may be in either axis.
180 *
181 * @see elm_object_part_content_set()
182 *
183 * @ingroup Hover
184 */
185EAPI const char *elm_hover_best_content_location_get(const Evas_Object *obj, Elm_Hover_Axis pref_axis);
186
187/**
188 * @brief Dismiss a hover object
189 *
190 * @param obj The hover object
191 * Use this function to simulate clicking outside the hover to dismiss it.
192 * In this way, the hover will be hidden and the "clicked" signal will be emitted.
193 *
194 * @ingroup Hover
195 */
196EAPI void elm_hover_dismiss(Evas_Object *obj);
197/**
198 * @}
199 */
diff --git a/libraries/elementary/src/lib/elm_icon.c b/libraries/elementary/src/lib/elm_icon.c
new file mode 100644
index 0000000..187df0e
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_icon.c
@@ -0,0 +1,1006 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_icon.h"
4#include <assert.h>
5
6#ifdef ELM_EFREET
7#define NON_EXISTING (void *)-1
8static const char *icon_theme = NULL;
9#endif
10
11typedef struct _Widget_Data Widget_Data;
12
13struct _Widget_Data
14{
15 Evas_Object *img;
16 const char *stdicon;
17 Elm_Icon_Lookup_Order lookup_order;
18
19#ifdef HAVE_ELEMENTARY_ETHUMB
20 struct
21 {
22 struct
23 {
24 const char *path;
25 const char *key;
26 } file, thumb;
27
28 Ecore_Event_Handler *eeh;
29
30 Ethumb_Thumb_Format format;
31
32 Ethumb_Client_Async *request;
33
34 Eina_Bool retry : 1;
35 } thumb;
36#endif
37
38#ifdef ELM_EFREET
39 struct
40 {
41 int requested_size;
42 Eina_Bool use : 1;
43 } freedesktop;
44#endif
45 int in_eval;
46 Eina_Bool scale_up : 1;
47 Eina_Bool scale_down : 1;
48 Eina_Bool smooth : 1;
49 Eina_Bool fill_outside : 1;
50 Eina_Bool no_scale : 1;
51
52 /* for animation feature */
53 Ecore_Timer *timer;
54 int frame_count;
55 int cur_frame;
56 double duration;
57 Eina_Bool anim : 1;
58 Eina_Bool play : 1;
59};
60
61#ifdef HAVE_ELEMENTARY_ETHUMB
62static Eina_List *_elm_icon_retry = NULL;
63static int _icon_pending_request = 0;
64#endif
65
66static const char *widtype = NULL;
67static void _del_hook(Evas_Object *obj);
68static void _theme_hook(Evas_Object *obj);
69static void _sizing_eval(Evas_Object *obj);
70static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
71
72static Eina_Bool _icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name);
73static Eina_Bool _icon_freedesktop_set(Widget_Data *wd, Evas_Object *obj, const char *name, int size);
74
75static const char SIG_CLICKED[] = "clicked";
76
77static const Evas_Smart_Cb_Description _signals[] = {
78 {SIG_CLICKED, ""},
79 {NULL, NULL}
80};
81
82
83//FIXME: move this code to ecore
84#ifdef _WIN32
85static Eina_Bool
86_path_is_absolute(const char *path)
87{
88 //TODO: Check if this works with all absolute paths in windows
89 return ((isalpha (*path)) && (*(path + 1) == ':') && ((*(path + 2) == '\\') || (*(path + 2) == '/')));
90}
91#else
92static Eina_Bool
93_path_is_absolute(const char *path)
94{
95 return (*path == '/');
96}
97#endif
98
99static inline int
100_icon_size_min_get(Evas_Object *icon)
101{
102 int size;
103 _els_smart_icon_size_get(icon, &size, NULL);
104 return (size < 16) ? 16 : size;
105}
106
107#ifdef HAVE_ELEMENTARY_ETHUMB
108static void
109_icon_thumb_stop(Widget_Data *wd, void *ethumbd)
110{
111 if (wd->thumb.request)
112 {
113 ethumb_client_thumb_async_cancel(ethumbd, wd->thumb.request);
114 wd->thumb.request = NULL;
115 _icon_pending_request--;
116 }
117
118 if (wd->thumb.retry)
119 {
120 _elm_icon_retry = eina_list_remove(_elm_icon_retry, wd);
121 wd->thumb.retry = EINA_FALSE;
122 }
123}
124
125static Eina_Bool
126_icon_thumb_display(Widget_Data *wd)
127{
128 Eina_Bool ret = EINA_FALSE;
129
130 if (wd->thumb.format == ETHUMB_THUMB_EET)
131 {
132 static const char *extensions[] = {
133 ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
134 };
135 const char **ext, *ptr;
136 int prefix_size;
137 Eina_Bool video = EINA_FALSE;
138
139 prefix_size = eina_stringshare_strlen(wd->thumb.file.path) - 4;
140 if (prefix_size >= 0)
141 {
142 ptr = wd->thumb.file.path + prefix_size;
143 for (ext = extensions; *ext; ++ext)
144 if (!strcasecmp(ptr, *ext))
145 {
146 video = EINA_TRUE;
147 break;
148 }
149 }
150
151 if (video)
152 ret = _els_smart_icon_file_edje_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
153 }
154
155 if (!ret)
156 ret = _els_smart_icon_file_key_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
157
158 return ret;
159}
160
161static Eina_Bool
162_icon_thumb_retry(Widget_Data *wd)
163{
164 return _icon_thumb_display(wd);
165}
166
167static void
168_icon_thumb_cleanup(Ethumb_Client *ethumbd)
169{
170 Eina_List *l, *ll;
171 Widget_Data *wd;
172
173 EINA_LIST_FOREACH_SAFE(_elm_icon_retry, l, ll, wd)
174 if (_icon_thumb_retry(wd))
175 {
176 _elm_icon_retry = eina_list_remove_list(_elm_icon_retry, l);
177 wd->thumb.retry = EINA_FALSE;
178 }
179
180 if (_icon_pending_request == 0)
181 EINA_LIST_FREE(_elm_icon_retry, wd)
182 _icon_thumb_stop(wd, ethumbd);
183}
184
185static void
186_icon_thumb_finish(Widget_Data *wd, Ethumb_Client *ethumbd)
187{
188 const char *file = NULL, *group = NULL;
189 Eina_Bool ret;
190
191 _els_smart_icon_file_get(wd->img, &file, &group);
192 file = eina_stringshare_ref(file);
193 group = eina_stringshare_ref(group);
194
195 ret = _icon_thumb_display(wd);
196
197 if (!ret && file)
198 {
199 const char *p;
200
201 if (!wd->thumb.retry)
202 {
203 _elm_icon_retry = eina_list_append(_elm_icon_retry, wd);
204 wd->thumb.retry = EINA_TRUE;
205 }
206
207 /* Back to previous image */
208 if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
209 _els_smart_icon_file_edje_set(wd->img, file, group);
210 else
211 _els_smart_icon_file_key_set(wd->img, file, group);
212 }
213
214 _icon_thumb_cleanup(ethumbd);
215
216 eina_stringshare_del(file);
217 eina_stringshare_del(group);
218}
219
220static void
221_icon_thumb_done(Ethumb_Client *client, const char *thumb_path, const char *thumb_key, void *data)
222{
223 Widget_Data *wd = data;
224
225 assert(wd->thumb.request);
226
227 _icon_pending_request--;
228 wd->thumb.request = NULL;
229
230 eina_stringshare_replace(&wd->thumb.thumb.path, thumb_path);
231 eina_stringshare_replace(&wd->thumb.thumb.key, thumb_key);
232 wd->thumb.format = ethumb_client_format_get(client);
233
234 _icon_thumb_finish(wd, client);
235}
236
237static void
238_icon_thumb_error(Ethumb_Client *client, void *data)
239{
240 Widget_Data *wd = data;
241
242 assert(wd->thumb.request);
243
244 _icon_pending_request--;
245 wd->thumb.request = NULL;
246
247 ERR("could not generate thumbnail for %s (key: %s)", wd->thumb.file.path, wd->thumb.file.key);
248 _icon_thumb_cleanup(client);
249}
250
251static void
252_icon_thumb_apply(Widget_Data *wd)
253{
254 Ethumb_Client *ethumbd;
255
256 ethumbd = elm_thumb_ethumb_client_get();
257
258 _icon_thumb_stop(wd, ethumbd);
259
260 if (!wd->thumb.file.path) return ;
261
262 _icon_pending_request++;
263 if (!ethumb_client_file_set(ethumbd, wd->thumb.file.path, wd->thumb.file.key)) return ;
264 ethumb_client_size_set(ethumbd, _icon_size_min_get(wd->img), _icon_size_min_get(wd->img));
265 wd->thumb.request = ethumb_client_thumb_async_get(ethumbd, _icon_thumb_done, _icon_thumb_error, wd);
266}
267
268static Eina_Bool
269_icon_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
270{
271 Widget_Data *wd = data;
272
273 _icon_thumb_apply(wd);
274 return ECORE_CALLBACK_RENEW;
275}
276#endif
277
278static void
279_del_hook(Evas_Object *obj)
280{
281 Widget_Data *wd = elm_widget_data_get(obj);
282#ifdef HAVE_ELEMENTARY_ETHUMB
283 Ethumb_Client *ethumbd;
284#endif
285
286 if (!wd) return;
287 if (wd->stdicon) eina_stringshare_del(wd->stdicon);
288
289#ifdef HAVE_ELEMENTARY_ETHUMB
290 ethumbd = elm_thumb_ethumb_client_get();
291 _icon_thumb_stop(wd, ethumbd);
292
293 eina_stringshare_del(wd->thumb.file.path);
294 eina_stringshare_del(wd->thumb.file.key);
295 eina_stringshare_del(wd->thumb.thumb.path);
296 eina_stringshare_del(wd->thumb.thumb.key);
297
298 if (wd->thumb.eeh)
299 ecore_event_handler_del(wd->thumb.eeh);
300#endif
301
302 if (wd->timer)
303 ecore_timer_del(wd->timer);
304 free(wd);
305}
306
307static void
308_theme_hook(Evas_Object *obj)
309{
310 Widget_Data *wd = elm_widget_data_get(obj);
311 if (!wd) return;
312 if (wd->stdicon)
313 _elm_theme_object_icon_set(obj, wd->img, wd->stdicon, elm_widget_style_get(obj));
314 _sizing_eval(obj);
315}
316
317static void
318_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
319{
320 Widget_Data *wd = elm_widget_data_get(obj);
321 if (!wd) return;
322 Evas_Object *icon_edje;
323 icon_edje = _els_smart_icon_edje_get(wd->img);
324 if (!icon_edje) return;
325 edje_object_signal_emit(icon_edje, emission, source);
326}
327
328static void
329_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
330{
331 Widget_Data *wd = elm_widget_data_get(obj);
332 if (!wd) return;
333 Evas_Object *icon_edje;
334 icon_edje = _els_smart_icon_edje_get(wd->img);
335 if (!icon_edje) return;
336 edje_object_signal_callback_add(icon_edje, emission, source, func_cb, data);
337}
338
339static void
340_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
341{
342 Widget_Data *wd = elm_widget_data_get(obj);
343 if (!wd) return;
344 Evas_Object *icon_edje;
345 icon_edje = _els_smart_icon_edje_get(wd->img);
346 if (!icon_edje) return;
347 edje_object_signal_callback_del_full(icon_edje, emission, source, func_cb,
348 data);
349}
350
351static void
352_sizing_eval(Evas_Object *obj)
353{
354 Widget_Data *wd = elm_widget_data_get(obj);
355 if (!wd) return;
356 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
357 int w, h;
358
359 wd->in_eval++;
360 _els_smart_icon_size_get(wd->img, &w, &h);
361#ifdef ELM_EFREET
362 if (wd->freedesktop.use && wd->stdicon)
363 {
364 int size;
365 /* This icon has been set to a freedesktop icon, and the requested
366 appears to have a different size than the requested size, so try to
367 request another, higher resolution, icon.
368FIXME: Find a better heuristic to determine if there should be
369an icon with a different resolution. */
370 size = ((w / 16) + 1) * 16;
371 _icon_freedesktop_set(wd, obj, wd->stdicon, size);
372 }
373#endif
374 _els_smart_icon_scale_up_set(wd->img, wd->scale_up);
375 _els_smart_icon_scale_down_set(wd->img, wd->scale_down);
376 _els_smart_icon_smooth_scale_set(wd->img, wd->smooth);
377 _els_smart_icon_fill_inside_set(wd->img, !(wd->fill_outside));
378 if (wd->no_scale) _els_smart_icon_scale_set(wd->img, 1.0);
379 else
380 {
381 _els_smart_icon_scale_set(wd->img, elm_widget_scale_get(obj) *
382 _elm_config->scale);
383 _els_smart_icon_size_get(wd->img, &w, &h);
384 }
385 if (!wd->scale_down)
386 {
387 minw = w;
388 minh = h;
389 }
390 if (!wd->scale_up)
391 {
392 maxw = w;
393 maxh = h;
394 }
395 evas_object_size_hint_min_set(obj, minw, minh);
396 evas_object_size_hint_max_set(obj, maxw, maxh);
397 wd->in_eval--;
398}
399
400static void
401_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
402{
403 Evas_Event_Mouse_Up *ev = event_info;
404 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
405 evas_object_smart_callback_call(data, SIG_CLICKED, event_info);
406}
407
408static Eina_Bool
409_elm_icon_animate_cb(void *data)
410{
411 Widget_Data *wd = data;
412 Evas_Object *img_obj;
413
414 if (!wd) return ECORE_CALLBACK_CANCEL;
415 if (!wd->anim) return ECORE_CALLBACK_CANCEL;
416
417 img_obj = _els_smart_icon_object_get(wd->img);
418 wd->cur_frame++;
419 if (wd->cur_frame > wd->frame_count)
420 wd->cur_frame = wd->cur_frame % wd->frame_count;
421 evas_object_image_animated_frame_set(img_obj, wd->cur_frame);
422
423 wd->duration = evas_object_image_animated_frame_duration_get(img_obj, wd->cur_frame, 0);
424
425 if (wd->duration > 0)
426 ecore_timer_interval_set(wd->timer, wd->duration);
427 return ECORE_CALLBACK_RENEW;
428}
429
430static Eina_Bool
431_icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name)
432{
433 if (_elm_theme_object_icon_set(obj, wd->img, name, "default"))
434 {
435#ifdef ELM_EFREET
436 /* TODO: elm_unneed_efreet() */
437 wd->freedesktop.use = EINA_FALSE;
438#endif
439 return EINA_TRUE;
440 }
441 return EINA_FALSE;
442}
443
444static Eina_Bool
445#ifdef ELM_EFREET
446_icon_file_set(Widget_Data *wd, Evas_Object *obj, const char *path)
447#else
448_icon_file_set(Widget_Data *wd __UNUSED__, Evas_Object *obj, const char *path)
449#endif
450{
451 if (elm_icon_file_set(obj, path, NULL))
452 {
453#ifdef ELM_EFREET
454 /* TODO: elm_unneed_efreet() */
455 wd->freedesktop.use = EINA_FALSE;
456#endif
457 return EINA_TRUE;
458 }
459 return EINA_FALSE;
460}
461
462static Eina_Bool
463#ifdef ELM_EFREET
464_icon_freedesktop_set(Widget_Data *wd, Evas_Object *obj, const char *name, int size)
465#else
466_icon_freedesktop_set(Widget_Data *wd __UNUSED__, Evas_Object *obj __UNUSED__, const char *name __UNUSED__, int size __UNUSED__)
467#endif
468{
469#ifdef ELM_EFREET
470 const char *path;
471
472 elm_need_efreet();
473 if (icon_theme == NON_EXISTING) return EINA_FALSE;
474 if (!icon_theme)
475 {
476 Efreet_Icon_Theme *theme;
477 /* TODO: Listen for EFREET_EVENT_ICON_CACHE_UPDATE */
478 theme = efreet_icon_theme_find(getenv("E_ICON_THEME"));
479 if (!theme)
480 {
481 const char **itr;
482 static const char *themes[] = {
483 "gnome", "Human", "oxygen", "hicolor", NULL
484 };
485 for (itr = themes; *itr; itr++)
486 {
487 theme = efreet_icon_theme_find(*itr);
488 if (theme) break;
489 }
490 }
491
492 if (!theme)
493 {
494 icon_theme = NON_EXISTING;
495 return EINA_FALSE;
496 }
497 else
498 icon_theme = eina_stringshare_add(theme->name.internal);
499 }
500 path = efreet_icon_path_find(icon_theme, name, size);
501 wd->freedesktop.use = !!path;
502 if (wd->freedesktop.use)
503 {
504 wd->freedesktop.requested_size = size;
505 elm_icon_file_set(obj, path, NULL);
506 return EINA_TRUE;
507 }
508#endif
509 return EINA_FALSE;
510}
511
512static Eina_Bool
513_elm_icon_standard_set(Widget_Data *wd, Evas_Object *obj, const char *name, Eina_Bool *fdo)
514{
515 char *tmp;
516 Eina_Bool ret;
517
518 /* try locating the icon using the specified lookup order */
519 switch (wd->lookup_order)
520 {
521 case ELM_ICON_LOOKUP_FDO:
522 ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
523 if (ret && fdo) *fdo = EINA_TRUE;
524 break;
525 case ELM_ICON_LOOKUP_THEME:
526 ret = _icon_standard_set(wd, obj, name);
527 break;
528 case ELM_ICON_LOOKUP_THEME_FDO:
529 ret = _icon_standard_set(wd, obj, name);
530 if (!ret)
531 {
532 ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
533 if (ret && fdo) *fdo = EINA_TRUE;
534 }
535 break;
536 case ELM_ICON_LOOKUP_FDO_THEME:
537 default:
538 ret = _icon_freedesktop_set(wd, obj, name, _icon_size_min_get(wd->img));
539 if (!ret)
540 ret = _icon_standard_set(wd, obj, name);
541 else if (fdo)
542 *fdo = EINA_TRUE;
543 break;
544 }
545
546 if (ret)
547 {
548 eina_stringshare_replace(&wd->stdicon, name);
549 if (!wd->in_eval) _sizing_eval(obj);
550 return EINA_TRUE;
551 }
552
553 if (_path_is_absolute(name))
554 return _icon_file_set(wd, obj, name);
555
556 /* if that fails, see if icon name is in the format size/name. if so,
557 try locating a fallback without the size specification */
558 if (!(tmp = strchr(name, '/'))) return EINA_FALSE;
559 ++tmp;
560 if (*tmp) return elm_icon_standard_set(obj, tmp);
561 /* give up */
562 return EINA_FALSE;
563}
564
565static void
566_elm_icon_standard_resize(void *data,
567 Evas *e __UNUSED__,
568 Evas_Object *obj,
569 void *event_info __UNUSED__)
570{
571 Widget_Data *wd = data;
572 const char *refup = eina_stringshare_ref(wd->stdicon);
573 Eina_Bool fdo = EINA_FALSE;
574
575 if (!_elm_icon_standard_set(wd, obj, wd->stdicon, &fdo) || (!fdo))
576 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
577 _elm_icon_standard_resize, wd);
578 eina_stringshare_del(refup);
579}
580
581#ifdef HAVE_ELEMENTARY_ETHUMB
582static void
583_elm_icon_thumb_resize(void *data,
584 Evas *e __UNUSED__,
585 Evas_Object *obj,
586 void *event_info __UNUSED__)
587{
588 Widget_Data *wd = data;
589
590 if (wd->thumb.file.path)
591 elm_icon_thumb_set(obj, wd->thumb.file.path, wd->thumb.file.key);
592}
593#endif
594
595EAPI Evas_Object *
596elm_icon_add(Evas_Object *parent)
597{
598 Evas_Object *obj;
599 Evas *e;
600 Widget_Data *wd;
601
602 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
603
604 ELM_SET_WIDTYPE(widtype, "icon");
605 elm_widget_type_set(obj, "icon");
606 elm_widget_can_focus_set(obj, EINA_FALSE);
607 elm_widget_sub_object_add(parent, obj);
608 elm_widget_data_set(obj, wd);
609 elm_widget_del_hook_set(obj, _del_hook);
610 elm_widget_theme_hook_set(obj, _theme_hook);
611 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
612 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
613 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
614
615 wd->lookup_order = ELM_ICON_LOOKUP_THEME_FDO;
616 wd->img = _els_smart_icon_add(e);
617 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
618 _mouse_up, obj);
619 evas_object_repeat_events_set(wd->img, EINA_TRUE);
620 elm_widget_resize_object_set(obj, wd->img);
621
622 evas_object_smart_callbacks_descriptions_set(obj, _signals);
623
624#ifdef HAVE_ELEMENTARY_ETHUMB
625 wd->thumb.request = NULL;
626#endif
627
628 wd->smooth = EINA_TRUE;
629 wd->scale_up = EINA_TRUE;
630 wd->scale_down = EINA_TRUE;
631
632 _sizing_eval(obj);
633 return obj;
634}
635
636EAPI Eina_Bool
637elm_icon_memfile_set(Evas_Object *obj, const void *img, size_t size, const char *format, const char *key)
638{
639 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
640 Widget_Data *wd = elm_widget_data_get(obj);
641 Eina_Bool ret;
642
643 if (!wd) return EINA_FALSE;
644 EINA_SAFETY_ON_NULL_RETURN_VAL(img, EINA_FALSE);
645 EINA_SAFETY_ON_TRUE_RETURN_VAL(!size, EINA_FALSE);
646 eina_stringshare_del(wd->stdicon);
647 wd->stdicon = NULL;
648 ret = _els_smart_icon_memfile_set(wd->img, img, size, format, key);
649 if (!wd->in_eval) _sizing_eval(obj);
650 return ret;
651}
652
653EAPI Eina_Bool
654elm_icon_file_set(Evas_Object *obj, const char *file, const char *group)
655{
656 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
657 Widget_Data *wd = elm_widget_data_get(obj);
658 Eina_Bool ret;
659
660 if (!wd) return EINA_FALSE;
661 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
662
663#ifdef ELM_EFREET
664 if (!wd->freedesktop.use)
665 {
666 if (wd->stdicon) eina_stringshare_del(wd->stdicon);
667 wd->stdicon = NULL;
668 }
669#endif
670 if (eina_str_has_extension(file, ".edj"))
671 ret = _els_smart_icon_file_edje_set(wd->img, file, group);
672 else
673 ret = _els_smart_icon_file_key_set(wd->img, file, group);
674 if (!wd->in_eval) _sizing_eval(obj);
675 return ret;
676}
677
678EAPI void
679elm_icon_file_get(const Evas_Object *obj, const char **file, const char **group)
680{
681 ELM_CHECK_WIDTYPE(obj, widtype);
682 Widget_Data *wd = elm_widget_data_get(obj);
683 if (!wd) return;
684 _els_smart_icon_file_get(wd->img, file, group);
685}
686
687EAPI void
688elm_icon_thumb_set(Evas_Object *obj, const char *file, const char *group)
689{
690 ELM_CHECK_WIDTYPE(obj, widtype);
691 Widget_Data *wd = elm_widget_data_get(obj);
692 if (!wd) return;
693
694#ifdef HAVE_ELEMENTARY_ETHUMB
695 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
696 _elm_icon_standard_resize, wd);
697 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
698 _elm_icon_thumb_resize, wd);
699
700 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
701 _elm_icon_thumb_resize, wd);
702
703 eina_stringshare_replace(&wd->thumb.file.path, file);
704 eina_stringshare_replace(&wd->thumb.file.key, group);
705
706 if (elm_thumb_ethumb_client_connected_get())
707 {
708 _icon_thumb_apply(wd);
709 return ;
710 }
711
712 if (!wd->thumb.eeh)
713 {
714 wd->thumb.eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, _icon_thumb_apply_cb, wd);
715 }
716#else
717 (void) obj;
718 (void) file;
719 (void) group;
720#endif
721}
722
723
724EAPI Eina_Bool
725elm_icon_animated_available_get(const Evas_Object *obj)
726{
727 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
728 Evas_Object *img_obj ;
729 Widget_Data *wd = elm_widget_data_get(obj);
730 if (!wd) return EINA_FALSE;
731
732 img_obj = _els_smart_icon_object_get(wd->img);
733
734 return evas_object_image_animated_get(img_obj);
735}
736
737EAPI void
738elm_icon_animated_set(Evas_Object *obj, Eina_Bool anim)
739{
740 ELM_CHECK_WIDTYPE(obj, widtype);
741 Evas_Object *img_obj ;
742 Widget_Data *wd = elm_widget_data_get(obj);
743 if (!wd) return;
744 if (wd->anim == anim) return;
745
746 img_obj = _els_smart_icon_object_get(wd->img);
747 if (!evas_object_image_animated_get(img_obj)) return;
748 if (anim)
749 {
750 wd->frame_count = evas_object_image_animated_frame_count_get(img_obj);
751 wd->cur_frame = 1;
752 wd->duration = evas_object_image_animated_frame_duration_get(img_obj, wd->cur_frame, 0);
753 evas_object_image_animated_frame_set(img_obj, wd->cur_frame);
754 }
755 else
756 {
757 wd->frame_count = -1;
758 wd->cur_frame = -1;
759 wd->duration = -1;
760 }
761 wd->anim = anim;
762 return;
763}
764
765EAPI Eina_Bool
766elm_icon_animated_get(const Evas_Object *obj)
767{
768 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
769 Widget_Data *wd = elm_widget_data_get(obj);
770 if (!wd) return EINA_FALSE;
771 return wd->anim;
772}
773
774EAPI void
775elm_icon_animated_play_set(Evas_Object *obj, Eina_Bool play)
776{
777 ELM_CHECK_WIDTYPE(obj, widtype);
778 Widget_Data *wd = elm_widget_data_get(obj);
779 if (!wd) return;
780 if (!wd->anim) return;
781 if (wd->play == play) return;
782
783 if (play)
784 {
785 wd->timer = ecore_timer_add(wd->duration, _elm_icon_animate_cb, wd);
786 }
787 else
788 {
789 if (wd->timer)
790 {
791 ecore_timer_del(wd->timer);
792 wd->timer = NULL;
793 }
794 }
795 wd->play = play;
796
797}
798
799EAPI Eina_Bool
800elm_icon_animated_play_get(const Evas_Object *obj)
801{
802 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
803 Widget_Data *wd = elm_widget_data_get(obj);
804 if (!wd) return EINA_FALSE;
805 return wd->play;
806}
807
808EAPI Eina_Bool
809elm_icon_standard_set(Evas_Object *obj, const char *name)
810{
811 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
812 Widget_Data *wd = elm_widget_data_get(obj);
813 Eina_Bool fdo = EINA_FALSE;
814 Eina_Bool ret;
815
816 if ((!wd) || (!name)) return EINA_FALSE;
817
818 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
819 _elm_icon_standard_resize, wd);
820
821 ret = _elm_icon_standard_set(wd, obj, name, &fdo);
822
823 if (fdo)
824 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
825 _elm_icon_standard_resize, wd);
826
827 return ret;
828}
829
830EAPI const char *
831elm_icon_standard_get(const Evas_Object *obj)
832{
833 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
834 Widget_Data *wd = elm_widget_data_get(obj);
835 if (!wd) return NULL;
836 return wd->stdicon;
837}
838
839EAPI void
840elm_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
841{
842 ELM_CHECK_WIDTYPE(obj, widtype);
843 Widget_Data *wd = elm_widget_data_get(obj);
844 if (wd) wd->lookup_order = order;
845}
846
847EAPI Elm_Icon_Lookup_Order
848elm_icon_order_lookup_get(const Evas_Object *obj)
849{
850 ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
851 Widget_Data *wd = elm_widget_data_get(obj);
852 if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
853 return wd->lookup_order;
854}
855
856EAPI void
857elm_icon_smooth_set(Evas_Object *obj, Eina_Bool smooth)
858{
859 ELM_CHECK_WIDTYPE(obj, widtype);
860 Widget_Data *wd = elm_widget_data_get(obj);
861
862 if (!wd) return;
863 wd->smooth = smooth;
864 if (!wd->in_eval) _sizing_eval(obj);
865}
866
867EAPI Eina_Bool
868elm_icon_smooth_get(const Evas_Object *obj)
869{
870 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
871 Widget_Data *wd = elm_widget_data_get(obj);
872
873 if (!wd) return EINA_FALSE;
874 return wd->smooth;
875}
876
877EAPI void
878elm_icon_no_scale_set(Evas_Object *obj, Eina_Bool no_scale)
879{
880 ELM_CHECK_WIDTYPE(obj, widtype);
881 Widget_Data *wd = elm_widget_data_get(obj);
882
883 if (!wd) return;
884 wd->no_scale = no_scale;
885 if (!wd->in_eval) _sizing_eval(obj);
886}
887
888EAPI Eina_Bool
889elm_icon_no_scale_get(const Evas_Object *obj)
890{
891 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
892 Widget_Data *wd = elm_widget_data_get(obj);
893 if (!wd) return EINA_FALSE;
894 return wd->no_scale;
895}
896
897EAPI void
898elm_icon_resizable_set(Evas_Object *obj, Eina_Bool size_up, Eina_Bool size_down)
899{
900 ELM_CHECK_WIDTYPE(obj, widtype);
901 Widget_Data *wd = elm_widget_data_get(obj);
902
903 if (!wd) return;
904 wd->scale_up = size_up;
905 wd->scale_down = size_down;
906 if (!wd->in_eval) _sizing_eval(obj);
907}
908
909EAPI void
910elm_icon_resizable_get(const Evas_Object *obj, Eina_Bool *size_up, Eina_Bool *size_down)
911{
912 ELM_CHECK_WIDTYPE(obj, widtype);
913 Widget_Data *wd = elm_widget_data_get(obj);
914 if (!wd) return;
915 if (size_up) *size_up = wd->scale_up;
916 if (size_down) *size_down = wd->scale_down;
917}
918
919EAPI void
920elm_icon_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside)
921{
922 ELM_CHECK_WIDTYPE(obj, widtype);
923 Widget_Data *wd = elm_widget_data_get(obj);
924
925 if (!wd) return;
926 wd->fill_outside = fill_outside;
927 if (!wd->in_eval) _sizing_eval(obj);
928}
929
930EAPI void
931elm_icon_size_get(const Evas_Object *obj, int *w, int *h)
932{
933 ELM_CHECK_WIDTYPE(obj, widtype);
934 Widget_Data *wd = elm_widget_data_get(obj);
935
936 if (!wd) return;
937 _els_smart_icon_size_get(wd->img, w, h);
938}
939
940EAPI Eina_Bool
941elm_icon_fill_outside_get(const Evas_Object *obj)
942{
943 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
944 Widget_Data *wd = elm_widget_data_get(obj);
945
946 if (!wd) return EINA_FALSE;
947 return wd->fill_outside;
948}
949
950EAPI void
951elm_icon_prescale_set(Evas_Object *obj, int size)
952{
953 ELM_CHECK_WIDTYPE(obj, widtype);
954 Widget_Data *wd = elm_widget_data_get(obj);
955
956 if (!wd) return;
957 _els_smart_icon_scale_size_set(wd->img, size);
958}
959
960EAPI int
961elm_icon_prescale_get(const Evas_Object *obj)
962{
963 ELM_CHECK_WIDTYPE(obj, widtype) 0;
964 Widget_Data *wd = elm_widget_data_get(obj);
965
966 if (!wd) return 0;
967 return _els_smart_icon_scale_size_get(wd->img);
968}
969
970EAPI Evas_Object *
971elm_icon_object_get(Evas_Object *obj)
972{
973 ELM_CHECK_WIDTYPE(obj, widtype) 0;
974 Widget_Data *wd = elm_widget_data_get(obj);
975
976 if (!wd) return NULL;
977 return _els_smart_icon_object_get(wd->img);
978}
979
980EAPI void
981elm_icon_preload_disabled_set(Evas_Object *obj, Eina_Bool disabled)
982{
983 ELM_CHECK_WIDTYPE(obj, widtype);
984 Widget_Data *wd = elm_widget_data_get(obj);
985
986 if (!wd) return;
987 _els_smart_icon_preload_set(wd->img, !!disabled);
988}
989
990EAPI void
991elm_icon_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed)
992{
993 ELM_CHECK_WIDTYPE(obj, widtype);
994 Widget_Data *wd = elm_widget_data_get(obj);
995 if (!wd) return;
996 _els_smart_icon_aspect_fixed_set(wd->img, fixed);
997}
998
999EAPI Eina_Bool
1000elm_icon_aspect_fixed_get(const Evas_Object *obj)
1001{
1002 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1003 Widget_Data *wd = elm_widget_data_get(obj);
1004 if (!wd) return EINA_FALSE;
1005 return _els_smart_icon_aspect_fixed_get(wd->img);
1006}
diff --git a/libraries/elementary/src/lib/elm_icon.h b/libraries/elementary/src/lib/elm_icon.h
new file mode 100644
index 0000000..08d6c11
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_icon.h
@@ -0,0 +1,566 @@
1/**
2 * @defgroup Icon Icon
3 * @ingroup Elementary
4 *
5 * @image html img/widget/icon/preview-00.png
6 * @image latex img/widget/icon/preview-00.eps
7 *
8 * An object that provides standard icon images (delete, edit, arrows, etc.)
9 * or a custom file (PNG, JPG, EDJE, etc.) used for an icon.
10 *
11 * The icon image requested can be in the elementary theme, or in the
12 * freedesktop.org paths. It's possible to set the order of preference from
13 * where the image will be used.
14 *
15 * This API is very similar to @ref Image, but with ready to use images.
16 *
17 * Default images provided by the theme are described below.
18 *
19 * The first list contains icons that were first intended to be used in
20 * toolbars, but can be used in many other places too:
21 * @li home
22 * @li close
23 * @li apps
24 * @li arrow_up
25 * @li arrow_down
26 * @li arrow_left
27 * @li arrow_right
28 * @li chat
29 * @li clock
30 * @li delete
31 * @li edit
32 * @li refresh
33 * @li folder
34 * @li file
35 *
36 * Now some icons that were designed to be used in menus (but again, you can
37 * use them anywhere else):
38 * @li menu/home
39 * @li menu/close
40 * @li menu/apps
41 * @li menu/arrow_up
42 * @li menu/arrow_down
43 * @li menu/arrow_left
44 * @li menu/arrow_right
45 * @li menu/chat
46 * @li menu/clock
47 * @li menu/delete
48 * @li menu/edit
49 * @li menu/refresh
50 * @li menu/folder
51 * @li menu/file
52 *
53 * And here we have some media player specific icons:
54 * @li media_player/forward
55 * @li media_player/info
56 * @li media_player/next
57 * @li media_player/pause
58 * @li media_player/play
59 * @li media_player/prev
60 * @li media_player/rewind
61 * @li media_player/stop
62 *
63 * Signals that you can add callbacks for are:
64 *
65 * "clicked" - This is called when a user has clicked the icon
66 *
67 * Supported elm_object common APIs.
68 * @li @ref elm_object_signal_emit
69 * @li @ref elm_object_signal_callback_add
70 * @li @ref elm_object_signal_callback_del
71 *
72 * An example of usage for this API follows:
73 * @li @ref tutorial_icon
74 */
75
76/**
77 * @addtogroup Icon
78 * @{
79 */
80
81typedef enum
82{
83 ELM_ICON_NONE,
84 ELM_ICON_FILE,
85 ELM_ICON_STANDARD
86} Elm_Icon_Type;
87
88/**
89 * @enum _Elm_Icon_Lookup_Order
90 * @typedef Elm_Icon_Lookup_Order
91 *
92 * Lookup order used by elm_icon_standard_set(). Should look for icons in the
93 * theme, FDO paths, or both?
94 *
95 * @ingroup Icon
96 */
97typedef enum
98{
99 ELM_ICON_LOOKUP_FDO_THEME, /**< icon look up order: freedesktop, theme */
100 ELM_ICON_LOOKUP_THEME_FDO, /**< icon look up order: theme, freedesktop */
101 ELM_ICON_LOOKUP_FDO, /**< icon look up order: freedesktop */
102 ELM_ICON_LOOKUP_THEME /**< icon look up order: theme */
103} Elm_Icon_Lookup_Order;
104
105/**
106 * Add a new icon object to the parent.
107 *
108 * @param parent The parent object
109 * @return The new object or NULL if it cannot be created
110 *
111 * @see elm_icon_file_set()
112 *
113 * @ingroup Icon
114 */
115EAPI Evas_Object *elm_icon_add(Evas_Object *parent);
116
117/**
118 * Set the file that will be used as icon.
119 *
120 * @param obj The icon object
121 * @param file The path to file that will be used as icon image
122 * @param group The group that the icon belongs to an edje file
123 *
124 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
125 *
126 * @note The icon image set by this function can be changed by
127 * elm_icon_standard_set().
128 *
129 * @see elm_icon_file_get()
130 *
131 * @ingroup Icon
132 */
133EAPI Eina_Bool elm_icon_file_set(Evas_Object *obj, const char *file, const char *group);
134
135/**
136 * Set a location in memory to be used as an icon
137 *
138 * @param obj The icon object
139 * @param img The binary data that will be used as an image
140 * @param size The size of binary data @p img
141 * @param format Optional format of @p img to pass to the image loader
142 * @param key Optional key of @p img to pass to the image loader (eg. if @p img is an edje file)
143 *
144 * The @p format string should be something like "png", "jpg", "tga",
145 * "tiff", "bmp" etc. if it is provided (NULL if not). This improves
146 * the loader performance as it tries the "correct" loader first before
147 * trying a range of other possible loaders until one succeeds.
148 *
149 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
150 *
151 * @note The icon image set by this function can be changed by
152 * elm_icon_standard_set().
153 *
154 * @ingroup Icon
155 */
156EAPI Eina_Bool elm_icon_memfile_set(Evas_Object *obj, const void *img, size_t size, const char *format, const char *key);
157
158/**
159 * Get the file that will be used as icon.
160 *
161 * @param obj The icon object
162 * @param file The path to file that will be used as the icon image
163 * @param group The group that the icon belongs to, in edje file
164 *
165 * @see elm_icon_file_set()
166 *
167 * @ingroup Icon
168 */
169EAPI void elm_icon_file_get(const Evas_Object *obj, const char **file, const char **group);
170
171/**
172 * Set the file that will be used, but use a generated thumbnail.
173 *
174 * @param obj The icon object
175 * @param file The path to file that will be used as icon image
176 * @param group The group that the icon belongs to an edje file
177 *
178 * This functions like elm_icon_file_set() but requires the Ethumb library
179 * support to be enabled successfully with elm_need_ethumb(). When set
180 * the file indicated has a thumbnail generated and cached on disk for
181 * future use or will directly use an existing cached thumbnail if it
182 * is valid.
183 *
184 * @see elm_icon_file_set()
185 *
186 * @ingroup Icon
187 */
188EAPI void elm_icon_thumb_set(Evas_Object *obj, const char *file, const char *group);
189
190/**
191 * Set the icon by icon standards names.
192 *
193 * @param obj The icon object
194 * @param name The icon name
195 *
196 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
197 *
198 * For example, freedesktop.org defines standard icon names such as "home",
199 * "network", etc. There can be different icon sets to match those icon
200 * keys. The @p name given as parameter is one of these "keys", and will be
201 * used to look in the freedesktop.org paths and elementary theme. One can
202 * change the lookup order with elm_icon_order_lookup_set().
203 *
204 * If name is not found in any of the expected locations and it is the
205 * absolute path of an image file, this image will be used.
206 *
207 * @note The icon image set by this function can be changed by
208 * elm_icon_file_set().
209 *
210 * @see elm_icon_standard_get()
211 * @see elm_icon_file_set()
212 *
213 * @ingroup Icon
214 */
215EAPI Eina_Bool elm_icon_standard_set(Evas_Object *obj, const char *name);
216
217/**
218 * Get the icon name set by icon standard names.
219 *
220 * @param obj The icon object
221 * @return The icon name
222 *
223 * If the icon image was set using elm_icon_file_set() instead of
224 * elm_icon_standard_set(), then this function will return @c NULL.
225 *
226 * @see elm_icon_standard_set()
227 *
228 * @ingroup Icon
229 */
230EAPI const char *elm_icon_standard_get(const Evas_Object *obj);
231
232/**
233 * Set the smooth scaling for an icon object.
234 *
235 * @param obj The icon object
236 * @param smooth @c EINA_TRUE if smooth scaling should be used, @c EINA_FALSE
237 * otherwise. Default is @c EINA_TRUE.
238 *
239 * Set the scaling algorithm to be used when scaling the icon image. Smooth
240 * scaling provides a better resulting image, but is slower.
241 *
242 * The smooth scaling should be disabled when making animations that change
243 * the icon size, since they will be faster. Animations that don't require
244 * resizing of the icon can keep the smooth scaling enabled (even if the icon
245 * is already scaled, since the scaled icon image will be cached).
246 *
247 * @see elm_icon_smooth_get()
248 *
249 * @ingroup Icon
250 */
251EAPI void elm_icon_smooth_set(Evas_Object *obj, Eina_Bool smooth);
252
253/**
254 * Get whether smooth scaling is enabled for an icon object.
255 *
256 * @param obj The icon object
257 * @return @c EINA_TRUE if smooth scaling is enabled, @c EINA_FALSE otherwise.
258 *
259 * @see elm_icon_smooth_set()
260 *
261 * @ingroup Icon
262 */
263EAPI Eina_Bool elm_icon_smooth_get(const Evas_Object *obj);
264
265/**
266 * Disable scaling of this object.
267 *
268 * @param obj The icon object.
269 * @param no_scale @c EINA_TRUE if the object is not scalable, @c EINA_FALSE
270 * otherwise. Default is @c EINA_FALSE.
271 *
272 * This function disables scaling of the icon object through the function
273 * elm_object_scale_set(). However, this does not affect the object
274 * size/resize in any way. For that effect, take a look at
275 * elm_icon_resizable_set().
276 *
277 * @see elm_icon_no_scale_get()
278 * @see elm_icon_resizable_set()
279 * @see elm_object_scale_set()
280 *
281 * @ingroup Icon
282 */
283EAPI void elm_icon_no_scale_set(Evas_Object *obj, Eina_Bool no_scale);
284
285/**
286 * Get whether scaling is disabled on the object.
287 *
288 * @param obj The icon object
289 * @return @c EINA_TRUE if scaling is disabled, @c EINA_FALSE otherwise
290 *
291 * @see elm_icon_no_scale_set()
292 *
293 * @ingroup Icon
294 */
295EAPI Eina_Bool elm_icon_no_scale_get(const Evas_Object *obj);
296
297/**
298 * Set if the object is (up/down) resizable.
299 *
300 * @param obj The icon object
301 * @param size_up A bool to set if the object is resizable up. Default is
302 * @c EINA_TRUE.
303 * @param size_down A bool to set if the object is resizable down. Default
304 * is @c EINA_TRUE.
305 *
306 * This function limits the icon object resize ability. If @p size_up is set to
307 * @c EINA_FALSE, the object can't have its height or width resized to a value
308 * higher than the original icon size. Same is valid for @p size_down.
309 *
310 * @see elm_icon_resizable_get()
311 *
312 * @ingroup Icon
313 */
314EAPI void elm_icon_resizable_set(Evas_Object *obj, Eina_Bool size_up, Eina_Bool size_down);
315
316/**
317 * Get if the object is (up/down) resizable.
318 *
319 * @param obj The icon object
320 * @param size_up A bool to set if the object is resizable up
321 * @param size_down A bool to set if the object is resizable down
322 *
323 * @see elm_icon_resizable_set()
324 *
325 * @ingroup Icon
326 */
327EAPI void elm_icon_resizable_get(const Evas_Object *obj, Eina_Bool *size_up, Eina_Bool *size_down);
328
329/**
330 * Get the object's image size
331 *
332 * @param obj The icon object
333 * @param w A pointer to store the width in
334 * @param h A pointer to store the height in
335 *
336 * @ingroup Icon
337 */
338EAPI void elm_icon_size_get(const Evas_Object *obj, int *w, int *h);
339
340/**
341 * Set if the icon fill the entire object area.
342 *
343 * @param obj The icon object
344 * @param fill_outside @c EINA_TRUE if the object is filled outside,
345 * @c EINA_FALSE otherwise. Default is @c EINA_FALSE.
346 *
347 * When the icon object is resized to a different aspect ratio from the
348 * original icon image, the icon image will still keep its aspect. This flag
349 * tells how the image should fill the object's area. They are: keep the
350 * entire icon inside the limits of height and width of the object (@p
351 * fill_outside is @c EINA_FALSE) or let the extra width or height go outside
352 * of the object, and the icon will fill the entire object (@p fill_outside
353 * is @c EINA_TRUE).
354 *
355 * @note Unlike @ref Image, there's no option in icon to set the aspect ratio
356 * retain property to false. Thus, the icon image will always keep its
357 * original aspect ratio.
358 *
359 * @see elm_icon_fill_outside_get()
360 * @see elm_image_fill_outside_set()
361 *
362 * @ingroup Icon
363 */
364EAPI void elm_icon_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside);
365
366/**
367 * Get if the object is filled outside.
368 *
369 * @param obj The icon object
370 * @return @c EINA_TRUE if the object is filled outside, @c EINA_FALSE otherwise.
371 *
372 * @see elm_icon_fill_outside_set()
373 *
374 * @ingroup Icon
375 */
376EAPI Eina_Bool elm_icon_fill_outside_get(const Evas_Object *obj);
377
378/**
379 * Set the prescale size for the icon.
380 *
381 * @param obj The icon object
382 * @param size The prescale size. This value is used for both width and
383 * height.
384 *
385 * This function sets a new size for pixmap representation of the given
386 * icon. It allows the icon to be loaded already in the specified size,
387 * reducing the memory usage and load time when loading a big icon with load
388 * size set to a smaller size.
389 *
390 * It's equivalent to the elm_bg_load_size_set() function for bg.
391 *
392 * @note this is just a hint, the real size of the pixmap may differ
393 * depending on the type of icon being loaded, being bigger than requested.
394 *
395 * @see elm_icon_prescale_get()
396 * @see elm_bg_load_size_set()
397 *
398 * @ingroup Icon
399 */
400EAPI void elm_icon_prescale_set(Evas_Object *obj, int size);
401
402/**
403 * Get the prescale size for the icon.
404 *
405 * @param obj The icon object
406 * @return The prescale size
407 *
408 * @see elm_icon_prescale_set()
409 *
410 * @ingroup Icon
411 */
412EAPI int elm_icon_prescale_get(const Evas_Object *obj);
413
414/**
415 * Gets the image object of the icon. DO NOT MODIFY THIS.
416 *
417 * @param obj The icon object
418 * @return The internal icon object
419 *
420 * @ingroup Icon
421 */
422EAPI Evas_Object *elm_icon_object_get(Evas_Object *obj);
423
424/**
425 * Sets the icon lookup order used by elm_icon_standard_set().
426 *
427 * @param obj The icon object
428 * @param order The icon lookup order (can be one of
429 * ELM_ICON_LOOKUP_FDO_THEME, ELM_ICON_LOOKUP_THEME_FDO, ELM_ICON_LOOKUP_FDO
430 * or ELM_ICON_LOOKUP_THEME)
431 *
432 * @see elm_icon_order_lookup_get()
433 * @see Elm_Icon_Lookup_Order
434 *
435 * @ingroup Icon
436 */
437EAPI void elm_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order);
438
439/**
440 * Gets the icon lookup order.
441 *
442 * @param obj The icon object
443 * @return The icon lookup order
444 *
445 * @see elm_icon_order_lookup_set()
446 * @see Elm_Icon_Lookup_Order
447 *
448 * @ingroup Icon
449 */
450EAPI Elm_Icon_Lookup_Order elm_icon_order_lookup_get(const Evas_Object *obj);
451
452/**
453 * Enable or disable preloading of the icon
454 *
455 * @param obj The icon object
456 * @param disabled If EINA_TRUE, preloading will be disabled
457 * @ingroup Icon
458 */
459EAPI void elm_icon_preload_disabled_set(Evas_Object *obj, Eina_Bool disabled);
460
461/**
462 * Get if the icon supports animation or not.
463 *
464 * @param obj The icon object
465 * @return @c EINA_TRUE if the icon supports animation,
466 * @c EINA_FALSE otherwise.
467 *
468 * Return if this elm icon's image can be animated. Currently Evas only
469 * supports gif animation. If the return value is EINA_FALSE, other
470 * elm_icon_animated_xxx APIs won't work.
471 * @ingroup Icon
472 */
473EAPI Eina_Bool elm_icon_animated_available_get(const Evas_Object *obj);
474
475/**
476 * Set animation mode of the icon.
477 *
478 * @param obj The icon object
479 * @param animated @c EINA_TRUE if the object do animation job,
480 * @c EINA_FALSE otherwise. Default is @c EINA_FALSE.
481 *
482 * Since the default animation mode is set to EINA_FALSE,
483 * the icon is shown without animation. Files like animated GIF files
484 * can animate, and this is supported if you enable animated support
485 * on the icon.
486 * Set it to EINA_TRUE when the icon needs to be animated.
487 * @ingroup Icon
488 */
489EAPI void elm_icon_animated_set(Evas_Object *obj, Eina_Bool animated);
490
491/**
492 * Get animation mode of the icon.
493 *
494 * @param obj The icon object
495 * @return The animation mode of the icon object
496 * @see elm_icon_animated_set
497 * @ingroup Icon
498 */
499EAPI Eina_Bool elm_icon_animated_get(const Evas_Object *obj);
500
501/**
502 * Set animation play mode of the icon.
503 *
504 * @param obj The icon object
505 * @param play @c EINA_TRUE the object play animation images,
506 * @c EINA_FALSE otherwise. Default is @c EINA_FALSE.
507 *
508 * To play elm icon's animation, set play to EINA_TRUE.
509 * For example, you make gif player using this set/get API and click event.
510 * This literally lets you control current play or paused state. To have
511 * this work with animated GIF files for example, you first, before
512 * setting the file have to use elm_icon_animated_set() to enable animation
513 * at all on the icon.
514 *
515 * 1. Click event occurs
516 * 2. Check play flag using elm_icon_animated_play_get
517 * 3. If elm icon was playing, set play to EINA_FALSE.
518 * Then animation will be stopped and vice versa
519 * @ingroup Icon
520 */
521EAPI void elm_icon_animated_play_set(Evas_Object *obj, Eina_Bool play);
522
523/**
524 * Get animation play mode of the icon.
525 *
526 * @param obj The icon object
527 * @return The play mode of the icon object
528 *
529 * @see elm_icon_animated_play_get
530 * @ingroup Icon
531 */
532EAPI Eina_Bool elm_icon_animated_play_get(const Evas_Object *obj);
533
534/**
535 * Set whether the original aspect ratio of the icon should be kept on resize.
536 *
537 * @param obj The icon object.
538 * @param fixed @c EINA_TRUE if the icon should retain the aspect,
539 * @c EINA_FALSE otherwise.
540 *
541 * The original aspect ratio (width / height) of the icon is usually
542 * distorted to match the object's size. Enabling this option will retain
543 * this original aspect, and the way that the icon is fit into the object's
544 * area depends on the option set by elm_icon_fill_outside_set().
545 *
546 * @see elm_icon_aspect_fixed_get()
547 * @see elm_icon_fill_outside_set()
548 *
549 * @ingroup Icon
550 */
551EAPI void elm_icon_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed);
552
553/**
554 * Get if the object retains the original aspect ratio.
555 *
556 * @param obj The icon object.
557 * @return @c EINA_TRUE if the object keeps the original aspect, @c EINA_FALSE
558 * otherwise.
559 *
560 * @ingroup Icon
561 */
562EAPI Eina_Bool elm_icon_aspect_fixed_get(const Evas_Object *obj);
563
564/**
565 * @}
566 */
diff --git a/libraries/elementary/src/lib/elm_image.c b/libraries/elementary/src/lib/elm_image.c
new file mode 100644
index 0000000..5d59251
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_image.c
@@ -0,0 +1,352 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_icon.h"
4
5typedef struct _Widget_Data Widget_Data;
6
7struct _Widget_Data
8{
9 Evas_Object *img;
10 Eina_Bool scale_up : 1;
11 Eina_Bool scale_down : 1;
12 Eina_Bool smooth : 1;
13 Eina_Bool fill_outside : 1;
14 Eina_Bool no_scale : 1;
15};
16
17static const char *widtype = NULL;
18static void _del_hook(Evas_Object *obj);
19static void _theme_hook(Evas_Object *obj);
20static void _sizing_eval(Evas_Object *obj);
21static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
22
23static const char SIG_CLICKED[] = "clicked";
24
25static const Evas_Smart_Cb_Description _signals[] = {
26 {SIG_CLICKED, ""},
27 {NULL, NULL}
28};
29
30
31static void
32_del_hook(Evas_Object *obj)
33{
34 Widget_Data *wd = elm_widget_data_get(obj);
35
36 if (!wd) return;
37 free(wd);
38}
39
40static void
41_del_pre_hook(Evas_Object *obj)
42{
43 Widget_Data *wd = elm_widget_data_get(obj);
44
45 if (!wd) return;
46 evas_object_del(wd->img);
47}
48
49static void
50_theme_hook(Evas_Object *obj)
51{
52 Widget_Data *wd = elm_widget_data_get(obj);
53
54 if (!wd) return;
55 _sizing_eval(obj);
56}
57
58static void
59_sizing_eval(Evas_Object *obj)
60{
61 Widget_Data *wd = elm_widget_data_get(obj);
62 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
63 int w, h;
64
65 if (!wd) return;
66 _els_smart_icon_size_get(wd->img, &w, &h);
67 _els_smart_icon_scale_up_set(wd->img, wd->scale_up);
68 _els_smart_icon_scale_down_set(wd->img, wd->scale_down);
69 _els_smart_icon_smooth_scale_set(wd->img, wd->smooth);
70 _els_smart_icon_fill_inside_set(wd->img, !(wd->fill_outside));
71 if (wd->no_scale) _els_smart_icon_scale_set(wd->img, 1.0);
72 else
73 {
74 _els_smart_icon_scale_set(wd->img, elm_widget_scale_get(obj) * _elm_config->scale);
75 _els_smart_icon_size_get(wd->img, &w, &h);
76 }
77 if (!wd->scale_down)
78 {
79 minw = w;
80 minh = h;
81 }
82 if (!wd->scale_up)
83 {
84 maxw = w;
85 maxh = h;
86 }
87 evas_object_size_hint_min_set(obj, minw, minh);
88 evas_object_size_hint_max_set(obj, maxw, maxh);
89}
90
91static void
92_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
93{
94 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
95}
96
97EAPI Evas_Object *
98elm_image_add(Evas_Object *parent)
99{
100 Evas_Object *obj;
101 Evas *e;
102 Widget_Data *wd;
103
104 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
105
106 ELM_SET_WIDTYPE(widtype, "image");
107 elm_widget_type_set(obj, "image");
108 elm_widget_sub_object_add(parent, obj);
109 elm_widget_data_set(obj, wd);
110 elm_widget_del_hook_set(obj, _del_hook);
111 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
112 elm_widget_theme_hook_set(obj, _theme_hook);
113 elm_widget_can_focus_set(obj, EINA_FALSE);
114
115 wd->img = _els_smart_icon_add(e);
116 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
117 _mouse_up, obj);
118 evas_object_repeat_events_set(wd->img, EINA_TRUE);
119 elm_widget_resize_object_set(obj, wd->img);
120
121 evas_object_smart_callbacks_descriptions_set(obj, _signals);
122
123 wd->smooth = EINA_TRUE;
124 wd->scale_up = EINA_TRUE;
125 wd->scale_down = EINA_TRUE;
126
127 _els_smart_icon_scale_size_set(wd->img, 0);
128
129 _sizing_eval(obj);
130 return obj;
131}
132
133EAPI Eina_Bool
134elm_image_file_set(Evas_Object *obj, const char *file, const char *group)
135{
136 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
137 Widget_Data *wd = elm_widget_data_get(obj);
138 Eina_Bool ret;
139 const char *p;
140
141 if (!wd) return EINA_FALSE;
142 EINA_SAFETY_ON_NULL_RETURN_VAL(file, EINA_FALSE);
143 if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
144 ret = _els_smart_icon_file_edje_set(wd->img, file, group);
145 else
146 ret = _els_smart_icon_file_key_set(wd->img, file, group);
147 _sizing_eval(obj);
148 return ret;
149}
150
151EAPI void
152elm_image_file_get(const Evas_Object *obj, const char **file, const char **group)
153{
154 ELM_CHECK_WIDTYPE(obj, widtype);
155 Widget_Data *wd = elm_widget_data_get(obj);
156 if (!wd) return;
157 _els_smart_icon_file_get(wd->img, file, group);
158}
159
160EAPI void
161elm_image_smooth_set(Evas_Object *obj, Eina_Bool smooth)
162{
163 ELM_CHECK_WIDTYPE(obj, widtype);
164 Widget_Data *wd = elm_widget_data_get(obj);
165
166 if (!wd) return;
167 wd->smooth = smooth;
168 _sizing_eval(obj);
169}
170
171EAPI Eina_Bool
172elm_image_smooth_get(const Evas_Object *obj)
173{
174 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
175 Widget_Data *wd = elm_widget_data_get(obj);
176
177 if (!wd) return EINA_FALSE;
178 return wd->smooth;
179}
180
181EAPI void
182elm_image_object_size_get(const Evas_Object *obj, int *w, int *h)
183{
184 if (w) *w = 0;
185 if (h) *h = 0;
186 ELM_CHECK_WIDTYPE(obj, widtype);
187 Widget_Data *wd = elm_widget_data_get(obj);
188
189 if (!wd) return;
190 _els_smart_icon_size_get(wd->img, w, h);
191}
192
193EAPI void
194elm_image_no_scale_set(Evas_Object *obj, Eina_Bool no_scale)
195{
196 ELM_CHECK_WIDTYPE(obj, widtype);
197 Widget_Data *wd = elm_widget_data_get(obj);
198
199 if (!wd) return;
200 wd->no_scale = no_scale;
201 _sizing_eval(obj);
202
203}
204
205EAPI Eina_Bool
206elm_image_no_scale_get(const Evas_Object *obj)
207{
208 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
209 Widget_Data *wd = elm_widget_data_get(obj);
210 if (!wd) return EINA_FALSE;
211 return wd->no_scale;
212}
213
214EAPI void
215elm_image_resizable_set(Evas_Object *obj, Eina_Bool size_up, Eina_Bool size_down)
216{
217 ELM_CHECK_WIDTYPE(obj, widtype);
218 Widget_Data *wd = elm_widget_data_get(obj);
219
220 if (!wd) return;
221 wd->scale_up = size_up;
222 wd->scale_down = size_down;
223 _sizing_eval(obj);
224}
225
226EAPI void
227elm_image_resizable_get(const Evas_Object *obj, Eina_Bool *size_up, Eina_Bool *size_down)
228{
229 ELM_CHECK_WIDTYPE(obj, widtype);
230 Widget_Data *wd = elm_widget_data_get(obj);
231 if (!wd) return;
232 if (size_up) *size_up = wd->scale_up;
233 if (size_down) *size_down = wd->scale_down;
234}
235
236EAPI void
237elm_image_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside)
238{
239 ELM_CHECK_WIDTYPE(obj, widtype);
240 Widget_Data *wd = elm_widget_data_get(obj);
241
242 if (!wd) return;
243 wd->fill_outside = fill_outside;
244 _sizing_eval(obj);
245}
246
247EAPI Eina_Bool
248elm_image_fill_outside_get(const Evas_Object *obj)
249{
250 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
251 Widget_Data *wd = elm_widget_data_get(obj);
252
253 if (!wd) return EINA_FALSE;
254 return wd->fill_outside;
255}
256
257EAPI void
258elm_image_preload_disabled_set(Evas_Object *obj, Eina_Bool disabled)
259{
260 ELM_CHECK_WIDTYPE(obj, widtype);
261 Widget_Data *wd = elm_widget_data_get(obj);
262
263 if (!wd) return;
264 _els_smart_icon_preload_set(wd->img, !!disabled);
265}
266
267EAPI void
268elm_image_prescale_set(Evas_Object *obj, int size)
269{
270 ELM_CHECK_WIDTYPE(obj, widtype);
271 Widget_Data *wd = elm_widget_data_get(obj);
272
273 if (!wd) return;
274 _els_smart_icon_scale_size_set(wd->img, size);
275}
276
277EAPI int
278elm_image_prescale_get(const Evas_Object *obj)
279{
280 ELM_CHECK_WIDTYPE(obj, widtype) 0;
281 Widget_Data *wd = elm_widget_data_get(obj);
282
283 if (!wd) return 0;
284 return _els_smart_icon_scale_size_get(wd->img);
285}
286
287EAPI void
288elm_image_orient_set(Evas_Object *obj, Elm_Image_Orient orient)
289{
290 ELM_CHECK_WIDTYPE(obj, widtype);
291 Widget_Data *wd = elm_widget_data_get(obj);
292
293 if (!wd) return;
294 _els_smart_icon_orient_set(wd->img, orient);
295}
296
297EAPI Elm_Image_Orient
298elm_image_orient_get(const Evas_Object *obj)
299{
300 ELM_CHECK_WIDTYPE(obj, widtype) ELM_IMAGE_ORIENT_NONE;
301 Widget_Data *wd = elm_widget_data_get(obj);
302 if (!wd) return ELM_IMAGE_ORIENT_NONE;
303 return _els_smart_icon_orient_get(wd->img);
304}
305
306EAPI void
307elm_image_editable_set(Evas_Object *obj, Eina_Bool set)
308{
309 ELM_CHECK_WIDTYPE(obj, widtype);
310 Widget_Data *wd = elm_widget_data_get(obj);
311
312 if (!wd) return;
313 _els_smart_icon_edit_set(wd->img, set, obj);
314}
315
316EAPI Eina_Bool
317elm_image_editable_get(const Evas_Object *obj)
318{
319 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
320 Widget_Data *wd = elm_widget_data_get(obj);
321 if (!wd) return EINA_FALSE;
322 return _els_smart_icon_edit_get(wd->img);
323}
324
325EAPI Evas_Object *
326elm_image_object_get(const Evas_Object *obj)
327{
328 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
329 Widget_Data *wd = elm_widget_data_get(obj);
330 if (!wd) return NULL;
331 return _els_smart_icon_object_get(wd->img);
332}
333
334EAPI void
335elm_image_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed)
336{
337 ELM_CHECK_WIDTYPE(obj, widtype);
338 Widget_Data *wd = elm_widget_data_get(obj);
339 if (!wd) return;
340 _els_smart_icon_aspect_fixed_set(wd->img, fixed);
341}
342
343EAPI Eina_Bool
344elm_image_aspect_fixed_get(const Evas_Object *obj)
345{
346 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
347 Widget_Data *wd = elm_widget_data_get(obj);
348 if (!wd) return EINA_FALSE;
349 return _els_smart_icon_aspect_fixed_get(wd->img);
350}
351
352/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/elm_image.h b/libraries/elementary/src/lib/elm_image.h
new file mode 100644
index 0000000..59a904f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_image.h
@@ -0,0 +1,390 @@
1/**
2 * @defgroup Image Image
3 * @ingroup Elementary
4 *
5 * @image html img/widget/image/preview-00.png
6 * @image latex img/widget/image/preview-00.eps
7
8 *
9 * An object that allows one to load an image file to it. It can be used
10 * anywhere like any other elementary widget.
11 *
12 * This widget provides most of the functionality provided from @ref Bg or @ref
13 * Icon, but with a slightly different API (use the one that fits better your
14 * needs).
15 *
16 * The features not provided by those two other image widgets are:
17 * @li allowing to get the basic @c Evas_Object with elm_image_object_get();
18 * @li change the object orientation with elm_image_orient_set();
19 * @li and turning the image editable with elm_image_editable_set().
20 *
21 * Signals that you can add callbacks for are:
22 *
23 * @li @c "clicked" - This is called when a user has clicked the image
24 *
25 * An example of usage for this API follows:
26 * @li @ref tutorial_image
27 */
28
29/**
30 * @addtogroup Image
31 * @{
32 */
33
34/**
35 * Possible orientation options for elm_image_orient_set().
36 *
37 * @image html elm_image_orient_set.png
38 * @image latex elm_image_orient_set.eps width=\textwidth
39 *
40 * @ingroup Image
41 */
42typedef enum
43{
44 ELM_IMAGE_ORIENT_NONE = 0, /**< no orientation change */
45 ELM_IMAGE_ORIENT_0 = 0, /**< no orientation change */
46 ELM_IMAGE_ROTATE_90 = 1, /**< rotate 90 degrees clockwise */
47 ELM_IMAGE_ROTATE_180 = 2, /**< rotate 180 degrees clockwise */
48 ELM_IMAGE_ROTATE_270 = 3, /**< rotate 90 degrees counter-clockwise (i.e. 270 degrees clockwise) */
49 ELM_IMAGE_FLIP_HORIZONTAL = 4, /**< flip image horizontally */
50 ELM_IMAGE_FLIP_VERTICAL = 5, /**< flip image vertically */
51 ELM_IMAGE_FLIP_TRANSPOSE = 6, /**< flip the image along the y = (width - x) line (bottom-left to top-right) */
52 ELM_IMAGE_FLIP_TRANSVERSE = 7 /**< flip the image along the y = x line (top-left to bottom-right) */
53} Elm_Image_Orient;
54
55/**
56 * Add a new image to the parent.
57 *
58 * @param parent The parent object
59 * @return The new object or NULL if it cannot be created
60 *
61 * @see elm_image_file_set()
62 *
63 * @ingroup Image
64 */
65EAPI Evas_Object *elm_image_add(Evas_Object *parent);
66
67/**
68 * Set the file that will be used as image.
69 *
70 * @param obj The image object
71 * @param file The path to file that will be used as image
72 * @param group The group that the image belongs in edje file (if it's an
73 * edje image)
74 *
75 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
76 *
77 * @see elm_image_file_get()
78 *
79 * @ingroup Image
80 */
81EAPI Eina_Bool elm_image_file_set(Evas_Object *obj, const char *file, const char *group);
82
83/**
84 * Get the file that will be used as image.
85 *
86 * @param obj The image object
87 * @param file The path to file
88 * @param group The group that the image belongs in edje file
89 *
90 * @see elm_image_file_set()
91 *
92 * @ingroup Image
93 */
94EAPI void elm_image_file_get(const Evas_Object *obj, const char **file, const char **group);
95
96/**
97 * Set the smooth effect for an image.
98 *
99 * @param obj The image object
100 * @param smooth @c EINA_TRUE if smooth scaling should be used, @c EINA_FALSE
101 * otherwise. Default is @c EINA_TRUE.
102 *
103 * Set the scaling algorithm to be used when scaling the image. Smooth
104 * scaling provides a better resulting image, but is slower.
105 *
106 * The smooth scaling should be disabled when making animations that change
107 * the image size, since it will be faster. Animations that don't require
108 * resizing of the image can keep the smooth scaling enabled (even if the
109 * image is already scaled, since the scaled image will be cached).
110 *
111 * @see elm_image_smooth_get()
112 *
113 * @ingroup Image
114 */
115EAPI void elm_image_smooth_set(Evas_Object *obj, Eina_Bool smooth);
116
117/**
118 * Get the smooth effect for an image.
119 *
120 * @param obj The image object
121 * @return @c EINA_TRUE if smooth scaling is enabled, @c EINA_FALSE otherwise.
122 *
123 * @see elm_image_smooth_get()
124 *
125 * @ingroup Image
126 */
127EAPI Eina_Bool elm_image_smooth_get(const Evas_Object *obj);
128
129/**
130 * Gets the current size of the image.
131 *
132 * @param obj The image object.
133 * @param w Pointer to store width, or NULL.
134 * @param h Pointer to store height, or NULL.
135 *
136 * This is the real size of the image, not the size of the object.
137 *
138 * @ingroup Image
139 */
140EAPI void elm_image_object_size_get(const Evas_Object *obj, int *w, int *h);
141
142/**
143 * Disable scaling of this object.
144 *
145 * @param obj The image object.
146 * @param no_scale @c EINA_TRUE if the object is not scalable, @c EINA_FALSE
147 * otherwise. Default is @c EINA_FALSE.
148 *
149 * This function disables scaling of the elm_image widget through the
150 * function elm_object_scale_set(). However, this does not affect the widget
151 * size/resize in any way. For that effect, take a look at
152 * elm_image_resizable_set().
153 *
154 * @see elm_image_no_scale_get()
155 * @see elm_image_resizable_set()
156 * @see elm_object_scale_set()
157 *
158 * @ingroup Image
159 */
160EAPI void elm_image_no_scale_set(Evas_Object *obj, Eina_Bool no_scale);
161
162/**
163 * Get whether scaling is disabled on the object.
164 *
165 * @param obj The image object
166 * @return @c EINA_TRUE if scaling is disabled, @c EINA_FALSE otherwise
167 *
168 * @see elm_image_no_scale_set()
169 *
170 * @ingroup Image
171 */
172EAPI Eina_Bool elm_image_no_scale_get(const Evas_Object *obj);
173
174/**
175 * Set if the object is (up/down) resizable.
176 *
177 * @param obj The image object
178 * @param size_up A bool to set if the object is resizable up. Default is
179 * @c EINA_TRUE.
180 * @param size_down A bool to set if the object is resizable down. Default
181 * is @c EINA_TRUE.
182 *
183 * This function limits the image resize ability. If @p size_up is set to
184 * @c EINA_FALSE, the object can't have its height or width resized to a value
185 * higher than the original image size. Same is valid for @p size_down.
186 *
187 * @see elm_image_resizable_get()
188 *
189 * @ingroup Image
190 */
191EAPI void elm_image_resizable_set(Evas_Object *obj, Eina_Bool size_up, Eina_Bool size_down);
192
193/**
194 * Get if the object is (up/down) resizable.
195 *
196 * @param obj The image object
197 * @param size_up A bool to set if the object is resizable up
198 * @param size_down A bool to set if the object is resizable down
199 *
200 * @see elm_image_resizable_set()
201 *
202 * @ingroup Image
203 */
204EAPI void elm_image_resizable_get(const Evas_Object *obj, Eina_Bool *size_up, Eina_Bool *size_down);
205
206/**
207 * Set if the image fills the entire object area, when keeping the aspect ratio.
208 *
209 * @param obj The image object
210 * @param fill_outside @c EINA_TRUE if the object is filled outside,
211 * @c EINA_FALSE otherwise. Default is @c EINA_FALSE.
212 *
213 * When the image should keep its aspect ratio even if resized to another
214 * aspect ratio, there are two possibilities to resize it: keep the entire
215 * image inside the limits of height and width of the object (@p fill_outside
216 * is @c EINA_FALSE) or let the extra width or height go outside of the object,
217 * and the image will fill the entire object (@p fill_outside is @c EINA_TRUE).
218 *
219 * @note This option will have no effect if
220 * elm_image_aspect_fixed_set() is set to @c EINA_FALSE.
221 *
222 * @see elm_image_fill_outside_get()
223 * @see elm_image_aspect_fixed_set()
224 *
225 * @ingroup Image
226 */
227EAPI void elm_image_fill_outside_set(Evas_Object *obj, Eina_Bool fill_outside);
228
229/**
230 * Get if the object is filled outside
231 *
232 * @param obj The image object
233 * @return @c EINA_TRUE if the object is filled outside, @c EINA_FALSE otherwise.
234 *
235 * @see elm_image_fill_outside_set()
236 *
237 * @ingroup Image
238 */
239EAPI Eina_Bool elm_image_fill_outside_get(const Evas_Object *obj);
240
241/**
242 * Enable or disable preloading of the image
243 *
244 * @param obj The image object
245 * @param disabled If EINA_TRUE, preloading will be disabled
246 * @ingroup Icon
247 */
248EAPI void elm_image_preload_disabled_set(Evas_Object *obj, Eina_Bool disabled);
249
250/**
251 * Set the prescale size for the image
252 *
253 * @param obj The image object
254 * @param size The prescale size. This value is used for both width and
255 * height.
256 *
257 * This function sets a new size for pixmap representation of the given
258 * image. It allows the image to be loaded already in the specified size,
259 * reducing the memory usage and load time when loading a big image with load
260 * size set to a smaller size.
261 *
262 * It's equivalent to the elm_bg_load_size_set() function for bg.
263 *
264 * @note this is just a hint, the real size of the pixmap may differ
265 * depending on the type of image being loaded, being bigger than requested.
266 *
267 * @see elm_image_prescale_get()
268 * @see elm_bg_load_size_set()
269 *
270 * @ingroup Image
271 */
272EAPI void elm_image_prescale_set(Evas_Object *obj, int size);
273
274/**
275 * Get the prescale size for the image
276 *
277 * @param obj The image object
278 * @return The prescale size
279 *
280 * @see elm_image_prescale_set()
281 *
282 * @ingroup Image
283 */
284EAPI int elm_image_prescale_get(const Evas_Object *obj);
285
286/**
287 * Set the image orientation.
288 *
289 * @param obj The image object
290 * @param orient The image orientation @ref Elm_Image_Orient
291 * Default is #ELM_IMAGE_ORIENT_NONE.
292 *
293 * This function allows to rotate or flip the given image.
294 *
295 * @see elm_image_orient_get()
296 * @see @ref Elm_Image_Orient
297 *
298 * @ingroup Image
299 */
300EAPI void elm_image_orient_set(Evas_Object *obj, Elm_Image_Orient orient);
301
302/**
303 * Get the image orientation.
304 *
305 * @param obj The image object
306 * @return The image orientation @ref Elm_Image_Orient
307 *
308 * @see elm_image_orient_set()
309 * @see @ref Elm_Image_Orient
310 *
311 * @ingroup Image
312 */
313EAPI Elm_Image_Orient elm_image_orient_get(const Evas_Object *obj);
314
315/**
316 * Make the image 'editable'.
317 *
318 * @param obj Image object.
319 * @param set Turn on or off editability. Default is @c EINA_FALSE.
320 *
321 * This means the image is a valid drag target for drag and drop, and can be
322 * cut or pasted too.
323 *
324 * @ingroup Image
325 */
326EAPI void elm_image_editable_set(Evas_Object *obj, Eina_Bool set);
327
328/**
329 * Check if the image is 'editable'.
330 *
331 * @param obj Image object.
332 * @return Editability.
333 *
334 * A return value of EINA_TRUE means the image is a valid drag target
335 * for drag and drop, and can be cut or pasted too.
336 *
337 * @ingroup Image
338 */
339EAPI Eina_Bool elm_image_editable_get(const Evas_Object *obj);
340
341/**
342 * Get the inlined image object of the image widget.
343 *
344 * @param obj The image object to get the inlined image from
345 * @return The inlined image object, or NULL if none exists
346 *
347 * This function allows one to get the underlying @c Evas_Object of type
348 * Image from this elementary widget. It can be useful to do things like get
349 * the pixel data, save the image to a file, etc.
350 *
351 * @note Be careful to not manipulate it, as it is under control of
352 * elementary.
353 *
354 * @ingroup Image
355 */
356EAPI Evas_Object *elm_image_object_get(const Evas_Object *obj);
357
358/**
359 * Set whether the original aspect ratio of the image should be kept on resize.
360 *
361 * @param obj The image object.
362 * @param fixed @c EINA_TRUE if the image should retain the aspect,
363 * @c EINA_FALSE otherwise.
364 *
365 * The original aspect ratio (width / height) of the image is usually
366 * distorted to match the object's size. Enabling this option will retain
367 * this original aspect, and the way that the image is fit into the object's
368 * area depends on the option set by elm_image_fill_outside_set().
369 *
370 * @see elm_image_aspect_fixed_get()
371 * @see elm_image_fill_outside_set()
372 *
373 * @ingroup Image
374 */
375EAPI void elm_image_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed);
376
377/**
378 * Get if the object retains the original aspect ratio.
379 *
380 * @param obj The image object.
381 * @return @c EINA_TRUE if the object keeps the original aspect, @c EINA_FALSE
382 * otherwise.
383 *
384 * @ingroup Image
385 */
386EAPI Eina_Bool elm_image_aspect_fixed_get(const Evas_Object *obj);
387
388/**
389 * @}
390 */
diff --git a/libraries/elementary/src/lib/elm_index.c b/libraries/elementary/src/lib/elm_index.c
new file mode 100644
index 0000000..985b181
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_index.c
@@ -0,0 +1,932 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_box.h"
4
5typedef struct _Widget_Data Widget_Data;
6typedef struct _Elm_Index_Item Elm_Index_Item;
7
8struct _Widget_Data
9{
10 Evas_Object *base;
11 Evas_Object *event[2];
12 Evas_Object *bx[2]; // 2 - for now all that's supported
13 Eina_List *items; // 1 list. yes N levels, but only 2 for now and # of items will be small
14 int level;
15 Evas_Coord dx, dy;
16 Ecore_Timer *delay;
17 Eina_Bool level_active[2];
18 Eina_Bool horizontal : 1;
19 Eina_Bool autohide_disabled : 1;
20 Eina_Bool down : 1;
21 Eina_Bool indicator_disabled : 1;
22};
23
24struct _Elm_Index_Item
25{
26 ELM_WIDGET_ITEM;
27 const char *letter;
28 int level;
29 Evas_Smart_Cb func;
30 Eina_Bool selected : 1;
31};
32
33static const char *widtype = NULL;
34
35static void _del_hook(Evas_Object *obj);
36static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
37static void _theme_hook(Evas_Object *obj);
38static void _sizing_eval(Evas_Object *obj);
39static void _index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level);
40static void _index_box_clear(Evas_Object *obj, Evas_Object *box, int level);
41static void _item_free(Elm_Index_Item *it);
42
43static const char SIG_CHANGED[] = "changed";
44static const char SIG_DELAY_CHANGED[] = "delay,changed";
45static const char SIG_SELECTED[] = "selected";
46static const char SIG_LEVEL_UP[] = "level,up";
47static const char SIG_LEVEL_DOWN[] = "level,down";
48
49static const Evas_Smart_Cb_Description _signals[] = {
50 {SIG_CHANGED, ""},
51 {SIG_DELAY_CHANGED, ""},
52 {SIG_SELECTED, ""},
53 {SIG_LEVEL_UP, ""},
54 {SIG_LEVEL_DOWN, ""},
55 {NULL, NULL}
56};
57
58static void
59_del_pre_hook(Evas_Object *obj)
60{
61 Widget_Data *wd = elm_widget_data_get(obj);
62 Elm_Index_Item *it;
63 if (!wd) return;
64 _index_box_clear(obj, wd->bx[wd->level], wd->level);
65 _index_box_clear(obj, wd->bx[0], 0);
66 while (wd->items)
67 {
68 it = wd->items->data;
69 _item_free(it);
70 elm_widget_item_free(it);
71 }
72 if (wd->delay) ecore_timer_del(wd->delay);
73}
74
75static void
76_del_hook(Evas_Object *obj)
77{
78 Widget_Data *wd = elm_widget_data_get(obj);
79 free(wd);
80}
81
82static void
83_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
84{
85 Widget_Data *wd = data;
86 if (!wd) return;
87 _els_box_layout(o, priv, wd->horizontal, 1, 0);
88}
89
90static void
91_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
92{
93 Widget_Data *wd = elm_widget_data_get(obj);
94 if (!wd) return;
95 edje_object_signal_emit(wd->base, emission, source);
96}
97
98static void
99_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
100{
101 Widget_Data *wd = elm_widget_data_get(obj);
102 if (!wd) return;
103 edje_object_signal_callback_add(wd->base, emission, source, func_cb, data);
104}
105
106static void
107_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
108{
109 Widget_Data *wd = elm_widget_data_get(obj);
110 edje_object_signal_callback_del_full(wd->base, emission, source, func_cb,
111 data);
112}
113
114static void
115_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
116{
117 Widget_Data *wd = elm_widget_data_get(obj);
118 if (!wd) return;
119 if (!wd->horizontal)
120 edje_object_mirrored_set(wd->base, rtl);
121}
122
123static void
124_theme_hook(Evas_Object *obj)
125{
126 Evas_Coord minw = 0, minh = 0;
127 Widget_Data *wd = elm_widget_data_get(obj);
128 if (!wd) return;
129 _elm_widget_mirrored_reload(obj);
130
131 _index_box_clear(obj, wd->bx[0], 0);
132 _index_box_clear(obj, wd->bx[1], 1);
133 if (wd->horizontal)
134 _elm_theme_object_set(obj, wd->base, "index", "base/horizontal", elm_widget_style_get(obj));
135 else
136 {
137 _elm_theme_object_set(obj, wd->base, "index", "base/vertical", elm_widget_style_get(obj));
138 _mirrored_set(obj, elm_widget_mirrored_get(obj));
139 }
140 edje_object_part_swallow(wd->base, "elm.swallow.event.0", wd->event[0]);
141 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
142 evas_object_size_hint_min_set(wd->event[0], minw, minh);
143 edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
144 if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
145 {
146 if (!wd->bx[1])
147 {
148 wd->bx[1] = evas_object_box_add(evas_object_evas_get(wd->base));
149 evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
150 elm_widget_sub_object_add(obj, wd->bx[1]);
151 }
152 edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
153 evas_object_show(wd->bx[1]);
154 }
155 else if (wd->bx[1])
156 {
157 evas_object_del(wd->bx[1]);
158 wd->bx[1] = NULL;
159 }
160 if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
161 {
162 if (!wd->event[1])
163 {
164 wd->event[1] = evas_object_rectangle_add(evas_object_evas_get(wd->base));
165 evas_object_color_set(wd->event[1], 0, 0, 0, 0);
166 elm_widget_sub_object_add(obj, wd->event[1]);
167 }
168 edje_object_part_swallow(wd->base, "elm.swallow.event.1", wd->event[1]);
169 evas_object_size_hint_min_set(wd->event[1], minw, minh);
170 }
171 else if (wd->event[1])
172 {
173 evas_object_del(wd->event[1]);
174 wd->event[1] = NULL;
175 }
176 edje_object_message_signal_process(wd->base);
177 edje_object_scale_set(wd->base, elm_widget_scale_get(obj) * _elm_config->scale);
178 _sizing_eval(obj);
179 _index_box_auto_fill(obj, wd->bx[0], 0);
180
181 if (wd->autohide_disabled)
182 {
183 if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
184 edje_object_signal_emit(wd->base, "elm,state,active", "elm");
185 }
186 else
187 edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
188}
189
190static void
191_sizing_eval(Evas_Object *obj)
192{
193 Widget_Data *wd = elm_widget_data_get(obj);
194 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
195 if (!wd) return;
196 edje_object_size_min_calc(wd->base, &minw, &minh);
197 evas_object_size_hint_min_set(obj, minw, minh);
198 evas_object_size_hint_max_set(obj, maxw, maxh);
199}
200
201static Eina_Bool
202_item_del_pre_hook(Elm_Object_Item *it)
203{
204 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
205 if (!wd) return EINA_FALSE;
206 _item_free((Elm_Index_Item *)it);
207 _index_box_clear(WIDGET(it), wd->bx[wd->level], wd->level);
208 return EINA_TRUE;
209}
210
211static Elm_Index_Item *
212_item_new(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data)
213{
214 Widget_Data *wd = elm_widget_data_get(obj);
215 Elm_Index_Item *it;
216 if (!wd) return NULL;
217 it = elm_widget_item_new(obj, Elm_Index_Item);
218 if (!it) return NULL;
219 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
220 if (letter) it->letter = eina_stringshare_add(letter);
221 it->func = func;
222 it->base.data = data;
223 it->level = wd->level;
224 return it;
225}
226
227static Elm_Index_Item *
228_item_find(Evas_Object *obj, const void *data)
229{
230 Widget_Data *wd = elm_widget_data_get(obj);
231 Eina_List *l;
232 Elm_Index_Item *it;
233 if (!wd) return NULL;
234 EINA_LIST_FOREACH(wd->items, l, it)
235 if (it->base.data == data) return it;
236 return NULL;
237}
238
239static void
240_item_free(Elm_Index_Item *it)
241{
242 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
243 if (!wd) return;
244 wd->items = eina_list_remove(wd->items, it);
245 if (it->letter) eina_stringshare_del(it->letter);
246}
247
248// FIXME: always have index filled
249static void
250_index_box_auto_fill(Evas_Object *obj, Evas_Object *box, int level)
251{
252 Widget_Data *wd = elm_widget_data_get(obj);
253 Eina_Bool rtl;
254 Eina_List *l;
255 Elm_Index_Item *it;
256 Evas_Coord mw, mh, w, h;
257 int i = 0;
258 if (!wd) return;
259 if (wd->level_active[level]) return;
260 rtl = elm_widget_mirrored_get(obj);
261 evas_object_geometry_get(box, NULL, NULL, &w, &h);
262 EINA_LIST_FOREACH(wd->items, l, it)
263 {
264 Evas_Object *o;
265 const char *stacking;
266
267 if (it->level != level) continue;
268 o = edje_object_add(evas_object_evas_get(obj));
269 VIEW(it) = o;
270 edje_object_mirrored_set(VIEW(it), rtl);
271
272 if (wd->horizontal)
273 {
274 if (i & 0x1)
275 _elm_theme_object_set(obj, o, "index", "item_odd/horizontal",
276 elm_widget_style_get(obj));
277 else
278 _elm_theme_object_set(obj, o, "index", "item/horizontal",
279 elm_widget_style_get(obj));
280 }
281 else
282 {
283 if (i & 0x1)
284 _elm_theme_object_set(obj, o, "index", "item_odd/vertical",
285 elm_widget_style_get(obj));
286 else
287 _elm_theme_object_set(obj, o, "index", "item/vertical",
288 elm_widget_style_get(obj));
289 }
290
291 edje_object_part_text_escaped_set(o, "elm.text", it->letter);
292 edje_object_size_min_restricted_calc(o, &mw, &mh, 0, 0);
293 evas_object_size_hint_min_set(o, mw, mh);
294 evas_object_size_hint_weight_set(o, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
295 evas_object_size_hint_align_set(o, EVAS_HINT_FILL, EVAS_HINT_FILL);
296 elm_widget_sub_object_add(obj, o);
297 evas_object_box_append(box, o);
298 stacking = edje_object_data_get(o, "stacking");
299 if (stacking)
300 {
301 if (!strcmp(stacking, "below")) evas_object_lower(o);
302 else if (!strcmp(stacking, "above")) evas_object_raise(o);
303 }
304 evas_object_show(o);
305 i++;
306 evas_object_smart_calculate(box); // force a calc so we know the size
307 evas_object_size_hint_min_get(box, &mw, &mh);
308 if (mh > h)
309 {
310 _index_box_clear(obj, box, level);
311 if (i > 0)
312 {
313 // FIXME: only i objects fit! try again. overflows right now
314 }
315 }
316 }
317 evas_object_smart_calculate(box);
318 wd->level_active[level] = 1;
319}
320
321static void
322_index_box_clear(Evas_Object *obj, Evas_Object *box __UNUSED__, int level)
323{
324 Widget_Data *wd = elm_widget_data_get(obj);
325 Eina_List *l;
326 Elm_Index_Item *it;
327 if (!wd) return;
328 if (!wd->level_active[level]) return;
329 EINA_LIST_FOREACH(wd->items, l, it)
330 {
331 if (!VIEW(it)) continue;
332 if (it->level != level) continue;
333 evas_object_del(VIEW(it));
334 VIEW(it) = NULL;
335 }
336 wd->level_active[level] = 0;
337}
338
339static Eina_Bool
340_delay_change(void *data)
341{
342 Widget_Data *wd = elm_widget_data_get(data);
343 Elm_Object_Item *item;
344 if (!wd) return ECORE_CALLBACK_CANCEL;
345 wd->delay = NULL;
346 item = elm_index_selected_item_get(data, wd->level);
347 if (item) evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, item);
348 return ECORE_CALLBACK_CANCEL;
349}
350
351static void
352_sel_eval(Evas_Object *obj, Evas_Coord evx, Evas_Coord evy)
353{
354 Widget_Data *wd = elm_widget_data_get(obj);
355 Elm_Index_Item *it, *it_closest, *it_last;
356 Eina_List *l;
357 Evas_Coord x, y, w, h, bx, by, bw, bh, xx, yy;
358 double cdv = 0.5;
359 Evas_Coord dist;
360 char *label = NULL, *last = NULL;
361 int i;
362 if (!wd) return;
363 for (i = 0; i <= wd->level; i++)
364 {
365 it_last = NULL;
366 it_closest = NULL;
367 dist = 0x7fffffff;
368 evas_object_geometry_get(wd->bx[i], &bx, &by, &bw, &bh);
369 EINA_LIST_FOREACH(wd->items, l, it)
370 {
371 if (it->level != i) continue;
372 if (it->level != wd->level)
373 {
374 if (it->selected)
375 {
376 it_closest = it;
377 break;
378 }
379 continue;
380 }
381 if (it->selected)
382 {
383 it_last = it;
384 it->selected = 0;
385 }
386 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
387 xx = x + (w / 2);
388 yy = y + (h / 2);
389 x = evx - xx;
390 y = evy - yy;
391 x = (x * x) + (y * y);
392 if ((x < dist) || (!it_closest))
393 {
394 if (wd->horizontal)
395 cdv = (double)(xx - bx) / (double)bw;
396 else
397 cdv = (double)(yy - by) / (double)bh;
398 it_closest = it;
399 dist = x;
400 }
401 }
402 if ((i == 0) && (wd->level == 0))
403 edje_object_part_drag_value_set(wd->base, "elm.dragable.index.1",
404 cdv, cdv);
405 if (it_closest) it_closest->selected = 1;
406 if (it_closest != it_last)
407 {
408 if (it_last)
409 {
410 const char *stacking, *selectraise;
411
412 it = it_last;
413 edje_object_signal_emit(VIEW(it), "elm,state,inactive", "elm");
414 stacking = edje_object_data_get(VIEW(it), "stacking");
415 selectraise = edje_object_data_get(VIEW(it), "selectraise");
416 if ((selectraise) && (!strcmp(selectraise, "on")))
417 {
418 if ((stacking) && (!strcmp(stacking, "below")))
419 evas_object_lower(VIEW(it));
420 }
421 }
422 if (it_closest)
423 {
424 const char *selectraise;
425
426 it = it_closest;
427 edje_object_signal_emit(VIEW(it), "elm,state,active", "elm");
428 selectraise = edje_object_data_get(VIEW(it), "selectraise");
429 if ((selectraise) && (!strcmp(selectraise, "on")))
430 evas_object_raise(VIEW(it));
431 evas_object_smart_callback_call((void *)obj, SIG_CHANGED, (void *)it);
432 if (wd->delay) ecore_timer_del(wd->delay);
433 wd->delay = ecore_timer_add(0.2, _delay_change, obj);
434 }
435 }
436 if (it_closest)
437 {
438 it = it_closest;
439 if (!last && it->letter)
440 last = strdup(it->letter);
441 else
442 {
443 if (!label && last) label = strdup(last);
444 else
445 {
446 if (label && last)
447 {
448 label = realloc(label, strlen(label) +
449 strlen(last) + 1);
450 if (!label) return;
451 strcat(label, last);
452 }
453 }
454 free(last);
455 if (it->letter) last = strdup(it->letter);
456 }
457 }
458 }
459 if (!label) label = strdup("");
460 if (!last) last = strdup("");
461 edje_object_part_text_escaped_set(wd->base, "elm.text.body", label);
462 edje_object_part_text_escaped_set(wd->base, "elm.text", last);
463 free(label);
464 free(last);
465}
466
467static void
468_wheel(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
469{
470 Widget_Data *wd = elm_widget_data_get(data);
471 // Evas_Event_Mouse_Wheel *ev = event_info;
472 // Evas_Object *obj = o;
473 if (!wd) return;
474}
475
476static void
477_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
478{
479 Widget_Data *wd = elm_widget_data_get(data);
480 Evas_Event_Mouse_Down *ev = event_info;
481 Evas_Coord x, y, w;
482 if (!wd) return;
483 if (ev->button != 1) return;
484 wd->down = 1;
485 evas_object_geometry_get(wd->base, &x, &y, &w, NULL);
486 wd->dx = ev->canvas.x - x;
487 wd->dy = ev->canvas.y - y;
488 if (!wd->autohide_disabled)
489 {
490 _index_box_clear(data, wd->bx[1], 1);
491 _index_box_auto_fill(data, wd->bx[0], 0);
492 edje_object_signal_emit(wd->base, "elm,state,active", "elm");
493 }
494 _sel_eval(data, ev->canvas.x, ev->canvas.y);
495 edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer",
496 (!edje_object_mirrored_get(wd->base)) ? wd->dx : (wd->dx - w), wd->dy);
497 if (wd->items && !wd->indicator_disabled)
498 edje_object_signal_emit(wd->base, "elm,indicator,state,active", "elm");
499}
500
501static void
502_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
503{
504 Widget_Data *wd = elm_widget_data_get(data);
505 Evas_Event_Mouse_Up *ev = event_info;
506 Elm_Object_Item *item;
507 Elm_Index_Item *id_item;
508 if (!wd) return;
509 if (ev->button != 1) return;
510 wd->down = 0;
511 item = elm_index_selected_item_get(data, wd->level);
512 if (item)
513 {
514 evas_object_smart_callback_call(data, SIG_SELECTED, item);
515 id_item = (Elm_Index_Item *)item;
516 if (id_item->func)
517 id_item->func((void *)id_item->base.data, WIDGET(id_item), id_item);
518 }
519 if (!wd->autohide_disabled)
520 edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
521 edje_object_signal_emit(wd->base, "elm,state,level,0", "elm");
522 if (wd->items && !wd->indicator_disabled)
523 edje_object_signal_emit(wd->base, "elm,indicator,state,inactive", "elm");
524}
525
526static void
527_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info)
528{
529 Widget_Data *wd = elm_widget_data_get(data);
530 Evas_Event_Mouse_Move *ev = event_info;
531 Evas_Coord minw = 0, minh = 0, x, y, dx, adx, w;
532 char buf[1024];
533 if (!wd) return;
534 if (!wd->down) return;
535 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
536 evas_object_geometry_get(wd->base, &x, &y, &w, NULL);
537 x = ev->cur.canvas.x - x;
538 y = ev->cur.canvas.y - y;
539 dx = x - wd->dx;
540 adx = dx;
541 if (adx < 0) adx = -dx;
542 edje_object_part_drag_value_set(wd->base, "elm.dragable.pointer"
543 , (!edje_object_mirrored_get(wd->base)) ? x : (x - w), y);
544 if (!wd->horizontal)
545 {
546 if (adx > minw)
547 {
548 if (!wd->level)
549 {
550 wd->level = 1;
551 snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
552 edje_object_signal_emit(wd->base, buf, "elm");
553 evas_object_smart_callback_call(data, SIG_LEVEL_UP, NULL);
554 }
555 }
556 else
557 {
558 if (wd->level == 1)
559 {
560 wd->level = 0;
561 snprintf(buf, sizeof(buf), "elm,state,level,%i", wd->level);
562 edje_object_signal_emit(wd->base, buf, "elm");
563 evas_object_smart_callback_call(data, SIG_LEVEL_DOWN, NULL);
564 }
565 }
566 }
567 _sel_eval(data, ev->cur.canvas.x, ev->cur.canvas.y);
568}
569
570EAPI Evas_Object *
571elm_index_add(Evas_Object *parent)
572{
573 Evas_Object *obj;
574 Evas_Object *o;
575 Evas *e;
576 Widget_Data *wd;
577 Evas_Coord minw, minh;
578
579 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
580
581 ELM_SET_WIDTYPE(widtype, "index");
582 elm_widget_type_set(obj, "index");
583 elm_widget_sub_object_add(parent, obj);
584 elm_widget_data_set(obj, wd);
585 elm_widget_del_hook_set(obj, _del_hook);
586 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
587 elm_widget_theme_hook_set(obj, _theme_hook);
588 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
589 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
590 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
591 elm_widget_can_focus_set(obj, EINA_FALSE);
592
593 wd->indicator_disabled = EINA_FALSE;
594 wd->horizontal = EINA_FALSE;
595 wd->autohide_disabled = EINA_FALSE;
596
597 wd->base = edje_object_add(e);
598 _elm_theme_object_set(obj, wd->base, "index", "base/vertical", "default");
599 elm_widget_resize_object_set(obj, wd->base);
600
601 o = evas_object_rectangle_add(e);
602 wd->event[0] = o;
603 evas_object_color_set(o, 0, 0, 0, 0);
604 minw = minh = 0;
605 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
606 evas_object_size_hint_min_set(o, minw, minh);
607 edje_object_part_swallow(wd->base, "elm.swallow.event.0", o);
608 elm_widget_sub_object_add(obj, o);
609 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _wheel, obj);
610 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, obj);
611 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _mouse_up, obj);
612 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, obj);
613 evas_object_show(o);
614 if (edje_object_part_exists(wd->base, "elm.swallow.event.1"))
615 {
616 o = evas_object_rectangle_add(e);
617 wd->event[1] = o;
618 evas_object_color_set(o, 0, 0, 0, 0);
619 evas_object_size_hint_min_set(o, minw, minh);
620 edje_object_part_swallow(wd->base, "elm.swallow.event.1", o);
621 elm_widget_sub_object_add(obj, o);
622 }
623
624 wd->bx[0] = evas_object_box_add(e);
625 evas_object_box_layout_set(wd->bx[0], _layout, wd, NULL);
626 elm_widget_sub_object_add(obj, wd->bx[0]);
627 edje_object_part_swallow(wd->base, "elm.swallow.index.0", wd->bx[0]);
628 evas_object_show(wd->bx[0]);
629
630 if (edje_object_part_exists(wd->base, "elm.swallow.index.1"))
631 {
632 wd->bx[1] = evas_object_box_add(e);
633 evas_object_box_layout_set(wd->bx[1], _layout, wd, NULL);
634 elm_widget_sub_object_add(obj, wd->bx[1]);
635 edje_object_part_swallow(wd->base, "elm.swallow.index.1", wd->bx[1]);
636 evas_object_show(wd->bx[1]);
637 }
638
639 evas_object_smart_callbacks_descriptions_set(obj, _signals);
640
641 _mirrored_set(obj, elm_widget_mirrored_get(obj));
642 _sizing_eval(obj);
643 return obj;
644}
645
646EAPI void
647elm_index_autohide_disabled_set(Evas_Object *obj, Eina_Bool disabled)
648{
649 ELM_CHECK_WIDTYPE(obj, widtype);
650 Widget_Data *wd = elm_widget_data_get(obj);
651 if (!wd) return;
652 disabled = !!disabled;
653 if (wd->autohide_disabled == disabled) return;
654 wd->autohide_disabled = disabled;
655 wd->level = 0;
656 if (wd->autohide_disabled)
657 {
658 _index_box_clear(obj, wd->bx[1], 1);
659 _index_box_auto_fill(obj, wd->bx[0], 0);
660 edje_object_signal_emit(wd->base, "elm,state,active", "elm");
661 }
662 else
663 edje_object_signal_emit(wd->base, "elm,state,inactive", "elm");
664
665 //FIXME: Should be update indicator based on the indicator visiblility
666}
667
668EAPI Eina_Bool
669elm_index_autohide_disabled_get(const Evas_Object *obj)
670{
671 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
672 Widget_Data *wd = elm_widget_data_get(obj);
673 if (!wd) return EINA_FALSE;
674 return wd->autohide_disabled;
675}
676
677EAPI void
678elm_index_item_level_set(Evas_Object *obj, int level)
679{
680 ELM_CHECK_WIDTYPE(obj, widtype);
681 Widget_Data *wd = elm_widget_data_get(obj);
682 if (!wd) return;
683 if (wd->level == level) return;
684 wd->level = level;
685}
686
687EAPI int
688elm_index_item_level_get(const Evas_Object *obj)
689{
690 ELM_CHECK_WIDTYPE(obj, widtype) 0;
691 Widget_Data *wd = elm_widget_data_get(obj);
692 if (!wd) return 0;
693 return wd->level;
694}
695
696EAPI void
697elm_index_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
698{
699 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
700 Evas_Coord x, y, w, h;
701 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
702 if (!wd) return;
703
704 //FIXME: Should be update indicator based on the autohidden status & indicator visiblility
705
706 if (selected)
707 {
708 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
709 _sel_eval(WIDGET(it), x + (w/2), y + (h/2));
710 }
711 else
712 _sel_eval(WIDGET(it), -99999, -9999);
713
714}
715
716EAPI Elm_Object_Item *
717elm_index_selected_item_get(const Evas_Object *obj, int level)
718{
719 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
720 Widget_Data *wd = elm_widget_data_get(obj);
721 Eina_List *l;
722 Elm_Index_Item *it;
723 if (!wd) return NULL;
724 EINA_LIST_FOREACH(wd->items, l, it)
725 {
726 if ((it->selected) && (it->level == level))
727 return (Elm_Object_Item *)it;
728 }
729 return NULL;
730}
731
732EAPI Elm_Object_Item *
733elm_index_item_append(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data)
734{
735 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
736 Widget_Data *wd = elm_widget_data_get(obj);
737 Elm_Index_Item *it;
738 if (!wd) return NULL;
739 it = _item_new(obj, letter, func, data);
740 if (!it) return NULL;
741 wd->items = eina_list_append(wd->items, it);
742 _index_box_clear(obj, wd->bx[wd->level], wd->level);
743 return (Elm_Object_Item *)it;
744}
745
746EAPI Elm_Object_Item *
747elm_index_item_prepend(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data)
748{
749 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
750 Widget_Data *wd = elm_widget_data_get(obj);
751 Elm_Index_Item *it;
752
753 if (!wd) return NULL;
754 it = _item_new(obj, letter, func, data);
755 if (!it) return NULL;
756 wd->items = eina_list_prepend(wd->items, it);
757 _index_box_clear(obj, wd->bx[wd->level], wd->level);
758 return (Elm_Object_Item *)it;
759}
760
761EINA_DEPRECATED EAPI Elm_Object_Item *
762elm_index_item_prepend_relative(Evas_Object *obj, const char *letter, const void *item, const Elm_Object_Item *relative)
763{
764 return elm_index_item_insert_before(obj, (Elm_Object_Item *) relative, letter, NULL, item);
765}
766
767EAPI Elm_Object_Item *
768elm_index_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *letter, Evas_Smart_Cb func, const void *data)
769{
770 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
771 Widget_Data *wd = elm_widget_data_get(obj);
772 Elm_Index_Item *it;
773 if (!wd) return NULL;
774 if (!after) return elm_index_item_append(obj, letter, func, data);
775 it = _item_new(obj, letter, func, data);
776 if (!it) return NULL;
777 wd->items = eina_list_append_relative(wd->items, it, after);
778 _index_box_clear(obj, wd->bx[wd->level], wd->level);
779 return (Elm_Object_Item *)it;
780}
781
782EAPI Elm_Object_Item *
783elm_index_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *letter, Evas_Smart_Cb func, const void *data)
784{
785 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
786 Widget_Data *wd = elm_widget_data_get(obj);
787 Elm_Index_Item *it;
788 if (!wd) return NULL;
789 if (!before) return elm_index_item_prepend(obj, letter, func, data);
790 it = _item_new(obj, letter, func, data);
791 if (!it) return NULL;
792 wd->items = eina_list_prepend_relative(wd->items, it, before);
793 _index_box_clear(obj, wd->bx[wd->level], wd->level);
794 return (Elm_Object_Item *)it;
795}
796
797EAPI Elm_Object_Item *
798elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func)
799{
800 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
801 Widget_Data *wd = elm_widget_data_get(obj);
802 Eina_List *lnear;
803 Elm_Index_Item *it;
804 int cmp;
805
806 if (!wd) return NULL;
807 if (!(wd->items))
808 return elm_index_item_append(obj, letter, func, data);
809
810 it = _item_new(obj, letter, func, data);
811 if (!it) return NULL;
812
813 lnear = eina_list_search_sorted_near_list(wd->items, cmp_func, it, &cmp);
814 if (cmp < 0)
815 wd->items = eina_list_append_relative_list(wd->items, it, lnear);
816 else if (cmp > 0)
817 wd->items = eina_list_prepend_relative_list(wd->items, it, lnear);
818 else
819 {
820 /* If cmp_data_func is not provided, append a duplicated item */
821 if (!cmp_data_func)
822 wd->items = eina_list_append_relative_list(wd->items, it, lnear);
823 else
824 {
825 Elm_Index_Item *p_it = eina_list_data_get(lnear);
826 if (cmp_data_func(p_it->base.data, it->base.data) >= 0)
827 p_it->base.data = it->base.data;
828 _item_free(it);
829 elm_widget_item_free(it);
830 }
831 }
832 _index_box_clear(obj, wd->bx[wd->level], wd->level);
833 return (Elm_Object_Item *)it;
834}
835
836EAPI Elm_Object_Item *
837elm_index_item_find(Evas_Object *obj, const void *data)
838{
839 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
840 Widget_Data *wd = elm_widget_data_get(obj);
841 if (!wd) return NULL;
842 return (Elm_Object_Item *) _item_find(obj, data);
843}
844
845EAPI void
846elm_index_item_clear(Evas_Object *obj)
847{
848 ELM_CHECK_WIDTYPE(obj, widtype);
849 Widget_Data *wd = elm_widget_data_get(obj);
850 Elm_Index_Item *it;
851 Eina_List *l, *clear = NULL;
852 if (!wd) return;
853 _index_box_clear(obj, wd->bx[wd->level], wd->level);
854 EINA_LIST_FOREACH(wd->items, l, it)
855 {
856 if (it->level != wd->level) continue;
857 clear = eina_list_append(clear, it);
858 }
859 EINA_LIST_FREE(clear, it)
860 {
861 _item_free(it);
862 elm_widget_item_free(it);
863 }
864}
865
866EAPI void
867elm_index_level_go(Evas_Object *obj, int level __UNUSED__)
868{
869 ELM_CHECK_WIDTYPE(obj, widtype);
870 Widget_Data *wd = elm_widget_data_get(obj);
871 if (!wd) return;
872 _index_box_auto_fill(obj, wd->bx[0], 0);
873 if (wd->level == 1) _index_box_auto_fill(obj, wd->bx[1], 1);
874}
875
876EAPI void
877elm_index_indicator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
878{
879 ELM_CHECK_WIDTYPE(obj, widtype);
880 Widget_Data *wd = elm_widget_data_get(obj);
881 if (!wd) return;
882
883 disabled = !!disabled;
884 if (wd->indicator_disabled == disabled) return;
885 wd->indicator_disabled = disabled;
886 if (!wd->items) return;
887 if (disabled)
888 edje_object_signal_emit(wd->base, "elm,indicator,state,inactive", "elm");
889 else
890 edje_object_signal_emit(wd->base, "elm,indicator,state,active", "elm");
891}
892
893EAPI Eina_Bool
894elm_index_indicator_disabled_get(const Evas_Object *obj)
895{
896 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
897 Widget_Data *wd = elm_widget_data_get(obj);
898 if (!wd) return EINA_FALSE;
899
900 return wd->indicator_disabled;
901}
902
903EAPI const char *
904elm_index_item_letter_get(const Elm_Object_Item *it)
905{
906 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
907 return ((Elm_Index_Item *)it)->letter;
908}
909
910EAPI void
911elm_index_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
912{
913 ELM_CHECK_WIDTYPE(obj, widtype);
914 Widget_Data *wd = elm_widget_data_get(obj);
915 if (!wd) return;
916
917 horizontal = !!horizontal;
918 if (horizontal == wd->horizontal) return;
919 wd->horizontal = horizontal;
920 _theme_hook(obj);
921}
922
923EAPI Eina_Bool
924elm_index_horizontal_get(const Evas_Object *obj)
925{
926 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
927 Widget_Data *wd = elm_widget_data_get(obj);
928 if (!wd) return EINA_FALSE;
929 return wd->horizontal;
930}
931
932
diff --git a/libraries/elementary/src/lib/elm_index.h b/libraries/elementary/src/lib/elm_index.h
new file mode 100644
index 0000000..33e41be
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_index.h
@@ -0,0 +1,373 @@
1/**
2 * @defgroup Index Index
3 * @ingroup Elementary
4 *
5 * @image html img/widget/index/preview-00.png
6 * @image latex img/widget/index/preview-00.eps
7 *
8 * An index widget gives you an index for fast access to whichever
9 * group of other UI items one might have. It's a list of text
10 * items (usually letters, for alphabetically ordered access).
11 *
12 * Index widgets are by default hidden and just appear when the
13 * user clicks over it's reserved area in the canvas. In its
14 * default theme, it's an area one @ref Fingers "finger" wide on
15 * the right side of the index widget's container.
16 *
17 * When items on the index are selected, smart callbacks get
18 * called, so that its user can make other container objects to
19 * show a given area or child object depending on the index item
20 * selected. You'd probably be using an index together with @ref
21 * List "lists", @ref Genlist "generic lists" or @ref Gengrid
22 * "general grids".
23 *
24 * Smart events one can add callbacks for are:
25 * - @c "changed" - When the selected index item changes. @c
26 * event_info is the selected item's data pointer.
27 * - @c "delay,changed" - When the selected index item changes, but
28 * after a small idling period. @c event_info is the selected
29 * item's data pointer.
30 * - @c "selected" - When the user releases a mouse button and
31 * selects an item. @c event_info is the selected item's data
32 * pointer.
33 * - @c "level,up" - when the user moves a finger from the first
34 * level to the second level
35 * - @c "level,down" - when the user moves a finger from the second
36 * level to the first level
37 *
38 * The @c "delay,changed" event is so that it'll wait a small time
39 * before actually reporting those events and, moreover, just the
40 * last event happening on those time frames will actually be
41 * reported.
42 *
43 * Here are some examples on its usage:
44 * @li @ref index_example_01
45 * @li @ref index_example_02
46 */
47
48/**
49 * @addtogroup Index
50 * @{
51 */
52
53/**
54 * Add a new index widget to the given parent Elementary
55 * (container) object
56 *
57 * @param parent The parent object
58 * @return a new index widget handle or @c NULL, on errors
59 *
60 * This function inserts a new index widget on the canvas.
61 *
62 * @ingroup Index
63 */
64EAPI Evas_Object *elm_index_add(Evas_Object *parent);
65
66/**
67 * Enable or disable auto hiding feature for a given index widget.
68 *
69 * @param obj The index object
70 * @param disabled @c EINA_TRUE to disable auto hiding, @c EINA_FALSE to enable
71 *
72 * @see elm_index_autohide_disabled_get()
73 *
74 * @ingroup Index
75 */
76EAPI void elm_index_autohide_disabled_set(Evas_Object *obj, Eina_Bool disabled);
77
78/**
79 * Get whether auto hiding feature is enabled or not for a given index widget.
80 *
81 * @param obj The index object
82 * @return @c EINA_TRUE, if auto hiding is disabled, @c EINA_FALSE otherwise
83 *
84 * @see elm_index_autohide_disabled_set() for more details
85 *
86 * @ingroup Index
87 */
88EAPI Eina_Bool elm_index_autohide_disabled_get(const Evas_Object *obj);
89
90/**
91 * Set the items level for a given index widget.
92 *
93 * @param obj The index object.
94 * @param level @c 0 or @c 1, the currently implemented levels.
95 *
96 * @see elm_index_item_level_get()
97 *
98 * @ingroup Index
99 */
100EAPI void elm_index_item_level_set(Evas_Object *obj, int level);
101
102/**
103 * Get the items level set for a given index widget.
104 *
105 * @param obj The index object.
106 * @return @c 0 or @c 1, which are the levels @p obj might be at.
107 *
108 * @see elm_index_item_level_set() for more information
109 *
110 * @ingroup Index
111 */
112EAPI int elm_index_item_level_get(const Evas_Object *obj);
113
114/**
115 * Set the selected state of an item.
116 *
117 * @param it The index item
118 * @param selected The selected state
119 *
120 * This sets the selected state of the given item @p it.
121 * @c EINA_TRUE for selected, @c EINA_FALSE for not selected.
122 *
123 * If a new item is selected the previously selected will be unselected.
124 * Previously selected item can be get with function
125 * elm_index_selected_item_get().
126 *
127 * Selected items will be highlighted.
128 *
129 * @see elm_index_selected_item_get()
130 *
131 * @ingroup Index
132 */
133EAPI void elm_index_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
134
135/**
136 * Returns the last selected item, for a given index widget.
137 *
138 * @param obj The index object.
139 * @param level @c 0 or @c 1, the currently implemented levels.
140 * @return The last item @b selected on @p obj (or @c NULL, on errors).
141 *
142 * @ingroup Index
143 */
144EAPI Elm_Object_Item *elm_index_selected_item_get(const Evas_Object *obj, int level);
145
146/**
147 * Append a new item on a given index widget.
148 *
149 * @param obj The index object.
150 * @param letter Letter under which the item should be indexed
151 * @param func The function to call when the item is selected.
152 * @param data The item data to set for the index's item
153 * @return A handle to the item added or @c NULL, on errors
154 *
155 * Despite the most common usage of the @p letter argument is for
156 * single char strings, one could use arbitrary strings as index
157 * entries.
158 *
159 * @c item will be the pointer returned back on @c "changed", @c
160 * "delay,changed" and @c "selected" smart events.
161 *
162 * @ingroup Index
163 */
164EAPI Elm_Object_Item *elm_index_item_append(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data);
165
166/**
167 * Prepend a new item on a given index widget.
168 *
169 * @param obj The index object.
170 * @param letter Letter under which the item should be indexed
171 * @param func The function to call when the item is selected.
172 * @param data The item data to set for the index's item
173 * @return A handle to the item added or @c NULL, on errors
174 *
175 * Despite the most common usage of the @p letter argument is for
176 * single char strings, one could use arbitrary strings as index
177 * entries.
178 *
179 * @c item will be the pointer returned back on @c "changed", @c
180 * "delay,changed" and @c "selected" smart events.
181 *
182 * @ingroup Index
183 */
184EAPI Elm_Object_Item *elm_index_item_prepend(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data);
185
186/**
187 * Insert a new item into the index object after item @p after.
188 *
189 * @param obj The index object.
190 * @param after The index item to insert after.
191 * @param letter Letter under which the item should be indexed
192 * @param func The function to call when the item is clicked.
193 * @param data The item data to set for the index's item
194 * @return A handle to the item added or @c NULL, on errors
195 *
196 * Despite the most common usage of the @p letter argument is for
197 * single char strings, one could use arbitrary strings as index
198 * entries.
199 *
200 * @c item will be the pointer returned back on @c "changed", @c
201 * "delay,changed" and @c "selected" smart events.
202 *
203 * @note If @p relative is @c NULL this function will behave as
204 * elm_index_item_append().
205 *
206 * @ingroup Index
207 */
208EAPI Elm_Object_Item *elm_index_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *letter, Evas_Smart_Cb func, const void *data);
209
210/**
211 * Insert a new item into the index object before item @p before.
212 *
213 * @param obj The index object.
214 * @param before The index item to insert after.
215 * @param letter Letter under which the item should be indexed
216 * @param func The function to call when the item is clicked.
217 * @param data The item data to set for the index's item
218 * @return A handle to the item added or @c NULL, on errors
219 *
220 * Despite the most common usage of the @p letter argument is for
221 * single char strings, one could use arbitrary strings as index
222 * entries.
223 *
224 * @c item will be the pointer returned back on @c "changed", @c
225 * "delay,changed" and @c "selected" smart events.
226 *
227 * @note If @p relative is @c NULL this function will behave as
228 * elm_index_item_prepend().
229 *
230 * @ingroup Index
231 */
232EAPI Elm_Object_Item *elm_index_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *letter, Evas_Smart_Cb func, const void *data);
233
234/**
235 * Insert a new item into the given index widget, using @p cmp_func
236 * function to sort items (by item handles).
237 *
238 * @param obj The index object.
239 * @param letter Letter under which the item should be indexed
240 * @param func The function to call when the item is clicked.
241 * @param data The item data to set for the index's item
242 * @param cmp_func The comparing function to be used to sort index
243 * items <b>by #index item handles</b>
244 * @param cmp_data_func A @b fallback function to be called for the
245 * sorting of index items <b>by item data</b>). It will be used
246 * when @p cmp_func returns @c 0 (equality), which means an index
247 * item with provided item data already exists. To decide which
248 * data item should be pointed to by the index item in question, @p
249 * cmp_data_func will be used. If @p cmp_data_func returns a
250 * non-negative value, the previous index item data will be
251 * replaced by the given @p item pointer. If the previous data need
252 * to be freed, it should be done by the @p cmp_data_func function,
253 * because all references to it will be lost. If this function is
254 * not provided (@c NULL is given), index items will be @b
255 * duplicated, if @p cmp_func returns @c 0.
256 * @return A handle to the item added or @c NULL, on errors
257 *
258 * Despite the most common usage of the @p letter argument is for
259 * single char strings, one could use arbitrary strings as index
260 * entries.
261 *
262 * @c item will be the pointer returned back on @c "changed", @c
263 * "delay,changed" and @c "selected" smart events.
264 *
265 * @ingroup Index
266 */
267EAPI Elm_Object_Item *elm_index_item_sorted_insert(Evas_Object *obj, const char *letter, Evas_Smart_Cb func, const void *data, Eina_Compare_Cb cmp_func, Eina_Compare_Cb cmp_data_func);
268
269/**
270 * Find a given index widget's item, <b>using item data</b>.
271 *
272 * @param obj The index object
273 * @param data The item data pointed to by the desired index item
274 * @return The index item handle, if found, or @c NULL otherwise
275 *
276 * @ingroup Index
277 */
278EAPI Elm_Object_Item *elm_index_item_find(Evas_Object *obj, const void *data);
279
280/**
281 * Removes @b all items from a given index widget.
282 *
283 * @param obj The index object.
284 *
285 * If deletion callbacks are set, via elm_object_item_del_cb_set(),
286 * that callback function will be called for each item in @p obj.
287 *
288 * @ingroup Index
289 */
290EAPI void elm_index_item_clear(Evas_Object *obj);
291
292/**
293 * Go to a given items level on a index widget
294 *
295 * @param obj The index object
296 * @param level The index level (one of @c 0 or @c 1)
297 *
298 * @ingroup Index
299 */
300EAPI void elm_index_level_go(Evas_Object *obj, int level);
301
302/**
303 * Get the letter (string) set on a given index widget item.
304 *
305 * @param item The index item handle
306 * @return The letter string set on @p it
307 *
308 * @ingroup Index
309 */
310EAPI const char *elm_index_item_letter_get(const Elm_Object_Item *item);
311
312/**
313 * Set the indicator as to be disabled.
314 *
315 * @param obj The index object
316 * @param disabled @c EINA_TRUE to disable it, @c EINA_FALSE to enable it
317 *
318 * In Index widget, Indicator notes popup text, which shows a letter has been selecting.
319 *
320 * @see elm_index_indicator_disabled_get()
321 *
322 * @ingroup Index
323 */
324EAPI void elm_index_indicator_disabled_set(Evas_Object *obj, Eina_Bool disabled);
325
326/**
327 * Get the value of indicator's disabled status.
328 *
329 * @param obj The index object
330 * @return EINA_TRUE if the indicator is disabled.
331 *
332 * @see elm_index_indicator_disabled_set()
333 *
334 * @ingroup Index
335 */
336EAPI Eina_Bool elm_index_indicator_disabled_get(const Evas_Object *obj);
337
338/**
339 * Enable or disable horizontal mode on the index object
340 *
341 * @param obj The index object.
342 * @param horizontal @c EINA_TRUE to enable horizontal or @c EINA_FALSE to
343 * disable it, i.e., to enable vertical mode. it's an area one @ref Fingers
344 * "finger" wide on the bottom side of the index widget's container.
345 *
346 * @note Vertical mode is set by default.
347 *
348 * On horizontal mode items are displayed on index from left to right,
349 * instead of from top to bottom. Also, the index will scroll horizontally.
350 *
351 * @see elm_index_horizontal_get()
352 *
353 * @ingroup Index
354 */
355EAPI void elm_index_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
356
357/**
358 * Get a value whether horizontal mode is enabled or not.
359 *
360 * @param obj The index object.
361 * @return @c EINA_TRUE means horizontal mode selection is enabled.
362 * @c EINA_FALSE indicates it's disabled. If @p obj is @c NULL,
363 * @c EINA_FALSE is returned.
364 *
365 * @see elm_index_horizontal_set() for details.
366 *
367 * @ingroup Index
368 */
369EAPI Eina_Bool elm_index_horizontal_get(const Evas_Object *obj);
370
371/**
372 * @}
373 */
diff --git a/libraries/elementary/src/lib/elm_intro.h b/libraries/elementary/src/lib/elm_intro.h
new file mode 100644
index 0000000..2dd8879
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_intro.h
@@ -0,0 +1,34 @@
1/**
2 * @mainpage Elementary
3 * @image html elementary.png
4 * @version 0.8.0
5 * @date 2008-2012
6 *
7 * @section intro What is Elementary?
8 *
9 * This is a VERY SIMPLE toolkit. It is not meant for writing extensive desktop
10 * applications (yet). Small simple ones with simple needs.
11 *
12 * It is meant to make the programmers work almost brainless but give them lots
13 * of flexibility.
14 *
15 * @li @ref Start - Go here to quickly get started with writing Apps
16 *
17 * @section organization Organization
18 *
19 * One can divide Elementary into three main groups:
20 * @li @ref infralist - These are modules that deal with Elementary as a whole.
21 * @li @ref widgetslist - These are the widgets you'll compose your UI out of.
22 * @li @ref containerslist - These are the containers which hold the widgets.
23 *
24 * @section license License
25 *
26 * LGPL v2 (see COPYING in the base of Elementary's source). This applies to
27 * all files in the source tree.
28 *
29 * @section ack Acknowledgements
30 * There is a lot that goes into making a widget set, and they don't happen out of
31 * nothing. It's like trying to make everyone everywhere happy, regardless of age,
32 * gender, race or nationality - and that is really tough. So thanks to people and
33 * organizations behind this, as listed in the @ref authors page.
34 */
diff --git a/libraries/elementary/src/lib/elm_label.c b/libraries/elementary/src/lib/elm_label.c
new file mode 100644
index 0000000..b31ef2f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_label.c
@@ -0,0 +1,543 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *lbl;
9 const char *label;
10 const char *format;
11 Ecore_Job *deferred_recalc_job;
12 double slide_duration;
13 Evas_Coord lastw;
14 Evas_Coord wrap_w;
15 Elm_Wrap_Type linewrap;
16 Eina_Bool changed : 1;
17 Eina_Bool ellipsis : 1;
18 Eina_Bool slidingmode : 1;
19 Eina_Bool slidingellipsis : 1;
20};
21
22static const char *widtype = NULL;
23static void _del_hook(Evas_Object *obj);
24static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
25static void _theme_hook(Evas_Object *obj);
26static void _sizing_eval(Evas_Object *obj);
27static int _get_value_in_key_string(const char *oldstring, const char *key, char **value);
28static int _strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag);
29static int _stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag);
30static void _label_sliding_change(Evas_Object *obj);
31static void _label_format_set(Evas_Object *obj, const char *format);
32
33static void
34_elm_recalc_job(void *data)
35{
36 Widget_Data *wd = elm_widget_data_get(data);
37 Evas_Coord minw = -1, minh = -1;
38 Evas_Coord resw;
39 if (!wd) return;
40 evas_event_freeze(evas_object_evas_get(data));
41 wd->deferred_recalc_job = NULL;
42 evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, NULL);
43 if (wd->wrap_w > resw)
44 resw = wd->wrap_w;
45
46 edje_object_size_min_restricted_calc(wd->lbl, &minw, &minh, resw, 0);
47 /* This is a hack to workaround the way min size hints are treated.
48 * If the minimum width is smaller than the restricted width, it means
49 * the mininmum doesn't matter. */
50 if ((minw <= resw) && (minw != wd->wrap_w))
51 {
52 Evas_Coord ominw = -1;
53 evas_object_size_hint_min_get(data, &ominw, NULL);
54 minw = ominw;
55 }
56 evas_object_size_hint_min_set(data, minw, minh);
57 evas_event_thaw(evas_object_evas_get(data));
58 evas_event_thaw_eval(evas_object_evas_get(data));
59}
60
61static void
62_del_hook(Evas_Object *obj)
63{
64 Widget_Data *wd = elm_widget_data_get(obj);
65 if (!wd) return;
66 evas_event_freeze(evas_object_evas_get(obj));
67 if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
68 if (wd->label) eina_stringshare_del(wd->label);
69 free(wd);
70 evas_event_thaw(evas_object_evas_get(obj));
71 evas_event_thaw_eval(evas_object_evas_get(obj));
72}
73
74static void
75_theme_change(Evas_Object *obj)
76{
77 Widget_Data *wd = elm_widget_data_get(obj);
78 if (!wd) return;
79
80 _elm_theme_object_set(obj, wd->lbl, "label", "base",
81 elm_widget_style_get(obj));
82}
83
84static void
85_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
86{
87 Widget_Data *wd = elm_widget_data_get(obj);
88 if (!wd) return;
89 edje_object_mirrored_set(wd->lbl, rtl);
90}
91
92static void
93_theme_hook(Evas_Object *obj)
94{
95 Widget_Data *wd = elm_widget_data_get(obj);
96 if (!wd) return;
97 evas_event_freeze(evas_object_evas_get(obj));
98 _elm_widget_mirrored_reload(obj);
99 _mirrored_set(obj, elm_widget_mirrored_get(obj));
100 _theme_change(obj);
101 _label_format_set(wd->lbl, wd->format);
102 edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
103 edje_object_scale_set(wd->lbl, elm_widget_scale_get(obj) *
104 _elm_config->scale);
105 _label_sliding_change(obj);
106 _sizing_eval(obj);
107 evas_event_thaw(evas_object_evas_get(obj));
108 evas_event_thaw_eval(evas_object_evas_get(obj));
109}
110
111static void
112_sizing_eval(Evas_Object *obj)
113{
114 Widget_Data *wd = elm_widget_data_get(obj);
115 Evas_Coord minw = -1, minh = -1;
116 Evas_Coord resw, resh;
117 if (!wd) return;
118
119 if (wd->linewrap)
120 {
121 evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
122 if ((resw == wd->lastw) && (!wd->changed)) return;
123 wd->changed = EINA_FALSE;
124 wd->lastw = resw;
125 _elm_recalc_job(obj);
126 // FIXME: works ok. but NOT for genlist. what should genlist do?
127 // if (wd->deferred_recalc_job) ecore_job_del(wd->deferred_recalc_job);
128 // wd->deferred_recalc_job = ecore_job_add(_elm_recalc_job, obj);
129 }
130 else
131 {
132 evas_event_freeze(evas_object_evas_get(obj));
133 evas_object_geometry_get(wd->lbl, NULL, NULL, &resw, &resh);
134 edje_object_size_min_calc(wd->lbl, &minw, &minh);
135 if (wd->wrap_w > 0 && minw > wd->wrap_w) minw = wd->wrap_w;
136 evas_object_size_hint_min_set(obj, minw, minh);
137 evas_event_thaw(evas_object_evas_get(obj));
138 evas_event_thaw_eval(evas_object_evas_get(obj));
139 }
140}
141
142static void
143_lbl_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
144{
145 Widget_Data *wd = elm_widget_data_get(data);
146 if (!wd) return;
147 if (wd->linewrap) _sizing_eval(data);
148}
149
150static void
151_label_format_set(Evas_Object *obj, const char *format)
152{
153 if (format)
154 edje_object_part_text_style_user_push(obj, "elm.text", format);
155 else
156 edje_object_part_text_style_user_pop(obj, "elm.text");
157}
158
159static int
160_get_value_in_key_string(const char *oldstring, const char *key, char **value)
161{
162 char *curlocater, *endtag;
163 int firstindex = 0, foundflag = -1;
164
165 curlocater = strstr(oldstring, key);
166 if (curlocater)
167 {
168 int key_len = strlen(key);
169 endtag = curlocater + key_len;
170 if ((!endtag) || (*endtag != '='))
171 {
172 foundflag = 0;
173 return -1;
174 }
175 firstindex = abs(oldstring - curlocater);
176 firstindex += key_len + 1; // strlen("key") + strlen("=")
177 *value = (char *)oldstring + firstindex;
178
179 foundflag = 1;
180 }
181 else
182 {
183 foundflag = 0;
184 }
185
186 if (foundflag == 1) return 0;
187
188 return -1;
189}
190
191
192static int
193_strbuf_key_value_replace(Eina_Strbuf *srcbuf, const char *key, const char *value, int deleteflag)
194{
195 char *kvalue;
196 const char *srcstring = NULL;
197
198 srcstring = eina_strbuf_string_get(srcbuf);
199
200 if (_get_value_in_key_string(srcstring, key, &kvalue) == 0)
201 {
202 const char *val_end;
203 int val_end_idx = 0;
204 int key_start_idx = 0;
205 val_end = strchr(kvalue, ' ');
206
207 if (val_end)
208 val_end_idx = val_end - srcstring;
209 else
210 val_end_idx = kvalue - srcstring + strlen(kvalue) - 1;
211
212 /* -1 is because of the '=' */
213 key_start_idx = kvalue - srcstring - 1 - strlen(key);
214 eina_strbuf_remove(srcbuf, key_start_idx, val_end_idx);
215 if (!deleteflag)
216 {
217 eina_strbuf_insert_printf(srcbuf, "%s=%s", key_start_idx, key,
218 value);
219 }
220 }
221 else if (!deleteflag)
222 {
223 if (*srcstring)
224 {
225 /* -1 because we want it before the ' */
226 eina_strbuf_insert_printf(srcbuf, " %s=%s",
227 eina_strbuf_length_get(srcbuf) - 1, key, value);
228 }
229 else
230 {
231 eina_strbuf_append_printf(srcbuf, "DEFAULT='%s=%s'", key, value);
232 }
233 }
234 return 0;
235}
236
237static int
238_stringshare_key_value_replace(const char **srcstring, const char *key, const char *value, int deleteflag)
239{
240 Eina_Strbuf *sharebuf = NULL;
241
242 sharebuf = eina_strbuf_new();
243 eina_strbuf_append(sharebuf, *srcstring);
244 _strbuf_key_value_replace(sharebuf, key, value, deleteflag);
245 eina_stringshare_del(*srcstring);
246 *srcstring = eina_stringshare_add(eina_strbuf_string_get(sharebuf));
247 eina_strbuf_free(sharebuf);
248
249 return 0;
250}
251
252static void
253_label_sliding_change(Evas_Object *obj)
254{
255 Widget_Data *wd = elm_widget_data_get(obj);
256 if (!wd) return;
257 char *plaintxt;
258 int plainlen = 0;
259
260 // dosen't support multiline sliding effect
261 if (wd->linewrap)
262 {
263 wd->slidingmode = EINA_FALSE;
264 return;
265 }
266
267 plaintxt = _elm_util_mkup_to_text(edje_object_part_text_get(wd->lbl, "elm.text"));
268 if (plaintxt != NULL)
269 {
270 plainlen = strlen(plaintxt);
271 free(plaintxt);
272 }
273 // too short to slide label
274 if (plainlen < 1)
275 {
276 wd->slidingmode = EINA_TRUE;
277 return;
278 }
279
280 if (wd->slidingmode)
281 {
282 Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
283
284 if (wd->ellipsis)
285 {
286 wd->slidingellipsis = EINA_TRUE;
287 elm_label_ellipsis_set(obj, EINA_FALSE);
288 }
289
290 msg->count = 1;
291 msg->val[0] = wd->slide_duration;
292
293 edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
294 edje_object_signal_emit(wd->lbl, "elm,state,slide,start", "elm");
295 }
296 else
297 {
298 edje_object_signal_emit(wd->lbl, "elm,state,slide,stop", "elm");
299 if (wd->slidingellipsis)
300 {
301 wd->slidingellipsis = EINA_FALSE;
302 elm_label_ellipsis_set(obj, EINA_TRUE);
303 }
304 }
305}
306
307static void
308_elm_label_label_set(Evas_Object *obj, const char *item, const char *label)
309{
310 ELM_CHECK_WIDTYPE(obj, widtype);
311 Widget_Data *wd = elm_widget_data_get(obj);
312 if (!wd) return;
313 if (item && strcmp(item, "default")) return;
314 if (!label) label = "";
315 eina_stringshare_replace(&wd->label, label);
316 _label_format_set(wd->lbl, wd->format);
317 edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
318 wd->changed = 1;
319 _sizing_eval(obj);
320}
321
322static const char *
323_elm_label_label_get(const Evas_Object *obj, const char *item)
324{
325 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
326 Widget_Data *wd = elm_widget_data_get(obj);
327 if (item && strcmp(item, "default")) return NULL;
328 if (!wd) return NULL;
329 return wd->label;
330}
331
332static void
333_translate_hook(Evas_Object *obj)
334{
335 evas_object_smart_callback_call(obj, "language,changed", NULL);
336}
337
338EAPI Evas_Object *
339elm_label_add(Evas_Object *parent)
340{
341 Evas_Object *obj;
342 Evas *e;
343 Widget_Data *wd;
344
345 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
346
347 ELM_SET_WIDTYPE(widtype, "label");
348 elm_widget_type_set(obj, "label");
349 elm_widget_sub_object_add(parent, obj);
350 elm_widget_data_set(obj, wd);
351 elm_widget_del_hook_set(obj, _del_hook);
352 elm_widget_theme_hook_set(obj, _theme_hook);
353 elm_widget_can_focus_set(obj, EINA_FALSE);
354 elm_widget_text_set_hook_set(obj, _elm_label_label_set);
355 elm_widget_text_get_hook_set(obj, _elm_label_label_get);
356 elm_widget_translate_hook_set(obj, _translate_hook);
357
358 wd->linewrap = ELM_WRAP_NONE;
359 wd->ellipsis = EINA_FALSE;
360 wd->slidingmode = EINA_FALSE;
361 wd->slidingellipsis = EINA_FALSE;
362 wd->wrap_w = -1;
363 wd->slide_duration = 10;
364
365 wd->lbl = edje_object_add(e);
366 _elm_theme_object_set(obj, wd->lbl, "label", "base", "default");
367 wd->format = eina_stringshare_add("");
368 wd->label = eina_stringshare_add("<br>");
369 _label_format_set(wd->lbl, wd->format);
370 edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
371
372 elm_widget_resize_object_set(obj, wd->lbl);
373
374 evas_object_event_callback_add(wd->lbl, EVAS_CALLBACK_RESIZE, _lbl_resize, obj);
375
376 _mirrored_set(obj, elm_widget_mirrored_get(obj));
377 wd->changed = 1;
378 _sizing_eval(obj);
379 return obj;
380}
381
382EAPI void
383elm_label_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap)
384{
385 ELM_CHECK_WIDTYPE(obj, widtype);
386 Widget_Data *wd = elm_widget_data_get(obj);
387 const char *wrap_str;
388 int len;
389
390 if (!wd) return;
391 if (wd->linewrap == wrap) return;
392 wd->linewrap = wrap;
393 len = strlen(wd->label);
394 if (len <= 0) return;
395
396 switch (wrap)
397 {
398 case ELM_WRAP_CHAR:
399 wrap_str = "char";
400 break;
401 case ELM_WRAP_WORD:
402 wrap_str = "word";
403 break;
404 case ELM_WRAP_MIXED:
405 wrap_str = "mixed";
406 break;
407 default:
408 wrap_str = "none";
409 break;
410 }
411
412 if (_stringshare_key_value_replace(&wd->format,
413 "wrap", wrap_str, 0) == 0)
414 {
415 _label_format_set(wd->lbl, wd->format);
416 edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
417 wd->changed = 1;
418 _sizing_eval(obj);
419 }
420}
421
422EAPI Elm_Wrap_Type
423elm_label_line_wrap_get(const Evas_Object *obj)
424{
425 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
426 Widget_Data *wd = elm_widget_data_get(obj);
427 if (!wd) return EINA_FALSE;
428 return wd->linewrap;
429}
430
431EAPI void
432elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w)
433{
434 ELM_CHECK_WIDTYPE(obj, widtype);
435 Widget_Data *wd = elm_widget_data_get(obj);
436 if (!wd) return;
437 if (w < 0) w = 0;
438 if (wd->wrap_w == w) return;
439 if (wd->ellipsis)
440 {
441 _label_format_set(wd->lbl, wd->format);
442 edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
443 }
444 wd->wrap_w = w;
445 _sizing_eval(obj);
446}
447
448EAPI Evas_Coord
449elm_label_wrap_width_get(const Evas_Object *obj)
450{
451 ELM_CHECK_WIDTYPE(obj, widtype) 0;
452 Widget_Data *wd = elm_widget_data_get(obj);
453 if (!wd) return 0;
454 return wd->wrap_w;
455}
456
457EAPI void
458elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis)
459{
460 ELM_CHECK_WIDTYPE(obj, widtype);
461 Widget_Data *wd = elm_widget_data_get(obj);
462 Eina_Strbuf *fontbuf = NULL;
463 int len, removeflag = 0;
464
465 if (!wd) return;
466 if (wd->ellipsis == ellipsis) return;
467 wd->ellipsis = ellipsis;
468 len = strlen(wd->label);
469 if (len <= 0) return;
470
471 if (ellipsis == EINA_FALSE) removeflag = 1; // remove fontsize tag
472
473 fontbuf = eina_strbuf_new();
474 eina_strbuf_append_printf(fontbuf, "%f", 1.0);
475
476 if (_stringshare_key_value_replace(&wd->format,
477 "ellipsis", eina_strbuf_string_get(fontbuf), removeflag) == 0)
478 {
479 _label_format_set(wd->lbl, wd->format);
480 edje_object_part_text_set(wd->lbl, "elm.text", wd->label);
481 wd->changed = 1;
482 _sizing_eval(obj);
483 }
484 eina_strbuf_free(fontbuf);
485
486}
487
488EAPI Eina_Bool
489elm_label_ellipsis_get(const Evas_Object *obj)
490{
491 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
492 Widget_Data *wd = elm_widget_data_get(obj);
493 if (!wd) return EINA_FALSE;
494 return wd->ellipsis;
495}
496
497EAPI void
498elm_label_slide_set(Evas_Object *obj,
499 Eina_Bool slide)
500{
501 ELM_CHECK_WIDTYPE(obj, widtype);
502 Widget_Data *wd = elm_widget_data_get(obj);
503 if (!wd) return;
504
505 if (wd->slidingmode == slide) return;
506 wd->slidingmode = slide;
507 _label_sliding_change(obj);
508 wd->changed = 1;
509 _sizing_eval(obj);
510}
511
512EAPI Eina_Bool
513elm_label_slide_get(const Evas_Object *obj)
514{
515 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
516 Widget_Data *wd = elm_widget_data_get(obj);
517 if (!wd) return EINA_FALSE;
518 return wd->slidingmode;
519}
520
521EAPI void
522elm_label_slide_duration_set(Evas_Object *obj, double duration)
523{
524 ELM_CHECK_WIDTYPE(obj, widtype);
525 Widget_Data *wd = elm_widget_data_get(obj);
526 Edje_Message_Float_Set *msg = alloca(sizeof(Edje_Message_Float_Set) + (sizeof(double)));
527
528 if (!wd) return;
529 wd->slide_duration = duration;
530 msg->count = 1;
531 msg->val[0] = wd->slide_duration;
532 edje_object_message_send(wd->lbl, EDJE_MESSAGE_FLOAT_SET, 0, msg);
533}
534
535EAPI double
536elm_label_slide_duration_get(const Evas_Object *obj)
537{
538 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
539 Widget_Data *wd = elm_widget_data_get(obj);
540 if (!wd) return 0;
541 return wd->slide_duration;
542}
543
diff --git a/libraries/elementary/src/lib/elm_label.h b/libraries/elementary/src/lib/elm_label.h
new file mode 100644
index 0000000..7fdc619
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_label.h
@@ -0,0 +1,180 @@
1/**
2 * @defgroup Label Label
3 * @ingroup Elementary
4 *
5 * @image html img/widget/label/preview-00.png
6 * @image latex img/widget/label/preview-00.eps
7 *
8 * @brief Widget to display text, with simple html-like markup.
9 *
10 * The Label widget @b doesn't allow text to overflow its boundaries, if the
11 * text doesn't fit the geometry of the label it will be ellipsized or be
12 * cut. Elementary provides several styles for this widget:
13 * @li default - No animation
14 * @li marker - Centers the text in the label and makes it bold by default
15 * @li slide_long - The entire text appears from the right of the screen and
16 * slides until it disappears in the left of the screen(reappearing on the
17 * right again).
18 * @li slide_short - The text appears in the left of the label and slides to
19 * the right to show the overflow. When all of the text has been shown the
20 * position is reset.
21 * @li slide_bounce - The text appears in the left of the label and slides to
22 * the right to show the overflow. When all of the text has been shown the
23 * animation reverses, moving the text to the left.
24 *
25 * Custom themes can of course invent new markup tags and style them any way
26 * they like.
27 *
28 * The following signals may be emitted by the label widget:
29 * @li "language,changed": The program's language changed.
30 *
31 * See @ref tutorial_label for a demonstration of how to use a label widget.
32 * @{
33 */
34
35/**
36 * @brief Add a new label to the parent
37 *
38 * @param parent The parent object
39 * @return The new object or NULL if it cannot be created
40 *
41 * @ingroup Label
42 */
43EAPI Evas_Object *elm_label_add(Evas_Object *parent);
44
45/**
46 * @brief Set the wrapping behavior of the label
47 *
48 * @param obj The label object
49 * @param wrap To wrap text or not
50 *
51 * By default no wrapping is done. Possible values for @p wrap are:
52 * @li ELM_WRAP_NONE - No wrapping
53 * @li ELM_WRAP_CHAR - wrap between characters
54 * @li ELM_WRAP_WORD - wrap between words
55 * @li ELM_WRAP_MIXED - Word wrap, and if that fails, char wrap
56 *
57 * @ingroup Label
58 */
59EAPI void elm_label_line_wrap_set(Evas_Object *obj, Elm_Wrap_Type wrap);
60
61/**
62 * @brief Get the wrapping behavior of the label
63 *
64 * @param obj The label object
65 * @return Wrap type
66 *
67 * @see elm_label_line_wrap_set()
68 *
69 * @ingroup Label
70 */
71EAPI Elm_Wrap_Type elm_label_line_wrap_get(const Evas_Object *obj);
72
73/**
74 * @brief Set wrap width of the label
75 *
76 * @param obj The label object
77 * @param w The wrap width in pixels at a minimum where words need to wrap
78 *
79 * This function sets the maximum width size hint of the label.
80 *
81 * @warning This is only relevant if the label is inside a container.
82 *
83 * @ingroup Label
84 */
85EAPI void elm_label_wrap_width_set(Evas_Object *obj, Evas_Coord w);
86
87/**
88 * @brief Get wrap width of the label
89 *
90 * @param obj The label object
91 * @return The wrap width in pixels at a minimum where words need to wrap
92 *
93 * @see elm_label_wrap_width_set()
94 *
95 * @ingroup Label
96 */
97EAPI Evas_Coord elm_label_wrap_width_get(const Evas_Object *obj);
98
99/**
100 * @brief Set the ellipsis behavior of the label
101 *
102 * @param obj The label object
103 * @param ellipsis To ellipsis text or not
104 *
105 * If set to true and the text doesn't fit in the label an ellipsis("...")
106 * will be shown at the end of the widget.
107 *
108 * @warning This doesn't work with slide(elm_label_slide_set()) or if the
109 * chosen wrap method was ELM_WRAP_WORD.
110 *
111 * @ingroup Label
112 */
113EAPI void elm_label_ellipsis_set(Evas_Object *obj, Eina_Bool ellipsis);
114
115/**
116 * @brief Get the ellipsis behavior of the label
117 *
118 * @param obj The label object
119 * @return If true, an ellipsis will be shown at the end of the label area.
120 *
121 * @see elm_label_ellipsis_set()
122 *
123 * @ingroup Label
124 */
125EAPI Eina_Bool elm_label_ellipsis_get(const Evas_Object *obj);
126
127/**
128 * @brief Set sliding effect of label widget.
129 *
130 * @param obj The label object
131 * @param slide If true, sliding effect will be shown
132 *
133 * If set to true, the text of the label will slide/scroll through the length of
134 * label.
135 *
136 * @warning This only works with the themes "slide_short", "slide_long" and
137 * "slide_bounce".
138 *
139 * @ingroup Label
140 */
141EAPI void elm_label_slide_set(Evas_Object *obj, Eina_Bool slide);
142
143/**
144 * @brief Get whether sliding effect is shown or not.
145 *
146 * @param obj The label object
147 * @return If true, sliding effect is shown.
148 *
149 * @see elm_label_slide_set()
150 *
151 * @ingroup Label
152 */
153EAPI Eina_Bool elm_label_slide_get(const Evas_Object *obj);
154
155/**
156 * @brief Set the slide duration(speed) of the label
157 *
158 * @param obj The label object
159 * @param duration The duration in seconds in moving text from slide begin position
160 * to slide end position
161 *
162 * @ingroup Label
163 */
164EAPI void elm_label_slide_duration_set(Evas_Object *obj, double duration);
165
166/**
167 * @brief Get the slide duration(speed) of the label
168 *
169 * @param obj The label object
170 * @return The duration time in moving text from slide begin position to slide end position
171 *
172 * @see elm_label_slide_duration_set()
173 *
174 * @ingroup Label
175 */
176EAPI double elm_label_slide_duration_get(const Evas_Object *obj);
177
178/**
179 * @}
180 */
diff --git a/libraries/elementary/src/lib/elm_layout.c b/libraries/elementary/src/lib/elm_layout.c
new file mode 100644
index 0000000..6f14484
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_layout.c
@@ -0,0 +1,967 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Subinfo Subinfo;
6typedef struct _Part_Cursor Part_Cursor;
7
8struct _Widget_Data
9{
10 Evas_Object *obj;
11 Evas_Object *lay;
12 Eina_List *subs;
13 Eina_List *parts_cursors;
14 Eina_Bool needs_size_calc:1;
15 const char *clas, *group, *style;
16};
17
18struct _Subinfo
19{
20 const char *part;
21 Evas_Object *obj;
22 enum
23 {
24 SWALLOW,
25 BOX_APPEND,
26 BOX_PREPEND,
27 BOX_INSERT_BEFORE,
28 BOX_INSERT_AT,
29 TABLE_PACK,
30 TEXT
31 } type;
32 union
33 {
34 union
35 {
36 const Evas_Object *reference;
37 unsigned int pos;
38 } box;
39 struct
40 {
41 unsigned short col, row, colspan, rowspan;
42 } table;
43 struct
44 {
45 const char *text;
46 } text;
47 } p;
48};
49
50struct _Part_Cursor
51{
52 Evas_Object *obj;
53 const char *part;
54 const char *cursor;
55 const char *style;
56 Eina_Bool engine_only:1;
57};
58
59static const char *widtype = NULL;
60static void _del_hook(Evas_Object *obj);
61static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
62static void _theme_hook(Evas_Object *obj);
63static void _sizing_eval(Widget_Data *wd);
64static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
65static void _sub_del(void *data, Evas_Object *obj, void *event_info);
66static void _part_cursor_free(Part_Cursor *pc);
67
68static const char SIG_THEME_CHANGED[] = "theme,changed";
69
70static const Evas_Smart_Cb_Description _signals[] = {
71 {SIG_THEME_CHANGED, ""},
72 {NULL, NULL}
73};
74
75static void
76_del_hook(Evas_Object *obj)
77{
78 Widget_Data *wd = elm_widget_data_get(obj);
79 Subinfo *si;
80 Part_Cursor *pc;
81
82 if (!wd) return;
83 EINA_LIST_FREE(wd->subs, si)
84 {
85 eina_stringshare_del(si->part);
86 if (si->type == TEXT)
87 eina_stringshare_del(si->p.text.text);
88 free(si);
89 }
90 EINA_LIST_FREE(wd->parts_cursors, pc) _part_cursor_free(pc);
91 free(wd);
92}
93
94static void
95_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
96{
97 Widget_Data *wd = elm_widget_data_get(obj);
98 if (!wd) return;
99 edje_object_mirrored_set(wd->lay, rtl);
100}
101
102static void
103_theme_hook(Evas_Object *obj)
104{
105 Widget_Data *wd = elm_widget_data_get(obj);
106 if (!wd) return;
107 _elm_widget_mirrored_reload(obj);
108 _mirrored_set(obj, elm_widget_mirrored_get(obj));
109 _elm_theme_object_set(obj, wd->lay, wd->clas, wd->group, wd->style);
110 edje_object_scale_set(wd->lay, elm_widget_scale_get(obj) *
111 _elm_config->scale);
112 evas_object_smart_callback_call(obj, SIG_THEME_CHANGED, NULL);
113 _sizing_eval(wd);
114}
115
116static void
117_changed_hook(Evas_Object *obj)
118{
119 Widget_Data *wd = elm_widget_data_get(obj);
120 if (!wd) return;
121 if (wd->needs_size_calc)
122 {
123 _sizing_eval(wd);
124 wd->needs_size_calc = 0;
125 }
126}
127
128static void
129_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
130{
131 Widget_Data *wd = elm_widget_data_get(obj);
132 edje_object_signal_emit(wd->lay, emission, source);
133}
134
135static void
136_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
137{
138 Widget_Data *wd = elm_widget_data_get(obj);
139 edje_object_signal_callback_add(wd->lay, emission, source, func_cb, data);
140}
141
142static void
143_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
144{
145 Widget_Data *wd = elm_widget_data_get(obj);
146 edje_object_signal_callback_del_full(wd->lay, emission, source, func_cb,
147 data);
148}
149
150
151static void *
152_elm_layout_list_data_get(const Eina_List *list)
153{
154 Subinfo *si = eina_list_data_get(list);
155 return si->obj;
156}
157
158static Eina_Bool
159_elm_layout_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
160{
161 Widget_Data *wd = elm_widget_data_get(obj);
162 const Eina_List *items;
163 void *(*list_data_get) (const Eina_List *list);
164
165 if ((!wd) || (!wd->subs))
166 return EINA_FALSE;
167
168 /* Focus chain (This block is diferent of elm_win cycle)*/
169 if ((items = elm_widget_focus_custom_chain_get(obj)))
170 list_data_get = eina_list_data_get;
171 else
172 {
173 items = wd->subs;
174 list_data_get = _elm_layout_list_data_get;
175
176 if (!items) return EINA_FALSE;
177 }
178
179 return elm_widget_focus_list_next_get(obj, items, list_data_get, dir,
180 next);
181}
182
183static void
184_sizing_eval(Widget_Data *wd)
185{
186 Evas_Coord minw = -1, minh = -1;
187 edje_object_size_min_calc(wd->lay, &minw, &minh);
188 evas_object_size_hint_min_set(wd->obj, minw, minh);
189 evas_object_size_hint_max_set(wd->obj, -1, -1);
190}
191
192static void
193_request_sizing_eval(Widget_Data *wd)
194{
195 if (wd->needs_size_calc) return;
196 wd->needs_size_calc = 1;
197 evas_object_smart_changed(wd->obj);
198}
199
200static void
201_part_cursor_free(Part_Cursor *pc)
202{
203 eina_stringshare_del(pc->part);
204 eina_stringshare_del(pc->style);
205 eina_stringshare_del(pc->cursor);
206 free(pc);
207}
208
209static void
210_part_cursor_part_apply(const Part_Cursor *pc)
211{
212 elm_object_cursor_set(pc->obj, pc->cursor);
213 elm_object_cursor_style_set(pc->obj, pc->style);
214 elm_object_cursor_theme_search_enabled_set(pc->obj, pc->engine_only);
215}
216
217static Part_Cursor *
218_parts_cursors_find(Widget_Data *wd, const char *part)
219{
220 const Eina_List *l;
221 Part_Cursor *pc;
222 EINA_LIST_FOREACH(wd->parts_cursors, l, pc)
223 {
224 if (!strcmp(pc->part, part))
225 return pc;
226 }
227 return NULL;
228}
229
230static void
231_parts_cursors_apply(Widget_Data *wd)
232{
233 const char *file, *group;
234 const Eina_List *l;
235 Part_Cursor *pc;
236
237 edje_object_file_get(wd->lay, &file, &group);
238
239 EINA_LIST_FOREACH(wd->parts_cursors, l, pc)
240 {
241 Evas_Object *obj = (Evas_Object *)edje_object_part_object_get
242 (wd->lay, pc->part);
243
244 if (!obj)
245 {
246 pc->obj = NULL;
247 WRN("no part '%s' in group '%s' of file '%s'. "
248 "Cannot set cursor '%s'",
249 pc->part, group, file, pc->cursor);
250 continue;
251 }
252 else if (evas_object_pass_events_get(obj))
253 {
254 pc->obj = NULL;
255 WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. "
256 "Cannot set cursor '%s'",
257 pc->part, group, file, pc->cursor);
258 continue;
259 }
260
261 pc->obj = obj;
262 _part_cursor_part_apply(pc);
263 }
264}
265
266static void
267_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
268{
269 _request_sizing_eval(data);
270}
271
272static void
273_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
274{
275 Widget_Data *wd = elm_widget_data_get(obj);
276 Evas_Object *sub = event_info;
277 Eina_List *l;
278 Subinfo *si;
279 if (!wd) return;
280 EINA_LIST_FOREACH(wd->subs, l, si)
281 {
282 if (si->obj == sub)
283 {
284 evas_object_event_callback_del_full(sub,
285 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
286 _changed_size_hints,
287 wd);
288 wd->subs = eina_list_remove_list(wd->subs, l);
289 eina_stringshare_del(si->part);
290 free(si);
291 break;
292 }
293 }
294}
295
296static void
297_signal_size_eval(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
298{
299 _request_sizing_eval(data);
300}
301
302static void
303_parts_text_fix(Widget_Data *wd)
304{
305 const Eina_List *l;
306 Subinfo *si;
307
308 EINA_LIST_FOREACH(wd->subs, l, si)
309 {
310 if (si->type == TEXT)
311 edje_object_part_text_escaped_set(wd->lay, si->part, si->p.text.text);
312 }
313}
314
315static void
316_elm_layout_label_set(Evas_Object *obj, const char *part, const char *text)
317{
318 Widget_Data *wd = elm_widget_data_get(obj);
319 Subinfo *si = NULL;
320 Eina_List *l;
321 ELM_CHECK_WIDTYPE(obj, widtype);
322 if (!part) part = "elm.text";
323
324 EINA_LIST_FOREACH(wd->subs, l, si)
325 {
326 if ((si->type == TEXT) && (!strcmp(part, si->part)))
327 {
328 if (!text)
329 {
330 eina_stringshare_del(si->part);
331 eina_stringshare_del(si->p.text.text);
332 free(si);
333 edje_object_part_text_escaped_set(wd->lay, part, NULL);
334 wd->subs = eina_list_remove_list(wd->subs, l);
335 return;
336 }
337 else
338 break;
339 }
340 si = NULL;
341 }
342
343 if (!si)
344 {
345 si = ELM_NEW(Subinfo);
346 if (!si) return;
347 si->type = TEXT;
348 si->part = eina_stringshare_add(part);
349 wd->subs = eina_list_append(wd->subs, si);
350 }
351
352 eina_stringshare_replace(&si->p.text.text, text);
353 edje_object_part_text_escaped_set(wd->lay, part, text);
354 _request_sizing_eval(wd);
355}
356
357static const char *
358_elm_layout_label_get(const Evas_Object *obj, const char *part)
359{
360 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
361 Widget_Data *wd = elm_widget_data_get(obj);
362 if (!part) part = "elm.text";
363 return edje_object_part_text_get(wd->lay, part);
364}
365
366static void
367_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
368{
369 ELM_CHECK_WIDTYPE(obj, widtype);
370 Widget_Data *wd = elm_widget_data_get(obj);
371 Subinfo *si;
372 const Eina_List *l;
373 if (!wd) return;
374 EINA_SAFETY_ON_NULL_RETURN(part);
375 EINA_LIST_FOREACH(wd->subs, l, si)
376 {
377 if ((si->type == SWALLOW) && (!strcmp(part, si->part)))
378 {
379 if (content == si->obj) return;
380 evas_object_del(si->obj);
381 break;
382 }
383 }
384 if (content)
385 {
386 elm_widget_sub_object_add(obj, content);
387 evas_object_event_callback_add(content,
388 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
389 _changed_size_hints, wd);
390 if (!edje_object_part_swallow(wd->lay, part, content))
391 WRN("could not swallow %p into part '%s'", content, part);
392 si = ELM_NEW(Subinfo);
393 si->type = SWALLOW;
394 si->part = eina_stringshare_add(part);
395 si->obj = content;
396 wd->subs = eina_list_append(wd->subs, si);
397 }
398 _request_sizing_eval(wd);
399}
400
401static Evas_Object *
402_content_get_hook(const Evas_Object *obj, const char *part)
403{
404 Widget_Data *wd = elm_widget_data_get(obj);
405 const Eina_List *l;
406 Subinfo *si;
407 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
408
409 EINA_LIST_FOREACH(wd->subs, l, si)
410 {
411 if ((si->type == SWALLOW) && !strcmp(part, si->part))
412 return si->obj;
413 }
414 return NULL;
415}
416
417static Evas_Object *
418_content_unset_hook(Evas_Object *obj, const char *part)
419{
420 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
421 Widget_Data *wd = elm_widget_data_get(obj);
422 Subinfo *si;
423 const Eina_List *l;
424 if (!wd) return NULL;
425 EINA_LIST_FOREACH(wd->subs, l, si)
426 {
427 if ((si->type == SWALLOW) && (!strcmp(part, si->part)))
428 {
429 Evas_Object *content;
430 if (!si->obj) return NULL;
431 content = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */
432 elm_widget_sub_object_del(obj, content);
433 evas_object_event_callback_del_full(content,
434 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
435 _changed_size_hints, wd);
436 edje_object_part_unswallow(wd->lay, content);
437 return content;
438 }
439 }
440 return NULL;
441}
442
443EAPI Evas_Object *
444elm_layout_add(Evas_Object *parent)
445{
446 Evas_Object *obj;
447 Evas *e;
448 Widget_Data *wd;
449
450 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
451
452 ELM_SET_WIDTYPE(widtype, "layout");
453 elm_widget_type_set(obj, "layout");
454 elm_widget_sub_object_add(parent, obj);
455 elm_widget_data_set(obj, wd);
456 elm_widget_del_hook_set(obj, _del_hook);
457 elm_widget_theme_hook_set(obj, _theme_hook);
458 elm_widget_changed_hook_set(obj, _changed_hook);
459 elm_widget_can_focus_set(obj, EINA_FALSE);
460 elm_widget_focus_next_hook_set(obj, _elm_layout_focus_next_hook);
461 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
462 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
463 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
464 elm_widget_text_set_hook_set(obj, _elm_layout_label_set);
465 elm_widget_text_get_hook_set(obj, _elm_layout_label_get);
466 elm_widget_content_set_hook_set(obj, _content_set_hook);
467 elm_widget_content_get_hook_set(obj, _content_get_hook);
468 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
469
470 wd->obj = obj;
471 wd->lay = edje_object_add(e);
472 elm_widget_resize_object_set(obj, wd->lay);
473 edje_object_signal_callback_add(wd->lay, "size,eval", "elm",
474 _signal_size_eval, wd);
475
476 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
477 evas_object_smart_callbacks_descriptions_set(obj, _signals);
478
479 _mirrored_set(obj, elm_widget_mirrored_get(obj));
480 _request_sizing_eval(wd);
481 return obj;
482}
483
484EAPI Eina_Bool
485elm_layout_file_set(Evas_Object *obj, const char *file, const char *group)
486{
487 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
488 Widget_Data *wd = elm_widget_data_get(obj);
489 if (!wd) return EINA_FALSE;
490 Eina_Bool ret = edje_object_file_set(wd->lay, file, group);
491 if (ret)
492 {
493 _parts_text_fix(wd);
494 _request_sizing_eval(wd);
495 _parts_cursors_apply(wd);
496 }
497 else DBG("failed to set edje file '%s', group '%s': %s",
498 file, group,
499 edje_load_error_str(edje_object_load_error_get(wd->lay)));
500 return ret;
501}
502
503EAPI Eina_Bool
504elm_layout_theme_set(Evas_Object *obj, const char *clas, const char *group, const char *style)
505{
506 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
507 Widget_Data *wd = elm_widget_data_get(obj);
508 if (!wd) return EINA_FALSE;
509 Eina_Bool ret = _elm_theme_object_set(obj, wd->lay, clas, group, style);
510 wd->clas = clas;
511 wd->group = group;
512 wd->style = style;
513 if (ret)
514 {
515 _parts_text_fix(wd);
516 _request_sizing_eval(wd);
517 _parts_cursors_apply(wd);
518 }
519 return ret;
520}
521
522EAPI Eina_Bool
523elm_layout_box_append(Evas_Object *obj, const char *part, Evas_Object *child)
524{
525 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
526 Widget_Data *wd = elm_widget_data_get(obj);
527 Subinfo *si;
528 if (!wd) return EINA_FALSE;
529
530 if (!edje_object_part_box_append(wd->lay, part, child))
531 WRN("child %p could not be appended to box part '%s'", child, part);
532 elm_widget_sub_object_add(obj, child);
533 evas_object_event_callback_add
534 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
535
536 si = ELM_NEW(Subinfo);
537 si->type = BOX_APPEND;
538 si->part = eina_stringshare_add(part);
539 si->obj = child;
540 wd->subs = eina_list_append(wd->subs, si);
541 _request_sizing_eval(wd);
542
543 return EINA_TRUE;
544}
545
546EAPI Eina_Bool
547elm_layout_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child)
548{
549 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
550 Widget_Data *wd = elm_widget_data_get(obj);
551 Subinfo *si;
552 if (!wd) return EINA_FALSE;
553
554 if (!edje_object_part_box_prepend(wd->lay, part, child))
555 WRN("child %p could not be prepended to box part '%s'", child, part);
556 elm_widget_sub_object_add(obj, child);
557 evas_object_event_callback_add
558 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
559
560 si = ELM_NEW(Subinfo);
561 si->type = BOX_PREPEND;
562 si->part = eina_stringshare_add(part);
563 si->obj = child;
564 wd->subs = eina_list_prepend(wd->subs, si);
565 _request_sizing_eval(wd);
566
567 return EINA_TRUE;
568}
569
570static void
571_box_reference_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
572{
573 Subinfo *si = data;
574 si->p.box.reference = NULL;
575}
576
577EAPI Eina_Bool
578elm_layout_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference)
579{
580 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
581 Widget_Data *wd = elm_widget_data_get(obj);
582 Subinfo *si;
583 if (!wd) return EINA_FALSE;
584
585 if (!edje_object_part_box_insert_before(wd->lay, part, child, reference))
586 WRN("child %p could not be inserted before %p inf box part '%s'",
587 child, reference, part);
588
589 si = ELM_NEW(Subinfo);
590 si->type = BOX_INSERT_BEFORE;
591 si->part = eina_stringshare_add(part);
592 si->obj = child;
593 si->p.box.reference = reference;
594
595 elm_widget_sub_object_add(obj, child);
596 evas_object_event_callback_add
597 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
598 evas_object_event_callback_add
599 ((Evas_Object *)reference, EVAS_CALLBACK_DEL, _box_reference_del, si);
600
601 wd->subs = eina_list_append(wd->subs, si);
602 _request_sizing_eval(wd);
603
604 return EINA_TRUE;
605}
606
607EAPI Eina_Bool
608elm_layout_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos)
609{
610 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
611 Widget_Data *wd = elm_widget_data_get(obj);
612 Subinfo *si;
613 if (!wd) return EINA_FALSE;
614
615 if (!edje_object_part_box_insert_at(wd->lay, part, child, pos))
616 WRN("child %p could not be inserted at %u to box part '%s'",
617 child, pos, part);
618
619 elm_widget_sub_object_add(obj, child);
620 evas_object_event_callback_add
621 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
622
623 si = ELM_NEW(Subinfo);
624 si->type = BOX_INSERT_AT;
625 si->part = eina_stringshare_add(part);
626 si->obj = child;
627 si->p.box.pos = pos;
628 wd->subs = eina_list_append(wd->subs, si);
629 _request_sizing_eval(wd);
630
631 return EINA_TRUE;
632}
633
634static Evas_Object *
635_sub_box_remove(Widget_Data *wd, Subinfo *si)
636{
637 Evas_Object *child;
638
639 if (si->type == BOX_INSERT_BEFORE)
640 evas_object_event_callback_del_full
641 ((Evas_Object *)si->p.box.reference,
642 EVAS_CALLBACK_DEL, _box_reference_del, si);
643
644 child = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */
645 edje_object_part_box_remove(wd->lay, si->part, child);
646 elm_widget_sub_object_del(wd->obj, child);
647 return child;
648}
649
650static Evas_Object *
651_sub_table_remove(Widget_Data *wd, Subinfo *si)
652{
653 Evas_Object *child;
654
655 child = si->obj; /* si will die in _sub_del due elm_widget_sub_object_del() */
656 edje_object_part_table_unpack(wd->lay, si->part, child);
657 elm_widget_sub_object_del(wd->obj, child);
658 return child;
659}
660
661static Eina_Bool
662_sub_box_is(const Subinfo *si)
663{
664 switch (si->type)
665 {
666 case BOX_APPEND:
667 case BOX_PREPEND:
668 case BOX_INSERT_BEFORE:
669 case BOX_INSERT_AT:
670 return EINA_TRUE;
671 default:
672 return EINA_FALSE;
673 }
674}
675
676EAPI Evas_Object *
677elm_layout_box_remove(Evas_Object *obj, const char *part, Evas_Object *child)
678{
679 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
680 Widget_Data *wd = elm_widget_data_get(obj);
681 const Eina_List *l;
682 Subinfo *si;
683
684 if (!wd) return NULL;
685
686 EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
687 EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL);
688 EINA_LIST_FOREACH(wd->subs, l, si)
689 {
690 if (!_sub_box_is(si)) continue;
691 if ((si->obj == child) && (!strcmp(si->part, part)))
692 return _sub_box_remove(wd, si);
693 }
694 return NULL;
695}
696
697EAPI Eina_Bool
698elm_layout_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear)
699{
700 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
701 Widget_Data *wd = elm_widget_data_get(obj);
702 Subinfo *si;
703 Eina_List *lst;
704
705 if (!wd) return EINA_FALSE;
706 EINA_SAFETY_ON_NULL_RETURN_VAL(part, EINA_FALSE);
707
708 lst = eina_list_clone(wd->subs);
709 EINA_LIST_FREE(lst, si)
710 {
711 if (!_sub_box_is(si)) continue;
712 if (!strcmp(si->part, part))
713 {
714 Evas_Object *child = _sub_box_remove(wd, si);
715 if ((clear) && (child)) evas_object_del(child);
716 }
717 }
718 /* eventually something may not be added with layout, del them as well */
719 edje_object_part_box_remove_all(wd->lay, part, clear);
720
721 return EINA_TRUE;
722}
723
724EAPI Eina_Bool
725elm_layout_table_pack(Evas_Object *obj, const char *part, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
726{
727 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
728 Widget_Data *wd = elm_widget_data_get(obj);
729 Subinfo *si;
730 if (!wd) return EINA_FALSE;
731
732 if (!edje_object_part_table_pack
733 (wd->lay, part, child, col, row, colspan, rowspan))
734 WRN("child %p could not be packed into box part '%s' col=%uh, row=%hu, "
735 "colspan=%hu, rowspan=%hu", child, part, col, row, colspan, rowspan);
736
737 elm_widget_sub_object_add(obj, child);
738 evas_object_event_callback_add
739 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, wd);
740
741 si = ELM_NEW(Subinfo);
742 si->type = TABLE_PACK;
743 si->part = eina_stringshare_add(part);
744 si->obj = child;
745 si->p.table.col = col;
746 si->p.table.row = row;
747 si->p.table.colspan = colspan;
748 si->p.table.rowspan = rowspan;
749 wd->subs = eina_list_append(wd->subs, si);
750 _request_sizing_eval(wd);
751
752 return EINA_TRUE;
753}
754
755EAPI Evas_Object *
756elm_layout_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child)
757{
758 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
759 Widget_Data *wd = elm_widget_data_get(obj);
760 const Eina_List *l;
761 Subinfo *si;
762
763 if (!wd) return NULL;
764
765 EINA_SAFETY_ON_NULL_RETURN_VAL(part, NULL);
766 EINA_SAFETY_ON_NULL_RETURN_VAL(child, NULL);
767 EINA_LIST_FOREACH(wd->subs, l, si)
768 {
769 if (si->type != TABLE_PACK) continue;
770 if ((si->obj == child) && (!strcmp(si->part, part)))
771 return _sub_table_remove(wd, si);
772 }
773 return NULL;
774}
775
776EAPI Eina_Bool
777elm_layout_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear)
778{
779 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
780 Widget_Data *wd = elm_widget_data_get(obj);
781 Subinfo *si;
782 Eina_List *lst;
783
784 if (!wd) return EINA_FALSE;
785 EINA_SAFETY_ON_NULL_RETURN_VAL(part, EINA_FALSE);
786
787 lst = eina_list_clone(wd->subs);
788 EINA_LIST_FREE(lst, si)
789 {
790 if (si->type != TABLE_PACK) continue;
791 if (!strcmp(si->part, part))
792 {
793 Evas_Object *child = _sub_table_remove(wd, si);
794 if ((clear) && (child)) evas_object_del(child);
795 }
796 }
797 /* eventually something may not be added with layout, del them as well */
798 edje_object_part_table_clear(wd->lay, part, clear);
799
800 return EINA_TRUE;
801}
802
803EAPI Evas_Object *
804elm_layout_edje_get(const Evas_Object *obj)
805{
806 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
807 Widget_Data *wd = elm_widget_data_get(obj);
808 if (!wd) return NULL;
809 return wd->lay;
810}
811
812EAPI const char *
813elm_layout_data_get(const Evas_Object *obj, const char *key)
814{
815 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
816 Widget_Data *wd = elm_widget_data_get(obj);
817 return edje_object_data_get(wd->lay, key);
818}
819
820EAPI void
821elm_layout_sizing_eval(Evas_Object *obj)
822{
823 ELM_CHECK_WIDTYPE(obj, widtype);
824 Widget_Data *wd = elm_widget_data_get(obj);
825 EINA_SAFETY_ON_NULL_RETURN(wd);
826 _request_sizing_eval(wd);
827}
828
829EAPI Eina_Bool
830elm_layout_part_cursor_set(Evas_Object *obj, const char *part_name, const char *cursor)
831{
832 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
833 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
834 Widget_Data *wd = elm_widget_data_get(obj);
835 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
836 Evas_Object *part_obj;
837 Part_Cursor *pc;
838
839 part_obj = (Evas_Object *)edje_object_part_object_get(wd->lay, part_name);
840 if (!part_obj)
841 {
842 const char *group, *file;
843 edje_object_file_get(wd->lay, &file, &group);
844 WRN("no part '%s' in group '%s' of file '%s'. Cannot set cursor '%s'",
845 part_name, group, file, cursor);
846 return EINA_FALSE;
847 }
848 if (evas_object_pass_events_get(part_obj))
849 {
850 const char *group, *file;
851 edje_object_file_get(wd->lay, &file, &group);
852 WRN("part '%s' in group '%s' of file '%s' has mouse_events: 0. "
853 "Cannot set cursor '%s'",
854 part_name, group, file, cursor);
855 return EINA_FALSE;
856 }
857
858 pc = _parts_cursors_find(wd, part_name);
859 if (pc) eina_stringshare_replace(&pc->cursor, cursor);
860 else
861 {
862 pc = calloc(1, sizeof(*pc));
863 pc->part = eina_stringshare_add(part_name);
864 pc->cursor = eina_stringshare_add(cursor);
865 pc->style = eina_stringshare_add("default");
866 wd->parts_cursors = eina_list_append(wd->parts_cursors, pc);
867 }
868
869 pc->obj = part_obj;
870 elm_object_sub_cursor_set(part_obj, obj, pc->cursor);
871 return EINA_TRUE;
872}
873
874EAPI const char *
875elm_layout_part_cursor_get(const Evas_Object *obj, const char *part_name)
876{
877 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
878 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL);
879 Widget_Data *wd = elm_widget_data_get(obj);
880 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
881 Part_Cursor *pc = _parts_cursors_find(wd, part_name);
882 EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL);
883 EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL);
884 return elm_object_cursor_get(pc->obj);
885}
886
887EAPI Eina_Bool
888elm_layout_part_cursor_unset(Evas_Object *obj, const char *part_name)
889{
890 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
891 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
892 Widget_Data *wd = elm_widget_data_get(obj);
893 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
894 Eina_List *l;
895 Part_Cursor *pc;
896
897 EINA_LIST_FOREACH(wd->parts_cursors, l, pc)
898 {
899 if (!strcmp(part_name, pc->part))
900 {
901 if (pc->obj) elm_object_cursor_unset(pc->obj);
902 _part_cursor_free(pc);
903 wd->parts_cursors = eina_list_remove_list(wd->parts_cursors, l);
904 return EINA_TRUE;
905 }
906 }
907
908 return EINA_FALSE;
909}
910
911EAPI Eina_Bool
912elm_layout_part_cursor_style_set(Evas_Object *obj, const char *part_name, const char *style)
913{
914 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
915 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
916 Widget_Data *wd = elm_widget_data_get(obj);
917 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
918 Part_Cursor *pc = _parts_cursors_find(wd, part_name);
919 EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
920 EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
921
922 eina_stringshare_replace(&pc->style, style);
923 elm_object_cursor_style_set(pc->obj, pc->style);
924 return EINA_TRUE;
925}
926
927EAPI const char *
928elm_layout_part_cursor_style_get(const Evas_Object *obj, const char *part_name)
929{
930 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
931 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, NULL);
932 Widget_Data *wd = elm_widget_data_get(obj);
933 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
934 Part_Cursor *pc = _parts_cursors_find(wd, part_name);
935 EINA_SAFETY_ON_NULL_RETURN_VAL(pc, NULL);
936 EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, NULL);
937 return elm_object_cursor_style_get(pc->obj);
938}
939
940EAPI Eina_Bool
941elm_layout_part_cursor_engine_only_set(Evas_Object *obj, const char *part_name, Eina_Bool engine_only)
942{
943 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
944 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
945 Widget_Data *wd = elm_widget_data_get(obj);
946 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
947 Part_Cursor *pc = _parts_cursors_find(wd, part_name);
948 EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
949 EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
950
951 pc->engine_only = !!engine_only;
952 elm_object_cursor_theme_search_enabled_set(pc->obj, pc->engine_only);
953 return EINA_TRUE;
954}
955
956EAPI Eina_Bool
957elm_layout_part_cursor_engine_only_get(const Evas_Object *obj, const char *part_name)
958{
959 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
960 EINA_SAFETY_ON_NULL_RETURN_VAL(part_name, EINA_FALSE);
961 Widget_Data *wd = elm_widget_data_get(obj);
962 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
963 Part_Cursor *pc = _parts_cursors_find(wd, part_name);
964 EINA_SAFETY_ON_NULL_RETURN_VAL(pc, EINA_FALSE);
965 EINA_SAFETY_ON_NULL_RETURN_VAL(pc->obj, EINA_FALSE);
966 return elm_object_cursor_theme_search_enabled_get(pc->obj);
967}
diff --git a/libraries/elementary/src/lib/elm_layout.h b/libraries/elementary/src/lib/elm_layout.h
new file mode 100644
index 0000000..84ecbff
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_layout.h
@@ -0,0 +1,638 @@
1/**
2 * @defgroup Layout Layout
3 * @ingroup Elementary
4 *
5 * @image html img/widget/layout/preview-00.png
6 * @image latex img/widget/layout/preview-00.eps width=\textwidth
7 *
8 * @image html img/layout-predefined.png
9 * @image latex img/layout-predefined.eps width=\textwidth
10 *
11 * This is a container widget that takes a standard Edje design file and
12 * wraps it very thinly in a widget.
13 *
14 * An Edje design (theme) file has a very wide range of possibilities to
15 * describe the behavior of elements added to the Layout. Check out the Edje
16 * documentation and the EDC reference to get more information about what can
17 * be done with Edje.
18 *
19 * Just like @ref List, @ref Box, and other container widgets, any
20 * object added to the Layout will become its child, meaning that it will be
21 * deleted if the Layout is deleted, move if the Layout is moved, and so on.
22 *
23 * The Layout widget can contain as many Contents, Boxes or Tables as
24 * described in its theme file. For instance, objects can be added to
25 * different Tables by specifying the respective Table part names. The same
26 * is valid for Content and Box.
27 *
28 * The objects added as child of the Layout will behave as described in the
29 * part description where they were added. There are 3 possible types of
30 * parts where a child can be added:
31 *
32 * @section secContent Content (SWALLOW part)
33 *
34 * Only one object can be added to the @c SWALLOW part (but you still can
35 * have many @c SWALLOW parts and one object on each of them). Use the @c
36 * elm_object_content_set/get/unset functions to set, retrieve and unset
37 * objects as content of the @c SWALLOW. After being set to this part, the
38 * object size, position, visibility, clipping and other description
39 * properties will be totally controlled by the description of the given part
40 * (inside the Edje theme file).
41 *
42 * One can use @c evas_object_size_hint_* functions on the child to have some
43 * kind of control over its behavior, but the resulting behavior will still
44 * depend heavily on the @c SWALLOW part description.
45 *
46 * The Edje theme also can change the part description, based on signals or
47 * scripts running inside the theme. This change can also be animated. All of
48 * this will affect the child object set as content accordingly. The object
49 * size will be changed if the part size is changed, it will animate move if
50 * the part is moving, and so on.
51 *
52 * The following picture demonstrates a Layout widget with a child object
53 * added to its @c SWALLOW:
54 *
55 * @image html layout_swallow.png
56 * @image latex layout_swallow.eps width=\textwidth
57 *
58 * @section secBox Box (BOX part)
59 *
60 * An Edje @c BOX part is very similar to the Elementary @ref Box widget. It
61 * allows one to add objects to the box and have them distributed along its
62 * area, accordingly to the specified @a layout property (now by @a layout we
63 * mean the chosen layouting design of the Box, not the Layout widget
64 * itself).
65 *
66 * A similar effect for having a box with its position, size and other things
67 * controlled by the Layout theme would be to create an Elementary @ref Box
68 * widget and add it as a Content in the @c SWALLOW part.
69 *
70 * The main difference of using the Layout Box is that its behavior, the box
71 * properties like layouting format, padding, align, etc. will be all
72 * controlled by the theme. This means, for example, that a signal could be
73 * sent to the Layout theme (with elm_object_signal_emit()) and the theme
74 * handled the signal by changing the box padding, or align, or both. Using
75 * the Elementary @ref Box widget is not necessarily harder or easier, it
76 * just depends on the circumstances and requirements.
77 *
78 * The Layout Box can be used through the @c elm_layout_box_* set of
79 * functions.
80 *
81 * The following picture demonstrates a Layout widget with many child objects
82 * added to its @c BOX part:
83 *
84 * @image html layout_box.png
85 * @image latex layout_box.eps width=\textwidth
86 *
87 * @section secTable Table (TABLE part)
88 *
89 * Just like the @ref secBox, the Layout Table is very similar to the
90 * Elementary @ref Table widget. It allows one to add objects to the Table
91 * specifying the row and column where the object should be added, and any
92 * column or row span if necessary.
93 *
94 * Again, we could have this design by adding a @ref Table widget to the @c
95 * SWALLOW part using elm_object_part_content_set(). The same difference happens
96 * here when choosing to use the Layout Table (a @c TABLE part) instead of
97 * the @ref Table plus @c SWALLOW part. It's just a matter of convenience.
98 *
99 * The Layout Table can be used through the @c elm_layout_table_* set of
100 * functions.
101 *
102 * The following picture demonstrates a Layout widget with many child objects
103 * added to its @c TABLE part:
104 *
105 * @image html layout_table.png
106 * @image latex layout_table.eps width=\textwidth
107 *
108 * @section secPredef Predefined Layouts
109 *
110 * Another interesting thing about the Layout widget is that it offers some
111 * predefined themes that come with the default Elementary theme. These
112 * themes can be set by the call elm_layout_theme_set(), and provide some
113 * basic functionality depending on the theme used.
114 *
115 * Most of them already send some signals, some already provide a toolbar or
116 * back and next buttons.
117 *
118 * These are available predefined theme layouts. All of them have class = @c
119 * layout, group = @c application, and style = one of the following options:
120 *
121 * @li @c toolbar-content - application with toolbar and main content area
122 * @li @c toolbar-content-back - application with toolbar and main content
123 * area with a back button and title area
124 * @li @c toolbar-content-back-next - application with toolbar and main
125 * content area with a back and next buttons and title area
126 * @li @c content-back - application with a main content area with a back
127 * button and title area
128 * @li @c content-back-next - application with a main content area with a
129 * back and next buttons and title area
130 * @li @c toolbar-vbox - application with toolbar and main content area as a
131 * vertical box
132 * @li @c toolbar-table - application with toolbar and main content area as a
133 * table
134 *
135 * Supported elm_object common APIs.
136 * @li @ref elm_object_signal_emit
137 * @li @ref elm_object_signal_callback_add
138 * @li @ref elm_object_signal_callback_del
139 * @li @ref elm_object_part_text_set
140 * @li @ref elm_object_part_text_get
141 * @li @ref elm_object_part_content_set
142 * @li @ref elm_object_part_content_get
143 * @li @ref elm_object_part_content_unset
144 *
145 * @section secExamples Examples
146 *
147 * Some examples of the Layout widget can be found here:
148 * @li @ref layout_example_01
149 * @li @ref layout_example_02
150 * @li @ref layout_example_03
151 * @li @ref layout_example_edc
152 *
153 */
154
155/**
156 * Add a new layout to the parent
157 *
158 * @param parent The parent object
159 * @return The new object or NULL if it cannot be created
160 *
161 * @see elm_layout_file_set()
162 * @see elm_layout_theme_set()
163 *
164 * @ingroup Layout
165 */
166EAPI Evas_Object *elm_layout_add(Evas_Object *parent);
167
168/**
169 * Set the file that will be used as layout
170 *
171 * @param obj The layout object
172 * @param file The path to file (edj) that will be used as layout
173 * @param group The group that the layout belongs in edje file
174 *
175 * @return (1 = success, 0 = error)
176 *
177 * @ingroup Layout
178 */
179EAPI Eina_Bool elm_layout_file_set(Evas_Object *obj, const char *file, const char *group);
180
181/**
182 * Set the edje group from the elementary theme that will be used as layout
183 *
184 * @param obj The layout object
185 * @param clas the class of the group
186 * @param group the group
187 * @param style the style to used
188 *
189 * @return (1 = success, 0 = error)
190 *
191 * @ingroup Layout
192 */
193EAPI Eina_Bool elm_layout_theme_set(Evas_Object *obj, const char *clas, const char *group, const char *style);
194
195/**
196 * Append child to layout box part.
197 *
198 * @param obj the layout object
199 * @param part the box part to which the object will be appended.
200 * @param child the child object to append to box.
201 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
202 *
203 * Once the object is appended, it will become child of the layout. Its
204 * lifetime will be bound to the layout, whenever the layout dies the child
205 * will be deleted automatically. One should use elm_layout_box_remove() to
206 * make this layout forget about the object.
207 *
208 * @see elm_layout_box_prepend()
209 * @see elm_layout_box_insert_before()
210 * @see elm_layout_box_insert_at()
211 * @see elm_layout_box_remove()
212 *
213 * @ingroup Layout
214 */
215EAPI Eina_Bool elm_layout_box_append(Evas_Object *obj, const char *part, Evas_Object *child);
216
217/**
218 * Prepend child to layout box part.
219 *
220 * @param obj the layout object
221 * @param part the box part to prepend.
222 * @param child the child object to prepend to box.
223 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
224 *
225 * Once the object is prepended, it will become child of the layout. Its
226 * lifetime will be bound to the layout, whenever the layout dies the child
227 * will be deleted automatically. One should use elm_layout_box_remove() to
228 * make this layout forget about the object.
229 *
230 * @see elm_layout_box_append()
231 * @see elm_layout_box_insert_before()
232 * @see elm_layout_box_insert_at()
233 * @see elm_layout_box_remove()
234 *
235 * @ingroup Layout
236 */
237EAPI Eina_Bool elm_layout_box_prepend(Evas_Object *obj, const char *part, Evas_Object *child);
238
239/**
240 * Insert child to layout box part before a reference object.
241 *
242 * @param obj the layout object
243 * @param part the box part to insert.
244 * @param child the child object to insert into box.
245 * @param reference another reference object to insert before in box.
246 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
247 *
248 * Once the object is inserted, it will become child of the layout. Its
249 * lifetime will be bound to the layout, whenever the layout dies the child
250 * will be deleted automatically. One should use elm_layout_box_remove() to
251 * make this layout forget about the object.
252 *
253 * @see elm_layout_box_append()
254 * @see elm_layout_box_prepend()
255 * @see elm_layout_box_insert_before()
256 * @see elm_layout_box_remove()
257 *
258 * @ingroup Layout
259 */
260EAPI Eina_Bool elm_layout_box_insert_before(Evas_Object *obj, const char *part, Evas_Object *child, const Evas_Object *reference);
261
262/**
263 * Insert child to layout box part at a given position.
264 *
265 * @param obj the layout object
266 * @param part the box part to insert.
267 * @param child the child object to insert into box.
268 * @param pos the numeric position >=0 to insert the child.
269 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
270 *
271 * Once the object is inserted, it will become child of the layout. Its
272 * lifetime will be bound to the layout, whenever the layout dies the child
273 * will be deleted automatically. One should use elm_layout_box_remove() to
274 * make this layout forget about the object.
275 *
276 * @see elm_layout_box_append()
277 * @see elm_layout_box_prepend()
278 * @see elm_layout_box_insert_before()
279 * @see elm_layout_box_remove()
280 *
281 * @ingroup Layout
282 */
283EAPI Eina_Bool elm_layout_box_insert_at(Evas_Object *obj, const char *part, Evas_Object *child, unsigned int pos);
284
285/**
286 * Remove a child of the given part box.
287 *
288 * @param obj The layout object
289 * @param part The box part name to remove child.
290 * @param child The object to remove from box.
291 * @return The object that was being used, or NULL if not found.
292 *
293 * The object will be removed from the box part and its lifetime will
294 * not be handled by the layout anymore. This is equivalent to
295 * elm_object_part_content_unset() for box.
296 *
297 * @see elm_layout_box_append()
298 * @see elm_layout_box_remove_all()
299 *
300 * @ingroup Layout
301 */
302EAPI Evas_Object *elm_layout_box_remove(Evas_Object *obj, const char *part, Evas_Object *child);
303
304/**
305 * Remove all children of the given part box.
306 *
307 * @param obj The layout object
308 * @param part The box part name to remove child.
309 * @param clear If EINA_TRUE, then all objects will be deleted as
310 * well, otherwise they will just be removed and will be
311 * dangling on the canvas.
312 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
313 *
314 * The objects will be removed from the box part and their lifetime will
315 * not be handled by the layout anymore. This is equivalent to
316 * elm_layout_box_remove() for all box children.
317 *
318 * @see elm_layout_box_append()
319 * @see elm_layout_box_remove()
320 *
321 * @ingroup Layout
322 */
323EAPI Eina_Bool elm_layout_box_remove_all(Evas_Object *obj, const char *part, Eina_Bool clear);
324
325/**
326 * Insert child to layout table part.
327 *
328 * @param obj the layout object
329 * @param part the box part to pack child.
330 * @param child_obj the child object to pack into table.
331 * @param col the column to which the child should be added. (>= 0)
332 * @param row the row to which the child should be added. (>= 0)
333 * @param colspan how many columns should be used to store this object. (>=
334 * 1)
335 * @param rowspan how many rows should be used to store this object. (>= 1)
336 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
337 *
338 * Once the object is inserted, it will become child of the table. Its
339 * lifetime will be bound to the layout, and whenever the layout dies the
340 * child will be deleted automatically. One should use
341 * elm_layout_table_remove() to make this layout forget about the object.
342 *
343 * If @p colspan or @p rowspan are bigger than 1, that object will occupy
344 * more space than a single cell. For instance, the following code:
345 * @code
346 * elm_layout_table_pack(layout, "table_part", child, 0, 1, 3, 1);
347 * @endcode
348 *
349 * Would result in an object being added like the following picture:
350 *
351 * @image html layout_colspan.png
352 * @image latex layout_colspan.eps width=\textwidth
353 *
354 * @see elm_layout_table_unpack()
355 * @see elm_layout_table_clear()
356 *
357 * @ingroup Layout
358 */
359EAPI Eina_Bool 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);
360
361/**
362 * Unpack (remove) a child of the given part table.
363 *
364 * @param obj The layout object
365 * @param part The table part name to remove child.
366 * @param child_obj The object to remove from table.
367 * @return The object that was being used, or NULL if not found.
368 *
369 * The object will be unpacked from the table part and its lifetime
370 * will not be handled by the layout anymore. This is equivalent to
371 * elm_object_part_content_unset() for table.
372 *
373 * @see elm_layout_table_pack()
374 * @see elm_layout_table_clear()
375 *
376 * @ingroup Layout
377 */
378EAPI Evas_Object *elm_layout_table_unpack(Evas_Object *obj, const char *part, Evas_Object *child_obj);
379
380/**
381 * Remove all the child objects of the given part table.
382 *
383 * @param obj The layout object
384 * @param part The table part name to remove child.
385 * @param clear If EINA_TRUE, then all objects will be deleted as
386 * well, otherwise they will just be removed and will be
387 * dangling on the canvas.
388 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
389 *
390 * The objects will be removed from the table part and their lifetime will
391 * not be handled by the layout anymore. This is equivalent to
392 * elm_layout_table_unpack() for all table children.
393 *
394 * @see elm_layout_table_pack()
395 * @see elm_layout_table_unpack()
396 *
397 * @ingroup Layout
398 */
399EAPI Eina_Bool elm_layout_table_clear(Evas_Object *obj, const char *part, Eina_Bool clear);
400
401/**
402 * Get the edje layout
403 *
404 * @param obj The layout object
405 *
406 * @return A Evas_Object with the edje layout settings loaded
407 * with function elm_layout_file_set
408 *
409 * This returns the edje object. It is not expected to be used to then
410 * swallow objects via edje_object_part_swallow() for example. Use
411 * elm_object_part_content_set() instead so child object handling and sizing is
412 * done properly.
413 *
414 * @note This function should only be used if you really need to call some
415 * low level Edje function on this edje object. All the common stuff (setting
416 * text, emitting signals, hooking callbacks to signals, etc.) can be done
417 * with proper elementary functions.
418 *
419 * @see elm_object_signal_callback_add()
420 * @see elm_object_signal_emit()
421 * @see elm_object_part_text_set()
422 * @see elm_object_part_content_set()
423 * @see elm_layout_box_append()
424 * @see elm_layout_table_pack()
425 * @see elm_layout_data_get()
426 *
427 * @ingroup Layout
428 */
429EAPI Evas_Object *elm_layout_edje_get(const Evas_Object *obj);
430
431/**
432 * Get the edje data from the given layout
433 *
434 * @param obj The layout object
435 * @param key The data key
436 *
437 * @return The edje data string
438 *
439 * This function fetches data specified inside the edje theme of this layout.
440 * This function return NULL if data is not found.
441 *
442 * In EDC this comes from a data block within the group block that @p
443 * obj was loaded from. E.g.
444 *
445 * @code
446 * collections {
447 * group {
448 * name: "a_group";
449 * data {
450 * item: "key1" "value1";
451 * item: "key2" "value2";
452 * }
453 * }
454 * }
455 * @endcode
456 *
457 * @ingroup Layout
458 */
459EAPI const char *elm_layout_data_get(const Evas_Object *obj, const char *key);
460
461/**
462 * Eval sizing
463 *
464 * @param obj The layout object
465 *
466 * Manually forces a sizing re-evaluation. This is useful when the minimum
467 * size required by the edje theme of this layout has changed. The change on
468 * the minimum size required by the edje theme is not immediately reported to
469 * the elementary layout, so one needs to call this function in order to tell
470 * the widget (layout) that it needs to reevaluate its own size.
471 *
472 * The minimum size of the theme is calculated based on minimum size of
473 * parts, the size of elements inside containers like box and table, etc. All
474 * of this can change due to state changes, and that's when this function
475 * should be called.
476 *
477 * Also note that a standard signal of "size,eval" "elm" emitted from the
478 * edje object will cause this to happen too.
479 *
480 * @ingroup Layout
481 */
482EAPI void elm_layout_sizing_eval(Evas_Object *obj);
483
484/**
485 * Sets a specific cursor for an edje part.
486 *
487 * @param obj The layout object.
488 * @param part_name a part from loaded edje group.
489 * @param cursor cursor name to use, see Elementary_Cursor.h
490 *
491 * @return EINA_TRUE on success or EINA_FALSE on failure, that may be
492 * part not exists or it has "mouse_events: 0".
493 *
494 * @ingroup Layout
495 */
496EAPI Eina_Bool elm_layout_part_cursor_set(Evas_Object *obj, const char *part_name, const char *cursor);
497
498/**
499 * Get the cursor to be shown when mouse is over an edje part
500 *
501 * @param obj The layout object.
502 * @param part_name a part from loaded edje group.
503 * @return the cursor name.
504 *
505 * @ingroup Layout
506 */
507EAPI const char *elm_layout_part_cursor_get(const Evas_Object *obj, const char *part_name);
508
509/**
510 * Unsets a cursor previously set with elm_layout_part_cursor_set().
511 *
512 * @param obj The layout object.
513 * @param part_name a part from loaded edje group, that had a cursor set
514 * with elm_layout_part_cursor_set().
515 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
516 *
517 * @ingroup Layout
518 */
519EAPI Eina_Bool elm_layout_part_cursor_unset(Evas_Object *obj, const char *part_name);
520
521/**
522 * Sets a specific cursor style for an edje part.
523 *
524 * @param obj The layout object.
525 * @param part_name a part from loaded edje group.
526 * @param style the theme style to use (default, transparent, ...)
527 *
528 * @return EINA_TRUE on success or EINA_FALSE on failure, that may be
529 * part not exists or it did not had a cursor set.
530 *
531 * @ingroup Layout
532 */
533EAPI Eina_Bool elm_layout_part_cursor_style_set(Evas_Object *obj, const char *part_name, const char *style);
534
535/**
536 * Gets a specific cursor style for an edje part.
537 *
538 * @param obj The layout object.
539 * @param part_name a part from loaded edje group.
540 *
541 * @return the theme style in use, defaults to "default". If the
542 * object does not have a cursor set, then NULL is returned.
543 *
544 * @ingroup Layout
545 */
546EAPI const char *elm_layout_part_cursor_style_get(const Evas_Object *obj, const char *part_name);
547
548/**
549 * Sets if the cursor set should be searched on the theme or should use
550 * the provided by the engine, only.
551 *
552 * @note before you set if should look on theme you should define a
553 * cursor with elm_layout_part_cursor_set(). By default it will only
554 * look for cursors provided by the engine.
555 *
556 * @param obj The layout object.
557 * @param part_name a part from loaded edje group.
558 * @param engine_only if cursors should be just provided by the engine (EINA_TRUE)
559 * or should also search on widget's theme as well (EINA_FALSE)
560 *
561 * @return EINA_TRUE on success or EINA_FALSE on failure, that may be
562 * part not exists or it did not had a cursor set.
563 *
564 * @ingroup Layout
565 */
566EAPI Eina_Bool elm_layout_part_cursor_engine_only_set(Evas_Object *obj, const char *part_name, Eina_Bool engine_only);
567
568/**
569 * Gets a specific cursor engine_only for an edje part.
570 *
571 * @param obj The layout object.
572 * @param part_name a part from loaded edje group.
573 *
574 * @return whenever the cursor is just provided by engine or also from theme.
575 *
576 * @ingroup Layout
577 */
578EAPI Eina_Bool elm_layout_part_cursor_engine_only_get(const Evas_Object *obj, const char *part_name);
579
580/**
581 * @def elm_layout_icon_set
582 * Convenience macro to set the icon object in a layout that follows the
583 * Elementary naming convention for its parts.
584 *
585 * @ingroup Layout
586 */
587#define elm_layout_icon_set(_ly, _obj) \
588 do { \
589 const char *sig; \
590 elm_object_part_content_set((_ly), "elm.swallow.icon", (_obj)); \
591 if ((_obj)) sig = "elm,state,icon,visible"; \
592 else sig = "elm,state,icon,hidden"; \
593 elm_object_signal_emit((_ly), sig, "elm"); \
594 } while (0)
595
596/**
597 * @def elm_layout_icon_get
598 * Convenience macro to get the icon object from a layout that follows the
599 * Elementary naming convention for its parts.
600 *
601 * @ingroup Layout
602 */
603#define elm_layout_icon_get(_ly) \
604 elm_object_part_content_get((_ly), "elm.swallow.icon")
605
606/**
607 * @def elm_layout_end_set
608 * Convenience macro to set the end object in a layout that follows the
609 * Elementary naming convention for its parts.
610 *
611 * @ingroup Layout
612 */
613#define elm_layout_end_set(_ly, _obj) \
614 do { \
615 const char *sig; \
616 elm_object_part_content_set((_ly), "elm.swallow.end", (_obj)); \
617 if ((_obj)) sig = "elm,state,end,visible"; \
618 else sig = "elm,state,end,hidden"; \
619 elm_object_signal_emit((_ly), sig, "elm"); \
620 } while (0)
621
622/**
623 * @def elm_layout_end_get
624 * Convenience macro to get the end object in a layout that follows the
625 * Elementary naming convention for its parts.
626 *
627 * @ingroup Layout
628 */
629#define elm_layout_end_get(_ly) \
630 elm_object_part_content_get((_ly), "elm.swallow.end")
631
632/* smart callbacks called:
633 * "theme,changed" - when elm theme is changed.
634 */
635
636/**
637 * @}
638 */
diff --git a/libraries/elementary/src/lib/elm_list.c b/libraries/elementary/src/lib/elm_list.c
new file mode 100644
index 0000000..d370baa
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_list.c
@@ -0,0 +1,2004 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4
5#define SWIPE_MOVES 12
6
7typedef struct _Widget_Data Widget_Data;
8typedef struct _Elm_List_Item Elm_List_Item;
9
10struct _Widget_Data
11{
12 Evas_Object *scr, *box, *self;
13 Eina_List *items, *selected, *to_delete;
14 Elm_Object_Item *last_selected_item;
15 Elm_List_Mode mode;
16 Elm_List_Mode h_mode;
17 Evas_Coord minw[2], minh[2];
18 Elm_Object_Select_Mode select_mode;
19 int walking;
20 int movements;
21 struct
22 {
23 Evas_Coord x, y;
24 } history[SWIPE_MOVES];
25 Eina_Bool scr_minw : 1;
26 Eina_Bool scr_minh : 1;
27 Eina_Bool swipe : 1;
28 Eina_Bool fix_pending : 1;
29 Eina_Bool on_hold : 1;
30 Eina_Bool multi : 1;
31 Eina_Bool longpressed : 1;
32 Eina_Bool wasselected : 1;
33};
34
35struct _Elm_List_Item
36{
37 ELM_WIDGET_ITEM;
38 Widget_Data *wd;
39 Eina_List *node;
40 const char *label;
41 Evas_Object *icon, *end;
42 Evas_Smart_Cb func;
43 Ecore_Timer *long_timer;
44 Ecore_Timer *swipe_timer;
45 Eina_Bool deleted : 1;
46 Eina_Bool even : 1;
47 Eina_Bool is_even : 1;
48 Eina_Bool is_separator : 1;
49 Eina_Bool fixed : 1;
50 Eina_Bool selected : 1;
51 Eina_Bool highlighted : 1;
52 Eina_Bool dummy_icon : 1;
53 Eina_Bool dummy_end : 1;
54};
55
56static const char *widtype = NULL;
57static void _del_hook(Evas_Object *obj);
58static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
59static void _theme_hook(Evas_Object *obj);
60static void _sizing_eval(Evas_Object *obj);
61static void _disable_hook(Evas_Object *obj);
62static void _on_focus_hook(void *data, Evas_Object *obj);
63static void _signal_emit_hook(Evas_Object *obj, const char *emission, const char *source);
64static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
65static void _sub_del(void *data, Evas_Object *obj, void *event_info);
66static void _fix_items(Evas_Object *obj);
67static void _mouse_down(void *data, Evas *evas, Evas_Object *obj, void *event_info);
68static void _mouse_up(void *data, Evas *evas, Evas_Object *obj, void *event_info);
69static void _mouse_move(void *data, Evas *evas, Evas_Object *obj, void *event_info);
70static void _edge_left(void *data, Evas_Object *scr, void *event_info);
71static void _edge_right(void *data, Evas_Object *scr, void *event_info);
72static void _edge_top(void *data, Evas_Object *scr, void *event_info);
73static void _edge_bottom(void *data, Evas_Object *scr, void *event_info);
74static Eina_Bool _item_multi_select_up(Widget_Data *wd);
75static Eina_Bool _item_multi_select_down(Widget_Data *wd);
76static Eina_Bool _item_single_select_up(Widget_Data *wd);
77static Eina_Bool _item_single_select_down(Widget_Data *wd);
78static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
79 Evas_Callback_Type type, void *event_info);
80static Eina_Bool _deselect_all_items(Widget_Data *wd);
81
82static const char SIG_ACTIVATED[] = "activated";
83static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
84static const char SIG_SELECTED[] = "selected";
85static const char SIG_UNSELECTED[] = "unselected";
86static const char SIG_LONGPRESSED[] = "longpressed";
87static const char SIG_EDGE_TOP[] = "edge,top";
88static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
89static const char SIG_EDGE_LEFT[] = "edge,left";
90static const char SIG_EDGE_RIGHT[] = "edge,right";
91
92static const Evas_Smart_Cb_Description _signals[] = {
93 {SIG_ACTIVATED, ""},
94 {SIG_CLICKED_DOUBLE, ""},
95 {SIG_SELECTED, ""},
96 {SIG_UNSELECTED, ""},
97 {SIG_LONGPRESSED, ""},
98 {SIG_EDGE_TOP, ""},
99 {SIG_EDGE_BOTTOM, ""},
100 {SIG_EDGE_LEFT, ""},
101 {SIG_EDGE_RIGHT, ""},
102 {NULL, NULL}
103};
104
105#define ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ...) \
106 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, __VA_ARGS__); \
107if (((Elm_List_Item *)it)->deleted) \
108{ \
109 ERR("ERROR: "#it" has been DELETED.\n"); \
110 return __VA_ARGS__; \
111}
112
113static inline void
114_elm_list_item_free(Elm_List_Item *it)
115{
116 evas_object_event_callback_del_full
117 (VIEW(it), EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, it);
118 evas_object_event_callback_del_full
119 (VIEW(it), EVAS_CALLBACK_MOUSE_UP, _mouse_up, it);
120 evas_object_event_callback_del_full
121 (VIEW(it), EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, it);
122
123 if (it->icon)
124 evas_object_event_callback_del_full
125 (it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
126 _changed_size_hints, WIDGET(it));
127
128 if (it->end)
129 evas_object_event_callback_del_full
130 (it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
131 _changed_size_hints, WIDGET(it));
132
133 eina_stringshare_del(it->label);
134
135 if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
136 it->swipe_timer = NULL;
137 if (it->long_timer) ecore_timer_del(it->long_timer);
138 it->long_timer = NULL;
139 if (it->icon) evas_object_del(it->icon);
140 if (it->end) evas_object_del(it->end);
141}
142
143static Eina_Bool
144_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
145{
146 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
147 Evas_Event_Key_Down *ev = event_info;
148 Widget_Data *wd = elm_widget_data_get(obj);
149 if (!wd) return EINA_FALSE;
150 if (!wd->items) return EINA_FALSE;
151 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
152 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
153
154 Elm_List_Item *it = NULL;
155 Evas_Coord x = 0;
156 Evas_Coord y = 0;
157 Evas_Coord step_x = 0;
158 Evas_Coord step_y = 0;
159 Evas_Coord v_w = 0;
160 Evas_Coord v_h = 0;
161 Evas_Coord page_x = 0;
162 Evas_Coord page_y = 0;
163
164 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
165 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
166 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
167 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
168
169 /* TODO: fix logic for horizontal mode */
170 if ((!strcmp(ev->keyname, "Left")) ||
171 ((!strcmp(ev->keyname, "KP_Left")) && !ev->string))
172 {
173 if ((wd->h_mode) &&
174 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
175 (_item_multi_select_up(wd)))
176 || (_item_single_select_up(wd))))
177 {
178 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
179 return EINA_TRUE;
180 }
181 else
182 x -= step_x;
183 }
184 else if ((!strcmp(ev->keyname, "Right")) ||
185 ((!strcmp(ev->keyname, "KP_Right")) && !ev->string))
186 {
187 if ((wd->h_mode) &&
188 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
189 (_item_multi_select_down(wd)))
190 || (_item_single_select_down(wd))))
191 {
192 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
193 return EINA_TRUE;
194 }
195 else
196 x += step_x;
197 }
198 else if ((!strcmp(ev->keyname, "Up")) ||
199 ((!strcmp(ev->keyname, "KP_Up")) && !ev->string))
200 {
201 if ((!wd->h_mode) &&
202 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
203 (_item_multi_select_up(wd)))
204 || (_item_single_select_up(wd))))
205 {
206 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
207 return EINA_TRUE;
208 }
209 else
210 y -= step_y;
211 }
212 else if ((!strcmp(ev->keyname, "Down")) ||
213 ((!strcmp(ev->keyname, "KP_Down")) && !ev->string))
214 {
215 if ((!wd->h_mode) &&
216 (((evas_key_modifier_is_set(ev->modifiers, "Shift")) &&
217 (_item_multi_select_down(wd)))
218 || (_item_single_select_down(wd))))
219 {
220 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
221 return EINA_TRUE;
222 }
223 else
224 y += step_y;
225 }
226 else if ((!strcmp(ev->keyname, "Home")) ||
227 ((!strcmp(ev->keyname, "KP_Home")) && !ev->string))
228 {
229 it = eina_list_data_get(wd->items);
230 elm_list_item_bring_in((Elm_Object_Item *)it);
231 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
232 return EINA_TRUE;
233 }
234 else if ((!strcmp(ev->keyname, "End")) ||
235 ((!strcmp(ev->keyname, "KP_End")) && !ev->string))
236 {
237 it = eina_list_data_get(eina_list_last(wd->items));
238 elm_list_item_bring_in((Elm_Object_Item *)it);
239 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
240 return EINA_TRUE;
241 }
242 else if ((!strcmp(ev->keyname, "Prior")) ||
243 ((!strcmp(ev->keyname, "KP_Prior")) && !ev->string))
244 {
245 if (wd->h_mode)
246 {
247 if (page_x < 0)
248 x -= -(page_x * v_w) / 100;
249 else
250 x -= page_x;
251 }
252 else
253 {
254 if (page_y < 0)
255 y -= -(page_y * v_h) / 100;
256 else
257 y -= page_y;
258 }
259 }
260 else if ((!strcmp(ev->keyname, "Next")) ||
261 ((!strcmp(ev->keyname, "KP_Next")) && !ev->string))
262 {
263 if (wd->h_mode)
264 {
265 if (page_x < 0)
266 x += -(page_x * v_w) / 100;
267 else
268 x += page_x;
269 }
270 else
271 {
272 if (page_y < 0)
273 y += -(page_y * v_h) / 100;
274 else
275 y += page_y;
276 }
277 }
278 else if (((!strcmp(ev->keyname, "Return")) ||
279 (!strcmp(ev->keyname, "KP_Enter")) ||
280 (!strcmp(ev->keyname, "space")))
281 && (!wd->multi) && (wd->selected))
282 {
283 it = (Elm_List_Item *) elm_list_selected_item_get(obj);
284 evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
285 }
286 else if (!strcmp(ev->keyname, "Escape"))
287 {
288 if (!_deselect_all_items(wd)) return EINA_FALSE;
289 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
290 return EINA_TRUE;
291 }
292 else return EINA_FALSE;
293
294 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
295 elm_smart_scroller_child_pos_set(wd->scr, x, y);
296 return EINA_TRUE;
297}
298
299static void
300_translate_hook(Evas_Object *obj)
301{
302 evas_object_smart_callback_call(obj, "language,changed", NULL);
303}
304
305static Eina_Bool
306_deselect_all_items(Widget_Data *wd)
307{
308 if (!wd->selected) return EINA_FALSE;
309 while (wd->selected)
310 elm_list_item_selected_set((Elm_Object_Item *) wd->selected->data,
311 EINA_FALSE);
312
313 return EINA_TRUE;
314}
315
316static Eina_Bool
317_item_multi_select_up(Widget_Data *wd)
318{
319 if (!wd->selected) return EINA_FALSE;
320 if (!wd->multi) return EINA_FALSE;
321
322 Elm_Object_Item *prev = elm_list_item_prev(wd->last_selected_item);
323 if (!prev) return EINA_TRUE;
324
325 if (elm_list_item_selected_get(prev))
326 {
327 elm_list_item_selected_set(wd->last_selected_item, EINA_FALSE);
328 wd->last_selected_item = prev;
329 elm_list_item_show(wd->last_selected_item);
330 }
331 else
332 {
333 elm_list_item_selected_set(prev, EINA_TRUE);
334 elm_list_item_show(prev);
335 }
336 return EINA_TRUE;
337}
338
339static Eina_Bool
340_item_multi_select_down(Widget_Data *wd)
341{
342 if (!wd->selected) return EINA_FALSE;
343 if (!wd->multi) return EINA_FALSE;
344
345 Elm_Object_Item *next = elm_list_item_next(wd->last_selected_item);
346 if (!next) return EINA_TRUE;
347
348 if (elm_list_item_selected_get(next))
349 {
350 elm_list_item_selected_set(wd->last_selected_item, EINA_FALSE);
351 wd->last_selected_item = next;
352 elm_list_item_show(wd->last_selected_item);
353 }
354 else
355 {
356 elm_list_item_selected_set(next, EINA_TRUE);
357 elm_list_item_show(next);
358 }
359 return EINA_TRUE;
360}
361
362static Eina_Bool
363_item_single_select_up(Widget_Data *wd)
364{
365 Elm_Object_Item *prev;
366
367 if (!wd->selected) prev = eina_list_data_get(eina_list_last(wd->items));
368 else prev = elm_list_item_prev(wd->last_selected_item);
369 if (!prev) return EINA_FALSE;
370
371 _deselect_all_items(wd);
372
373 elm_list_item_selected_set(prev, EINA_TRUE);
374 elm_list_item_show(prev);
375 return EINA_TRUE;
376}
377
378static Eina_Bool
379_item_single_select_down(Widget_Data *wd)
380{
381 Elm_Object_Item *next;
382
383 if (!wd->selected) next = eina_list_data_get(wd->items);
384 else next = elm_list_item_next(wd->last_selected_item);
385 if (!next) return EINA_FALSE;
386
387 _deselect_all_items(wd);
388
389 elm_list_item_selected_set(next, EINA_TRUE);
390 elm_list_item_show(next);
391 return EINA_TRUE;
392}
393
394static void
395_elm_list_process_deletions(Widget_Data *wd)
396{
397 Elm_List_Item *it;
398
399 wd->walking++; // avoid nested deletion and also _sub_del() fix_items
400
401 EINA_LIST_FREE(wd->to_delete, it)
402 {
403 wd->items = eina_list_remove_list(wd->items, it->node);
404 _elm_list_item_free(it);
405 elm_widget_item_free(it);
406 }
407
408 wd->walking--;
409}
410
411static inline void
412_elm_list_walk(Widget_Data *wd)
413{
414 if (wd->walking < 0)
415 {
416 ERR("ERROR: walking was negative. fixed!\n");
417 wd->walking = 0;
418 }
419 wd->walking++;
420}
421
422static inline void
423_elm_list_unwalk(Widget_Data *wd)
424{
425 wd->walking--;
426 if (wd->walking < 0)
427 {
428 ERR("ERROR: walking became negative. fixed!\n");
429 wd->walking = 0;
430 }
431
432 if (wd->walking)
433 return;
434
435 if (wd->to_delete)
436 _elm_list_process_deletions(wd);
437
438 if (wd->fix_pending)
439 {
440 wd->fix_pending = EINA_FALSE;
441 _fix_items(wd->self);
442 _sizing_eval(wd->self);
443 }
444}
445
446static void
447_del_pre_hook(Evas_Object *obj)
448{
449 Widget_Data *wd = elm_widget_data_get(obj);
450 const Eina_List *l;
451 Elm_List_Item *it;
452
453 evas_object_smart_callback_del(obj, "sub-object-del", _sub_del);
454
455 if (!wd) return;
456
457 EINA_LIST_FOREACH(wd->items, l, it)
458 {
459 if (it->icon)
460 evas_object_event_callback_del(it->icon,
461 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
462 _changed_size_hints);
463 if (it->end)
464 evas_object_event_callback_del(it->end,
465 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
466 _changed_size_hints);
467 }
468
469 evas_object_event_callback_del(wd->scr,
470 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
471 _changed_size_hints);
472 evas_object_event_callback_del(wd->box,
473 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
474 _changed_size_hints);
475}
476
477static void
478_del_hook(Evas_Object *obj)
479{
480 Widget_Data *wd = elm_widget_data_get(obj);
481 Elm_List_Item *it;
482 Eina_List *n;
483
484 if (!wd) return;
485 if (wd->walking)
486 ERR("ERROR: list deleted while walking.\n");
487
488 _elm_list_walk(wd);
489 EINA_LIST_FOREACH(wd->items, n, it) elm_widget_item_pre_notify_del(it);
490 _elm_list_unwalk(wd);
491 if (wd->to_delete)
492 ERR("ERROR: leaking nodes!\n");
493
494 EINA_LIST_FREE(wd->items, it)
495 {
496 _elm_list_item_free(it);
497 elm_widget_item_free(it);
498 }
499 eina_list_free(wd->selected);
500 free(wd);
501}
502
503static void
504_show_region_hook(void *data, Evas_Object *obj)
505{
506 Widget_Data *wd = elm_widget_data_get(data);
507 Evas_Coord x, y, w, h;
508 if (!wd) return;
509 elm_widget_show_region_get(obj, &x, &y, &w, &h);
510 elm_smart_scroller_child_region_set(wd->scr, x, y, w, h);
511}
512
513static void
514_disable_hook(Evas_Object *obj)
515{
516 Widget_Data *wd = elm_widget_data_get(obj);
517 if (!wd) return;
518 if (elm_widget_disabled_get(obj))
519 {
520 _signal_emit_hook(obj, "elm,state,disabled", "elm");
521 elm_widget_scroll_freeze_push(obj);
522 elm_widget_scroll_hold_push(obj);
523 /* FIXME: if we get to have a way to only un-highlight items
524 * in the future, keeping them selected... */
525 _deselect_all_items(wd);
526 }
527 else
528 {
529 _signal_emit_hook(obj, "elm,state,enabled", "elm");
530 elm_widget_scroll_freeze_pop(obj);
531 elm_widget_scroll_hold_pop(obj);
532 }
533}
534
535static void
536_sizing_eval(Evas_Object *obj)
537{
538
539 Widget_Data *wd = elm_widget_data_get(obj);
540 if (!wd) return;
541 Evas_Coord vw, vh, minw, minh, maxw, maxh, w, h, vmw, vmh;
542 double xw, yw;
543
544 evas_object_size_hint_min_get(wd->box, &minw, &minh);
545 evas_object_size_hint_max_get(wd->box, &maxw, &maxh);
546 evas_object_size_hint_weight_get(wd->box, &xw, &yw);
547 if (!wd->scr) return;
548 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
549 if (xw > 0.0)
550 {
551 if ((minw > 0) && (vw < minw)) vw = minw;
552 else if ((maxw > 0) && (vw > maxw)) vw = maxw;
553 }
554 else if (minw > 0) vw = minw;
555 if (yw > 0.0)
556 {
557 if ((minh > 0) && (vh < minh)) vh = minh;
558 else if ((maxh > 0) && (vh > maxh)) vh = maxh;
559 }
560 else if (minh > 0) vh = minh;
561 evas_object_resize(wd->box, vw, vh);
562 w = -1;
563 h = -1;
564 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
565 &vmw, &vmh);
566 if (wd->scr_minw) w = vmw + minw;
567 if (wd->scr_minh) h = vmh + minh;
568
569 evas_object_size_hint_max_get(obj, &maxw, &maxh);
570 if ((maxw > 0) && (w > maxw))
571 w = maxw;
572 if ((maxh > 0) && (h > maxh))
573 h = maxh;
574
575 evas_object_size_hint_min_set(obj, w, h);
576}
577
578static void
579_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
580{
581 Widget_Data *wd = elm_widget_data_get(obj);
582 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
583 emission, source);
584}
585
586static void
587_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
588{
589 Widget_Data *wd = elm_widget_data_get(obj);
590 edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
591 emission, source, func_cb, data);
592}
593
594static void
595_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
596{
597 Widget_Data *wd = elm_widget_data_get(obj);
598 edje_object_signal_callback_del_full(
599 elm_smart_scroller_edje_object_get(wd->scr),
600 emission, source, func_cb, data);
601}
602
603static void
604_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
605{
606 Widget_Data *wd = elm_widget_data_get(obj);
607 Elm_List_Item *it;
608 Eina_List *n;
609
610 if (!wd) return;
611 if (wd->scr)
612 elm_smart_scroller_mirrored_set(wd->scr, rtl);
613
614 EINA_LIST_FOREACH(wd->items, n, it)
615 edje_object_mirrored_set(VIEW(it), rtl);
616}
617
618static void
619_theme_hook(Evas_Object *obj)
620{
621 Widget_Data *wd = elm_widget_data_get(obj);
622 Elm_List_Item *it;
623 Eina_List *n;
624
625 if (!wd) return;
626 _elm_widget_mirrored_reload(obj);
627 _mirrored_set(obj, elm_widget_mirrored_get(obj));
628
629 if (wd->scr)
630 {
631 Evas_Object *edj;
632 const char *str;
633
634 elm_smart_scroller_object_theme_set(obj, wd->scr, "list", "base",
635 elm_widget_style_get(obj));
636 // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
637 edj = elm_smart_scroller_edje_object_get(wd->scr);
638 str = edje_object_data_get(edj, "focus_highlight");
639 if ((str) && (!strcmp(str, "on")))
640 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
641 else
642 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
643 elm_object_style_set(wd->scr, elm_widget_style_get(obj));
644 }
645 EINA_LIST_FOREACH(wd->items, n, it)
646 {
647 edje_object_scale_set(VIEW(it), elm_widget_scale_get(obj) * _elm_config->scale);
648 it->fixed = 0;
649 }
650 _fix_items(obj);
651 _sizing_eval(obj);
652}
653
654static void
655_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
656{
657 Widget_Data *wd = elm_widget_data_get(obj);
658 if (!wd) return;
659 if (elm_widget_focus_get(obj))
660 {
661 edje_object_signal_emit(wd->self, "elm,action,focus", "elm");
662 evas_object_focus_set(wd->self, EINA_TRUE);
663
664 if ((wd->selected) && (!wd->last_selected_item))
665 wd->last_selected_item = eina_list_data_get(wd->selected);
666 }
667 else
668 {
669 edje_object_signal_emit(wd->self, "elm,action,unfocus", "elm");
670 evas_object_focus_set(wd->self, EINA_FALSE);
671 }
672}
673
674static void
675_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
676{
677 Widget_Data *wd = elm_widget_data_get(data);
678 if (!wd) return;
679 _fix_items(data);
680 _sizing_eval(data);
681}
682
683static void
684_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
685{
686 Widget_Data *wd = elm_widget_data_get(obj);
687 Evas_Object *sub = event_info;
688 const Eina_List *l;
689 Elm_List_Item *it;
690
691 if (!wd) return;
692 if (!sub) abort();
693 if ((sub == wd->box) || (sub == wd->scr)) return;
694
695 EINA_LIST_FOREACH(wd->items, l, it)
696 {
697 if ((sub == it->icon) || (sub == it->end))
698 {
699 if (it->icon == sub) it->icon = NULL;
700 if (it->end == sub) it->end = NULL;
701 evas_object_event_callback_del_full
702 (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints,
703 obj);
704 if (!wd->walking)
705 {
706 _fix_items(obj);
707 _sizing_eval(obj);
708 }
709 else
710 wd->fix_pending = EINA_TRUE;
711 break;
712 }
713 }
714}
715
716static void
717_item_highlight(Elm_List_Item *it)
718{
719 Evas_Object *obj = WIDGET(it);
720 Widget_Data *wd = elm_widget_data_get(obj);
721 const char *selectraise;
722
723 if (!wd) return;
724 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
725 if ((it->highlighted) || (it->base.disabled) ||
726 (wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return;
727
728 evas_object_ref(obj);
729 _elm_list_walk(wd);
730
731 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
732 selectraise = edje_object_data_get(VIEW(it), "selectraise");
733 if ((selectraise) && (!strcmp(selectraise, "on")))
734 evas_object_raise(VIEW(it));
735 it->highlighted = EINA_TRUE;
736
737 _elm_list_unwalk(wd);
738 evas_object_unref(obj);
739}
740
741static void
742_item_select(Elm_List_Item *it)
743{
744 Evas_Object *obj = WIDGET(it);
745 Widget_Data *wd = elm_widget_data_get(obj);
746
747 if (!wd) return;
748 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
749 if (it->base.disabled || (wd->select_mode == ELM_OBJECT_SELECT_MODE_NONE)) return;
750 if (it->selected)
751 {
752 if (wd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) goto call;
753 return;
754 }
755 it->selected = EINA_TRUE;
756 wd->selected = eina_list_append(wd->selected, it);
757
758call:
759 evas_object_ref(obj);
760 _elm_list_walk(wd);
761
762 if (it->func) it->func((void *)it->base.data, WIDGET(it), it);
763 evas_object_smart_callback_call(obj, SIG_SELECTED, it);
764 it->wd->last_selected_item = (Elm_Object_Item *)it;
765
766 _elm_list_unwalk(wd);
767 evas_object_unref(obj);
768}
769
770static void
771_item_unselect(Elm_List_Item *it)
772{
773 Evas_Object *obj = WIDGET(it);
774 Widget_Data *wd = elm_widget_data_get(obj);
775 const char *stacking, *selectraise;
776
777 if (!wd) return;
778 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
779 if (!it->highlighted) return;
780
781 evas_object_ref(obj);
782 _elm_list_walk(wd);
783
784 edje_object_signal_emit(VIEW(it), "elm,state,unselected", "elm");
785 stacking = edje_object_data_get(VIEW(it), "stacking");
786 selectraise = edje_object_data_get(VIEW(it), "selectraise");
787 if ((selectraise) && (!strcmp(selectraise, "on")))
788 {
789 if ((stacking) && (!strcmp(stacking, "below")))
790 evas_object_lower(VIEW(it));
791 }
792 it->highlighted = EINA_FALSE;
793 if (it->selected)
794 {
795 it->selected = EINA_FALSE;
796 wd->selected = eina_list_remove(wd->selected, it);
797 evas_object_smart_callback_call(WIDGET(it), SIG_UNSELECTED, it);
798 }
799
800 _elm_list_unwalk(wd);
801 evas_object_unref(obj);
802}
803
804static Eina_Bool
805_swipe_cancel(void *data)
806{
807 Elm_List_Item *it = data;
808 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
809
810 if (!wd) return ECORE_CALLBACK_CANCEL;
811 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
812 wd->swipe = EINA_FALSE;
813 wd->movements = 0;
814 return ECORE_CALLBACK_RENEW;
815}
816
817static void
818_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
819{
820 Elm_List_Item *it = data;
821 Evas_Object *obj2 = WIDGET(it);
822 Widget_Data *wd = elm_widget_data_get(obj2);
823 Evas_Event_Mouse_Move *ev = event_info;
824
825 if (!wd) return;
826 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
827
828 evas_object_ref(obj2);
829 _elm_list_walk(wd);
830
831 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
832 {
833 if (!wd->on_hold)
834 {
835 wd->on_hold = EINA_TRUE;
836 if (it->long_timer)
837 {
838 ecore_timer_del(it->long_timer);
839 it->long_timer = NULL;
840 }
841 if (!wd->wasselected)
842 _item_unselect(it);
843 }
844 if (wd->movements == SWIPE_MOVES) wd->swipe = EINA_TRUE;
845 else
846 {
847 wd->history[wd->movements].x = ev->cur.canvas.x;
848 wd->history[wd->movements].y = ev->cur.canvas.y;
849 if (abs((wd->history[wd->movements].x - wd->history[0].x)) > 40)
850 wd->swipe = EINA_TRUE;
851 else
852 wd->movements++;
853 }
854 }
855
856 _elm_list_unwalk(wd);
857 evas_object_unref(obj2);
858}
859
860static void
861_edge_left(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
862{
863 Evas_Object *obj = data;
864 evas_object_smart_callback_call(obj, SIG_EDGE_LEFT, NULL);
865}
866
867static void
868_edge_right(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
869{
870 Evas_Object *obj = data;
871 evas_object_smart_callback_call(obj, SIG_EDGE_RIGHT, NULL);
872}
873
874static void
875_edge_top(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
876{
877 Evas_Object *obj = data;
878 evas_object_smart_callback_call(obj, SIG_EDGE_TOP, NULL);
879}
880
881static void
882_edge_bottom(void *data, Evas_Object *scr __UNUSED__, void *event_info __UNUSED__)
883{
884 Evas_Object *obj = data;
885 evas_object_smart_callback_call(obj, SIG_EDGE_BOTTOM, NULL);
886}
887
888static Eina_Bool
889_long_press(void *data)
890{
891 Elm_List_Item *it = data;
892 Evas_Object *obj = WIDGET(it);
893 Widget_Data *wd = elm_widget_data_get(obj);
894
895 if (!wd) goto end;
896
897 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, ECORE_CALLBACK_CANCEL);
898 it->long_timer = NULL;
899 if (it->base.disabled) goto end;
900
901 wd->longpressed = EINA_TRUE;
902 evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
903
904end:
905 return ECORE_CALLBACK_CANCEL;
906}
907
908static void
909_swipe(Elm_List_Item *it)
910{
911 int i, sum = 0;
912 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
913
914 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
915 if (!wd) return;
916 wd->swipe = EINA_FALSE;
917 for (i = 0; i < wd->movements; i++)
918 {
919 sum += wd->history[i].x;
920 if (abs(wd->history[0].y - wd->history[i].y) > 10) return;
921 }
922
923 sum /= wd->movements;
924 if (abs(sum - wd->history[0].x) <= 10) return;
925 evas_object_smart_callback_call(WIDGET(it), "swipe", it);
926}
927
928static void
929_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
930{
931 Elm_List_Item *it = data;
932 Evas_Object *obj2 = WIDGET(it);
933 Widget_Data *wd = elm_widget_data_get(obj2);
934 Evas_Event_Mouse_Down *ev = event_info;
935
936 if (!wd) return;
937 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
938 if (ev->button != 1) return;
939 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
940 else wd->on_hold = EINA_FALSE;
941 if (wd->on_hold) return;
942 wd->wasselected = it->selected;
943
944 evas_object_ref(obj2);
945 _elm_list_walk(wd);
946
947 _item_highlight(it);
948 wd->longpressed = EINA_FALSE;
949 if (it->long_timer) ecore_timer_del(it->long_timer);
950 it->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, it);
951 if (it->swipe_timer) ecore_timer_del(it->swipe_timer);
952 it->swipe_timer = ecore_timer_add(0.4, _swipe_cancel, it);
953 /* Always call the callbacks last - the user may delete our context! */
954 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
955 {
956 evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
957 evas_object_smart_callback_call(WIDGET(it), SIG_ACTIVATED, it);
958 }
959 wd->swipe = EINA_FALSE;
960 wd->movements = 0;
961
962 _elm_list_unwalk(wd);
963 evas_object_unref(obj2);
964}
965
966static void
967_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
968{
969 Elm_List_Item *it = data;
970 Evas_Object *obj2 = WIDGET(it);
971 Widget_Data *wd = elm_widget_data_get(obj2);
972 Evas_Event_Mouse_Up *ev = event_info;
973
974 if (!wd) return;
975 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
976 if (ev->button != 1) return;
977 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
978 else wd->on_hold = EINA_FALSE;
979 wd->longpressed = EINA_FALSE;
980 if (it->long_timer)
981 {
982 ecore_timer_del(it->long_timer);
983 it->long_timer = NULL;
984 }
985 if (it->swipe_timer)
986 {
987 ecore_timer_del(it->swipe_timer);
988 it->swipe_timer = NULL;
989 }
990 if (wd->on_hold)
991 {
992 if (wd->swipe) _swipe(data);
993 wd->on_hold = EINA_FALSE;
994 return;
995 }
996 if (wd->longpressed)
997 {
998 if (!wd->wasselected) _item_unselect(it);
999 wd->wasselected = 0;
1000 return;
1001 }
1002
1003 if (it->base.disabled)
1004 return;
1005 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return;
1006
1007 evas_object_ref(obj2);
1008 _elm_list_walk(wd);
1009
1010 if (wd->multi)
1011 {
1012 if (!it->selected)
1013 {
1014 _item_highlight(it);
1015 _item_select(it);
1016 }
1017 else _item_unselect(it);
1018 }
1019 else
1020 {
1021 if (!it->selected)
1022 {
1023 while (wd->selected)
1024 _item_unselect(wd->selected->data);
1025 _item_highlight(it);
1026 _item_select(it);
1027 }
1028 else
1029 {
1030 const Eina_List *l, *l_next;
1031 Elm_List_Item *it2;
1032
1033 EINA_LIST_FOREACH_SAFE(wd->selected, l, l_next, it2)
1034 if (it2 != it) _item_unselect(it2);
1035 _item_highlight(it);
1036 _item_select(it);
1037 }
1038 }
1039
1040 _elm_list_unwalk(wd);
1041 evas_object_unref(obj2);
1042}
1043
1044static void
1045_item_disable(Elm_Object_Item *it)
1046{
1047 Elm_List_Item *item = (Elm_List_Item *)it;
1048 if (item->base.disabled)
1049 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
1050 else
1051 edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm");
1052}
1053
1054static void
1055_item_content_set_hook(Elm_Object_Item *it, const char *part, Evas_Object *content)
1056{
1057 Elm_List_Item *item = (Elm_List_Item *)it;
1058 Evas_Object **icon_p = NULL;
1059 Eina_Bool dummy = EINA_FALSE;
1060
1061 if ((!part) || (!strcmp(part, "start")))
1062 {
1063 icon_p = &(item->icon);
1064 dummy = item->dummy_icon;
1065 if (!content) item->dummy_icon = EINA_TRUE;
1066 else item->dummy_icon = EINA_FALSE;
1067 }
1068 else if (!strcmp(part, "end"))
1069 {
1070 icon_p = &(item->end);
1071 dummy = item->dummy_end;
1072 if (!content) item->dummy_end = EINA_TRUE;
1073 else item->dummy_end = EINA_FALSE;
1074 }
1075 else
1076 return;
1077
1078 if (content == *icon_p) return;
1079 if ((dummy) && (!content)) return;
1080 if (dummy) evas_object_del(*icon_p);
1081 if (!content)
1082 {
1083 content = evas_object_rectangle_add(evas_object_evas_get(WIDGET(item)));
1084 evas_object_color_set(content, 0, 0, 0, 0);
1085 }
1086 if (*icon_p)
1087 {
1088 evas_object_del(*icon_p);
1089 *icon_p = NULL;
1090 }
1091 *icon_p = content;
1092 if (VIEW(item))
1093 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", content);
1094}
1095
1096static Evas_Object *
1097_item_content_get_hook(const Elm_Object_Item *it, const char *part)
1098{
1099 Elm_List_Item *item = (Elm_List_Item *)it;
1100
1101 if ((!part) || (!strcmp(part, "start")))
1102 {
1103 if (item->dummy_icon) return NULL;
1104 return item->icon;
1105 }
1106 else if (!strcmp(part, "end"))
1107 {
1108 if (item->dummy_end) return NULL;
1109 return item->end;
1110 }
1111 return NULL;
1112}
1113
1114static Evas_Object *
1115_item_content_unset_hook(const Elm_Object_Item *it, const char *part)
1116{
1117 Elm_List_Item *item = (Elm_List_Item *)it;
1118
1119 if ((!part) || (!strcmp(part, "start")))
1120 {
1121 Evas_Object *obj = item->icon;
1122 _item_content_set_hook((Elm_Object_Item *)it, part, NULL);
1123 return obj;
1124 }
1125 else if (!strcmp(part, "end"))
1126 {
1127 Evas_Object *obj = item->end;
1128 _item_content_set_hook((Elm_Object_Item *)it, part, NULL);
1129 return obj;
1130 }
1131 return NULL;
1132}
1133
1134static void
1135_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *text)
1136{
1137 Elm_List_Item *list_it = (Elm_List_Item *)it;
1138 if (part && strcmp(part, "default")) return;
1139 if (!eina_stringshare_replace(&list_it->label, text)) return;
1140 if (VIEW(list_it))
1141 edje_object_part_text_escaped_set(VIEW(list_it), "elm.text", text);
1142}
1143
1144static const char *
1145_item_text_get_hook(const Elm_Object_Item *it, const char *part)
1146{
1147 if (part && strcmp(part, "default")) return NULL;
1148 return ((Elm_List_Item *)it)->label;
1149}
1150
1151static Eina_Bool
1152_item_del_pre_hook(Elm_Object_Item *it)
1153{
1154 Evas_Object *obj = WIDGET(it);
1155 Elm_List_Item *item = (Elm_List_Item *)it;
1156 Widget_Data *wd = elm_widget_data_get(obj);
1157 if (!wd) return EINA_FALSE;
1158
1159 if (item->selected) _item_unselect(item);
1160
1161 if (wd->walking > 0)
1162 {
1163 if (item->deleted) return EINA_FALSE;
1164 item->deleted = EINA_TRUE;
1165 wd->to_delete = eina_list_append(wd->to_delete, item);
1166 return EINA_FALSE;
1167 }
1168
1169 wd->items = eina_list_remove_list(wd->items, item->node);
1170
1171 evas_object_ref(obj);
1172 _elm_list_walk(wd);
1173
1174 _elm_list_item_free(item);
1175
1176 _elm_list_unwalk(wd);
1177 evas_object_unref(obj);
1178
1179 return EINA_TRUE;
1180}
1181
1182static Elm_List_Item *
1183_item_new(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1184{
1185 Widget_Data *wd = elm_widget_data_get(obj);
1186 Elm_List_Item *it;
1187
1188 if (!wd) return NULL;
1189 it = elm_widget_item_new(obj, Elm_List_Item);
1190 it->wd = wd;
1191 it->label = eina_stringshare_add(label);
1192 it->icon = icon;
1193 it->end = end;
1194 it->func = func;
1195 it->base.data = data;
1196 VIEW(it) = edje_object_add(evas_object_evas_get(obj));
1197 edje_object_mirrored_set(VIEW(it), elm_widget_mirrored_get(obj));
1198 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
1199 _mouse_down, it);
1200 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
1201 _mouse_up, it);
1202 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_MOVE,
1203 _mouse_move, it);
1204 evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1205 evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
1206 if (it->icon)
1207 {
1208 elm_widget_sub_object_add(obj, it->icon);
1209 evas_object_event_callback_add(it->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1210 _changed_size_hints, obj);
1211 }
1212 if (it->end)
1213 {
1214 elm_widget_sub_object_add(obj, it->end);
1215 evas_object_event_callback_add(it->end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1216 _changed_size_hints, obj);
1217 }
1218 elm_widget_item_disable_hook_set(it, _item_disable);
1219 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
1220 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
1221 elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
1222 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
1223 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
1224 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
1225 return it;
1226}
1227
1228static void
1229_elm_list_mode_set_internal(Widget_Data *wd)
1230{
1231 if (!wd->scr)
1232 return;
1233
1234 if (wd->mode == ELM_LIST_LIMIT)
1235 {
1236 if (!wd->h_mode)
1237 {
1238 wd->scr_minw = EINA_TRUE;
1239 wd->scr_minh = EINA_FALSE;
1240 }
1241 else
1242 {
1243 wd->scr_minw = EINA_FALSE;
1244 wd->scr_minh = EINA_TRUE;
1245 }
1246 }
1247 else if (wd->mode == ELM_LIST_EXPAND)
1248 {
1249 wd->scr_minw = EINA_TRUE;
1250 wd->scr_minh = EINA_TRUE;
1251 }
1252 else
1253 {
1254 wd->scr_minw = EINA_FALSE;
1255 wd->scr_minh = EINA_FALSE;
1256 }
1257
1258 _sizing_eval(wd->self);
1259}
1260
1261static void
1262_fix_items(Evas_Object *obj)
1263{
1264 Widget_Data *wd = elm_widget_data_get(obj);
1265 if (!wd) return;
1266 const Eina_List *l;
1267 Elm_List_Item *it;
1268 Evas_Coord minw[2] = { 0, 0 }, minh[2] = { 0, 0 };
1269 Evas_Coord mw, mh;
1270 int i, redo = 0;
1271 const char *style = elm_widget_style_get(obj);
1272 const char *it_plain = wd->h_mode ? "h_item" : "item";
1273 const char *it_odd = wd->h_mode ? "h_item_odd" : "item_odd";
1274 const char *it_compress = wd->h_mode ? "h_item_compress" : "item_compress";
1275 const char *it_compress_odd = wd->h_mode ? "h_item_compress_odd" : "item_compress_odd";
1276
1277 if (wd->walking)
1278 {
1279 wd->fix_pending = EINA_TRUE;
1280 return;
1281 }
1282
1283 evas_object_ref(obj);
1284 _elm_list_walk(wd); // watch out "return" before unwalk!
1285
1286 EINA_LIST_FOREACH(wd->items, l, it)
1287 {
1288 if (it->deleted) continue;
1289 if (it->icon)
1290 {
1291 evas_object_size_hint_min_get(it->icon, &mw, &mh);
1292 if (mw > minw[0]) minw[0] = mw;
1293 if (mh > minh[0]) minh[0] = mh;
1294 }
1295 if (it->end)
1296 {
1297 evas_object_size_hint_min_get(it->end, &mw, &mh);
1298 if (mw > minw[1]) minw[1] = mw;
1299 if (mh > minh[1]) minh[1] = mh;
1300 }
1301 }
1302
1303 if ((minw[0] != wd->minw[0]) || (minw[1] != wd->minw[1]) ||
1304 (minw[0] != wd->minh[0]) || (minh[1] != wd->minh[1]))
1305 {
1306 wd->minw[0] = minw[0];
1307 wd->minw[1] = minw[1];
1308 wd->minh[0] = minh[0];
1309 wd->minh[1] = minh[1];
1310 redo = 1;
1311 }
1312 i = 0;
1313 EINA_LIST_FOREACH(wd->items, l, it)
1314 {
1315 if (it->deleted)
1316 continue;
1317
1318 it->even = i & 0x1;
1319 if ((it->even != it->is_even) || (!it->fixed) || (redo))
1320 {
1321 const char *stacking;
1322
1323 /* FIXME: separators' themes seem to be b0rked */
1324 if (it->is_separator)
1325 _elm_theme_object_set(obj, VIEW(it), "separator",
1326 wd->h_mode ? "horizontal" : "vertical",
1327 style);
1328 else if (wd->mode == ELM_LIST_COMPRESS)
1329 {
1330 if (it->even)
1331 _elm_theme_object_set(obj, VIEW(it), "list",
1332 it_compress, style);
1333 else
1334 _elm_theme_object_set(obj, VIEW(it), "list",
1335 it_compress_odd, style);
1336 }
1337 else
1338 {
1339 if (it->even)
1340 _elm_theme_object_set(obj, VIEW(it), "list", it_plain,
1341 style);
1342 else
1343 _elm_theme_object_set(obj, VIEW(it), "list", it_odd,
1344 style);
1345 }
1346 stacking = edje_object_data_get(VIEW(it), "stacking");
1347 if (stacking)
1348 {
1349 if (!strcmp(stacking, "below"))
1350 evas_object_lower(VIEW(it));
1351 else if (!strcmp(stacking, "above"))
1352 evas_object_raise(VIEW(it));
1353 }
1354 edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
1355
1356 if ((!it->icon) && (minh[0] > 0))
1357 {
1358 it->icon = evas_object_rectangle_add(evas_object_evas_get(VIEW(it)));
1359 evas_object_color_set(it->icon, 0, 0, 0, 0);
1360 it->dummy_icon = EINA_TRUE;
1361 }
1362 if ((!it->end) && (minh[1] > 0))
1363 {
1364 it->end = evas_object_rectangle_add(evas_object_evas_get(VIEW(it)));
1365 evas_object_color_set(it->end, 0, 0, 0, 0);
1366 it->dummy_end = EINA_TRUE;
1367 }
1368 if (it->icon)
1369 {
1370 evas_object_size_hint_min_set(it->icon, minw[0], minh[0]);
1371 evas_object_size_hint_max_set(it->icon, 99999, 99999);
1372 edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
1373 }
1374 if (it->end)
1375 {
1376 evas_object_size_hint_min_set(it->end, minw[1], minh[1]);
1377 evas_object_size_hint_max_set(it->end, 99999, 99999);
1378 edje_object_part_swallow(VIEW(it), "elm.swallow.end", it->end);
1379 }
1380 if (!it->fixed)
1381 {
1382 // this may call up user and it may modify the list item
1383 // but we're safe as we're flagged as walking.
1384 // just don't process further
1385 edje_object_message_signal_process(VIEW(it));
1386 if (it->deleted)
1387 continue;
1388 mw = mh = -1;
1389 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1390 edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
1391 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1392 evas_object_size_hint_min_set(VIEW(it), mw, mh);
1393 evas_object_show(VIEW(it));
1394 }
1395 if ((it->selected) || (it->highlighted))
1396 {
1397 const char *selectraise;
1398
1399 // this may call up user and it may modify the list item
1400 // but we're safe as we're flagged as walking.
1401 // just don't process further
1402 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
1403 if (it->deleted)
1404 continue;
1405
1406 selectraise = edje_object_data_get(VIEW(it), "selectraise");
1407 if ((selectraise) && (!strcmp(selectraise, "on")))
1408 evas_object_raise(VIEW(it));
1409 }
1410 if (it->base.disabled)
1411 edje_object_signal_emit(VIEW(it), "elm,state,disabled",
1412 "elm");
1413
1414 it->fixed = EINA_TRUE;
1415 it->is_even = it->even;
1416 }
1417 i++;
1418 }
1419
1420 mw = 0; mh = 0;
1421 evas_object_size_hint_min_get(wd->box, &mw, &mh);
1422
1423 _elm_list_mode_set_internal(wd);
1424
1425 _elm_list_unwalk(wd);
1426 evas_object_unref(obj);
1427}
1428
1429static void
1430_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1431{
1432 Widget_Data *wd = elm_widget_data_get(obj);
1433 if (!wd) return;
1434 if (wd->scr)
1435 elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
1436}
1437
1438static void
1439_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1440{
1441 Widget_Data *wd = elm_widget_data_get(obj);
1442 if (!wd) return;
1443 if (wd->scr)
1444 elm_smart_scroller_hold_set(wd->scr, EINA_FALSE);
1445}
1446
1447static void
1448_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1449{
1450 Widget_Data *wd = elm_widget_data_get(obj);
1451 if (!wd) return;
1452 if (wd->scr)
1453 elm_smart_scroller_freeze_set(wd->scr, EINA_TRUE);
1454}
1455
1456static void
1457_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1458{
1459 Widget_Data *wd = elm_widget_data_get(obj);
1460 if (!wd) return;
1461 if (wd->scr)
1462 elm_smart_scroller_freeze_set(wd->scr, EINA_FALSE);
1463}
1464
1465static void
1466_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1467{
1468 _sizing_eval(data);
1469}
1470
1471EAPI Evas_Object *
1472elm_list_add(Evas_Object *parent)
1473{
1474 Evas_Object *obj;
1475 Evas *e;
1476 Widget_Data *wd;
1477 Evas_Coord minw, minh;
1478
1479 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1480
1481 ELM_SET_WIDTYPE(widtype, "list");
1482 elm_widget_type_set(obj, "list");
1483 elm_widget_sub_object_add(parent, obj);
1484 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1485 elm_widget_data_set(obj, wd);
1486 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1487 elm_widget_del_hook_set(obj, _del_hook);
1488 elm_widget_theme_hook_set(obj, _theme_hook);
1489 elm_widget_disable_hook_set(obj, _disable_hook);
1490 elm_widget_can_focus_set(obj, EINA_TRUE);
1491 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
1492 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
1493 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
1494 elm_widget_event_hook_set(obj, _event_hook);
1495 elm_widget_translate_hook_set(obj, _translate_hook);
1496
1497 wd->self = obj;
1498 wd->scr = elm_smart_scroller_add(e);
1499 elm_smart_scroller_widget_set(wd->scr, obj);
1500 elm_widget_resize_object_set(obj, wd->scr);
1501 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1502 _changed_size_hints, obj);
1503 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
1504 evas_object_size_hint_min_set(obj, minw, minh);
1505 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
1506
1507 elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE,
1508 _elm_config->thumbscroll_bounce_enable);
1509
1510 wd->box = elm_box_add(parent);
1511 elm_box_homogeneous_set(wd->box, 1);
1512 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
1513 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
1514 elm_widget_on_show_region_hook_set(wd->box, _show_region_hook, obj);
1515 elm_widget_sub_object_add(obj, wd->box);
1516 elm_smart_scroller_child_set(wd->scr, wd->box);
1517 evas_object_event_callback_add(wd->box, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1518 _changed_size_hints, obj);
1519
1520 evas_object_show(wd->box);
1521
1522 _theme_hook(obj);
1523
1524 wd->mode = ELM_LIST_SCROLL;
1525
1526 evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
1527 evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
1528 evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
1529 evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
1530
1531 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
1532 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1533 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1534 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1535 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1536
1537 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1538
1539 _mirrored_set(obj, elm_widget_mirrored_get(obj));
1540 _sizing_eval(obj);
1541 return obj;
1542}
1543
1544EAPI void
1545elm_list_go(Evas_Object *obj)
1546{
1547 ELM_CHECK_WIDTYPE(obj, widtype);
1548 Widget_Data *wd = elm_widget_data_get(obj);
1549 if (!wd) return;
1550 _fix_items(obj);
1551}
1552
1553EAPI void
1554elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi)
1555{
1556 ELM_CHECK_WIDTYPE(obj, widtype);
1557 Widget_Data *wd = elm_widget_data_get(obj);
1558 if (!wd) return;
1559 wd->multi = multi;
1560}
1561
1562EAPI Eina_Bool
1563elm_list_multi_select_get(const Evas_Object *obj)
1564{
1565 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1566 Widget_Data *wd = elm_widget_data_get(obj);
1567 if (!wd) return EINA_FALSE;
1568 return wd->multi;
1569}
1570
1571EAPI void
1572elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode)
1573{
1574 ELM_CHECK_WIDTYPE(obj, widtype);
1575
1576 Widget_Data *wd;
1577
1578 wd = elm_widget_data_get(obj);
1579 if (!wd)
1580 return;
1581 if (wd->mode == mode)
1582 return;
1583 wd->mode = mode;
1584
1585 _elm_list_mode_set_internal(wd);
1586}
1587
1588EAPI Elm_List_Mode
1589elm_list_mode_get(const Evas_Object *obj)
1590{
1591 ELM_CHECK_WIDTYPE(obj, widtype) ELM_LIST_LAST;
1592 Widget_Data *wd = elm_widget_data_get(obj);
1593 if (!wd) return ELM_LIST_LAST;
1594 return wd->mode;
1595}
1596
1597EAPI void
1598elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
1599{
1600 ELM_CHECK_WIDTYPE(obj, widtype);
1601
1602 Widget_Data *wd;
1603 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1604
1605 wd = elm_widget_data_get(obj);
1606 if (!wd)
1607 return;
1608
1609 if (wd->h_mode == horizontal)
1610 return;
1611
1612 wd->h_mode = horizontal;
1613 elm_box_horizontal_set(wd->box, horizontal);
1614
1615 if (horizontal)
1616 {
1617 evas_object_size_hint_weight_set(wd->box, 0.0, EVAS_HINT_EXPAND);
1618 evas_object_size_hint_align_set(wd->box, 0.0, EVAS_HINT_FILL);
1619 elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1620 }
1621 else
1622 {
1623 evas_object_size_hint_weight_set(wd->box, EVAS_HINT_EXPAND, 0.0);
1624 evas_object_size_hint_align_set(wd->box, EVAS_HINT_FILL, 0.0);
1625 elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, bounce);
1626 }
1627
1628 _elm_list_mode_set_internal(wd);
1629}
1630
1631EAPI Eina_Bool
1632elm_list_horizontal_get(const Evas_Object *obj)
1633{
1634 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1635
1636 Widget_Data *wd;
1637
1638 wd = elm_widget_data_get(obj);
1639 if (!wd)
1640 return EINA_FALSE;
1641
1642 return wd->h_mode;
1643}
1644
1645EAPI void
1646elm_list_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
1647{
1648 ELM_CHECK_WIDTYPE(obj, widtype);
1649 Widget_Data *wd = elm_widget_data_get(obj);
1650 if (!wd) return;
1651 if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
1652 return;
1653 if (wd->select_mode != mode)
1654 wd->select_mode = mode;
1655}
1656
1657EAPI Elm_Object_Select_Mode
1658elm_list_select_mode_get(const Evas_Object *obj)
1659{
1660 ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
1661 Widget_Data *wd = elm_widget_data_get(obj);
1662 if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
1663 return wd->select_mode;
1664}
1665
1666EAPI void
1667elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1668{
1669 ELM_CHECK_WIDTYPE(obj, widtype);
1670 Widget_Data *wd = elm_widget_data_get(obj);
1671 if (!wd) return;
1672 if (wd->scr)
1673 elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
1674}
1675
1676EAPI void
1677elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
1678{
1679 ELM_CHECK_WIDTYPE(obj, widtype);
1680 Widget_Data *wd = elm_widget_data_get(obj);
1681 if (!wd) return;
1682 elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
1683}
1684
1685EAPI void
1686elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
1687{
1688 ELM_CHECK_WIDTYPE(obj, widtype);
1689 Widget_Data *wd = elm_widget_data_get(obj);
1690 if ((!wd) || (!wd->scr)) return;
1691 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
1692 (policy_v >= ELM_SCROLLER_POLICY_LAST))
1693 return;
1694 elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
1695}
1696
1697EAPI void
1698elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
1699{
1700 ELM_CHECK_WIDTYPE(obj, widtype);
1701 Widget_Data *wd = elm_widget_data_get(obj);
1702 Elm_Smart_Scroller_Policy s_policy_h, s_policy_v;
1703 if ((!wd) || (!wd->scr)) return;
1704 elm_smart_scroller_policy_get(wd->scr, &s_policy_h, &s_policy_v);
1705 if (policy_h) *policy_h = (Elm_Scroller_Policy) s_policy_h;
1706 if (policy_v) *policy_v = (Elm_Scroller_Policy) s_policy_v;
1707}
1708
1709EAPI void
1710elm_list_clear(Evas_Object *obj)
1711{
1712 ELM_CHECK_WIDTYPE(obj, widtype);
1713 Widget_Data *wd = elm_widget_data_get(obj);
1714 Elm_List_Item *it;
1715
1716 if (!wd) return;
1717 if (!wd->items) return;
1718
1719 eina_list_free(wd->selected);
1720 wd->selected = NULL;
1721
1722 if (wd->walking > 0)
1723 {
1724 Eina_List *n;
1725
1726 EINA_LIST_FOREACH(wd->items, n, it)
1727 {
1728 if (it->deleted) continue;
1729 it->deleted = EINA_TRUE;
1730 wd->to_delete = eina_list_append(wd->to_delete, it);
1731 }
1732 return;
1733 }
1734
1735 evas_object_ref(obj);
1736 _elm_list_walk(wd);
1737
1738 EINA_LIST_FREE(wd->items, it)
1739 {
1740 _elm_list_item_free(it);
1741 elm_widget_item_free(it);
1742 }
1743
1744 _elm_list_unwalk(wd);
1745
1746 _fix_items(obj);
1747 _sizing_eval(obj);
1748 evas_object_unref(obj);
1749}
1750
1751EAPI const Eina_List *
1752elm_list_items_get(const Evas_Object *obj)
1753{
1754 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1755 Widget_Data *wd = elm_widget_data_get(obj);
1756 if (!wd) return NULL;
1757 return wd->items;
1758}
1759
1760EAPI Elm_Object_Item *
1761elm_list_selected_item_get(const Evas_Object *obj)
1762{
1763 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1764 Widget_Data *wd = elm_widget_data_get(obj);
1765 if (!wd) return NULL;
1766 if (wd->selected) return (Elm_Object_Item *) wd->selected->data;
1767 return NULL;
1768}
1769
1770EAPI const Eina_List *
1771elm_list_selected_items_get(const Evas_Object *obj)
1772{
1773 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1774 Widget_Data *wd = elm_widget_data_get(obj);
1775 if (!wd) return NULL;
1776 return wd->selected;
1777}
1778
1779EAPI Elm_Object_Item *
1780elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1781{
1782 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1783 Widget_Data *wd = elm_widget_data_get(obj);
1784 Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1785
1786 wd->items = eina_list_append(wd->items, it);
1787 it->node = eina_list_last(wd->items);
1788 elm_box_pack_end(wd->box, VIEW(it));
1789 return (Elm_Object_Item *)it;
1790}
1791
1792EAPI Elm_Object_Item *
1793elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1794{
1795 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1796 Widget_Data *wd = elm_widget_data_get(obj);
1797 Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1798
1799 wd->items = eina_list_prepend(wd->items, it);
1800 it->node = wd->items;
1801 elm_box_pack_start(wd->box, VIEW(it));
1802 return (Elm_Object_Item *)it;
1803}
1804
1805EAPI Elm_Object_Item *
1806elm_list_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1807{
1808 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1809 ELM_LIST_ITEM_CHECK_DELETED_RETURN(before, NULL);
1810
1811 Widget_Data *wd;
1812 Elm_List_Item *it, *before_it;
1813
1814 wd = elm_widget_data_get(obj);
1815 if (!wd) return NULL;
1816
1817 before_it = (Elm_List_Item *) before;
1818 if (!before_it->node) return NULL;
1819
1820 it = _item_new(obj, label, icon, end, func, data);
1821 wd->items = eina_list_prepend_relative_list(wd->items, it, before_it->node);
1822 it->node = before_it->node->prev;
1823 elm_box_pack_before(wd->box, VIEW(it), VIEW(before_it));
1824 return (Elm_Object_Item *)it;
1825}
1826
1827EAPI Elm_Object_Item *
1828elm_list_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data)
1829{
1830 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1831 ELM_LIST_ITEM_CHECK_DELETED_RETURN(after, NULL);
1832
1833 Widget_Data *wd;
1834 Elm_List_Item *it, *after_it;
1835
1836 wd = elm_widget_data_get(obj);
1837 if (!wd) return NULL;
1838
1839 after_it = (Elm_List_Item *) after;
1840 if (!after_it->node) return NULL;
1841
1842 it = _item_new(obj, label, icon, end, func, data);
1843 wd->items = eina_list_append_relative_list(wd->items, it, after_it->node);
1844 it->node = after_it->node->next;
1845 elm_box_pack_after(wd->box, VIEW(it), VIEW(after_it));
1846 return (Elm_Object_Item *)it;
1847}
1848
1849EAPI Elm_Object_Item *
1850elm_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)
1851{
1852 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1853 Widget_Data *wd = elm_widget_data_get(obj);
1854 Elm_List_Item *it = _item_new(obj, label, icon, end, func, data);
1855 Eina_List *l;
1856
1857 wd->items = eina_list_sorted_insert(wd->items, cmp_func, it);
1858 l = eina_list_data_find_list(wd->items, it);
1859 l = eina_list_next(l);
1860 if (!l)
1861 {
1862 it->node = eina_list_last(wd->items);
1863 elm_box_pack_end(wd->box, VIEW(it));
1864 }
1865 else
1866 {
1867 Elm_List_Item *before = eina_list_data_get(l);
1868 it->node = before->node->prev;
1869 elm_box_pack_before(wd->box, VIEW(it), VIEW(before));
1870 }
1871 return (Elm_Object_Item *)it;
1872}
1873
1874EAPI void
1875elm_list_item_separator_set(Elm_Object_Item *it, Eina_Bool setting)
1876{
1877 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1878 ((Elm_List_Item *)it)->is_separator = !!setting;
1879}
1880
1881EAPI Eina_Bool
1882elm_list_item_separator_get(const Elm_Object_Item *it)
1883{
1884 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
1885 return ((Elm_List_Item *)it)->is_separator;
1886}
1887
1888EAPI void
1889elm_list_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
1890{
1891 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1892 Evas_Object *obj = WIDGET(it);
1893 Widget_Data *wd = elm_widget_data_get(obj);
1894 Elm_List_Item *item = (Elm_List_Item *)it;
1895 if (!wd) return;
1896
1897 selected = !!selected;
1898 if (item->selected == selected) return;
1899
1900 evas_object_ref(obj);
1901 _elm_list_walk(wd);
1902
1903 if (selected)
1904 {
1905 if (!wd->multi)
1906 {
1907 while (wd->selected)
1908 _item_unselect(wd->selected->data);
1909 }
1910 _item_highlight(item);
1911 _item_select(item);
1912 }
1913 else
1914 _item_unselect(item);
1915
1916 _elm_list_unwalk(wd);
1917 evas_object_unref(obj);
1918}
1919
1920EAPI Eina_Bool
1921elm_list_item_selected_get(const Elm_Object_Item *it)
1922{
1923 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, EINA_FALSE);
1924 return ((Elm_List_Item *)it)->selected;
1925}
1926
1927EAPI void
1928elm_list_item_show(Elm_Object_Item *it)
1929{
1930 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1931 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
1932 if (!wd) return;
1933 Evas_Coord bx, by, bw, bh;
1934 Evas_Coord x, y, w, h;
1935
1936 evas_smart_objects_calculate(evas_object_evas_get(wd->box));
1937 evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
1938 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
1939 x -= bx;
1940 y -= by;
1941 if (wd->scr) elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
1942}
1943
1944EAPI void
1945elm_list_item_bring_in(Elm_Object_Item *it)
1946{
1947 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it);
1948 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
1949 if (!wd) return;
1950 Evas_Coord bx, by, bw, bh;
1951 Evas_Coord x, y, w, h;
1952
1953 evas_smart_objects_calculate(evas_object_evas_get(wd->box));
1954 evas_object_geometry_get(wd->box, &bx, &by, &bw, &bh);
1955 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
1956 x -= bx;
1957 y -= by;
1958 if (wd->scr) elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
1959}
1960
1961EAPI Evas_Object *
1962elm_list_item_object_get(const Elm_Object_Item *it)
1963{
1964 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1965 return VIEW(it);
1966}
1967
1968EAPI Elm_Object_Item *
1969elm_list_item_prev(const Elm_Object_Item *it)
1970{
1971 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1972 Elm_List_Item *item = (Elm_List_Item *)it;
1973 if (item->node->prev) return item->node->prev->data;
1974 else return NULL;
1975}
1976
1977EAPI Elm_Object_Item *
1978elm_list_item_next(const Elm_Object_Item *it)
1979{
1980 ELM_LIST_ITEM_CHECK_DELETED_RETURN(it, NULL);
1981 Elm_List_Item *item = (Elm_List_Item *)it;
1982 if (item->node->next) return item->node->next->data;
1983 else return NULL;
1984}
1985
1986EAPI Elm_Object_Item *
1987elm_list_first_item_get(const Evas_Object *obj)
1988{
1989 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1990 Widget_Data *wd = elm_widget_data_get(obj);
1991 if (!wd) return NULL;
1992 if (!wd->items) return NULL;
1993 return eina_list_data_get(wd->items);
1994}
1995
1996EAPI Elm_Object_Item *
1997elm_list_last_item_get(const Evas_Object *obj)
1998{
1999 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2000 Widget_Data *wd = elm_widget_data_get(obj);
2001 if (!wd) return NULL;
2002 if (!wd->items) return NULL;
2003 return eina_list_data_get(eina_list_last(wd->items));
2004}
diff --git a/libraries/elementary/src/lib/elm_list.h b/libraries/elementary/src/lib/elm_list.h
new file mode 100644
index 0000000..933a28e
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_list.h
@@ -0,0 +1,779 @@
1/**
2 * @defgroup List List
3 * @ingroup Elementary
4 *
5 * @image html img/widget/list/preview-00.png
6 * @image latex img/widget/list/preview-00.eps width=\textwidth
7 *
8 * @image html img/list.png
9 * @image latex img/list.eps width=\textwidth
10 *
11 * A list widget is a container whose children are displayed vertically or
12 * horizontally, in order, and can be selected.
13 * The list can accept only one or multiple items selection. Also has many
14 * modes of items displaying.
15 *
16 * A list is a very simple type of list widget. For more robust
17 * lists, @ref Genlist should probably be used.
18 *
19 * Smart callbacks one can listen to:
20 * - @c "activated" - The user has double-clicked or pressed
21 * (enter|return|spacebar) on an item. The @c event_info parameter
22 * is the item that was activated.
23 * - @c "clicked,double" - The user has double-clicked an item.
24 * The @c event_info parameter is the item that was double-clicked.
25 * - "selected" - when the user selected an item
26 * - "unselected" - when the user unselected an item
27 * - "longpressed" - an item in the list is long-pressed
28 * - "edge,top" - the list is scrolled until the top edge
29 * - "edge,bottom" - the list is scrolled until the bottom edge
30 * - "edge,left" - the list is scrolled until the left edge
31 * - "edge,right" - the list is scrolled until the right edge
32 * - "language,changed" - the program's language changed
33 *
34 * Available styles for it:
35 * - @c "default"
36 *
37 * Default content parts of the list items that you can use for are:
38 * @li "start" - A start position object in the list item
39 * @li "end" - A end position object in the list item
40 *
41 * Default text parts of the list items that you can use for are:
42 * @li "default" - label in the list item
43 *
44 * Supported elm_object_item common APIs.
45 * @li @ref elm_object_item_disabled_set
46 * @li @ref elm_object_item_disabled_get
47 * @li @ref elm_object_item_part_text_set
48 * @li @ref elm_object_item_part_text_get
49 * @li @ref elm_object_item_part_content_set
50 * @li @ref elm_object_item_part_content_get
51 * @li @ref elm_object_item_part_content_unset
52 *
53 * List of examples:
54 * @li @ref list_example_01
55 * @li @ref list_example_02
56 * @li @ref list_example_03
57 */
58
59/**
60 * @addtogroup List
61 * @{
62 */
63
64/**
65 * @enum _Elm_List_Mode
66 * @typedef Elm_List_Mode
67 *
68 * Set list's resize behavior, transverse axis scroll and
69 * items cropping. See each mode's description for more details.
70 *
71 * @note Default value is #ELM_LIST_SCROLL.
72 *
73 * Values <b> don't </b> work as bitmask, only one can be chosen.
74 *
75 * @see elm_list_mode_set()
76 * @see elm_list_mode_get()
77 *
78 * @ingroup List
79 */
80typedef enum
81{
82 ELM_LIST_COMPRESS = 0, /**< 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 won't be able to scroll it in that direction. */
83 ELM_LIST_SCROLL, /**< Default value. 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 (large items will get cropped). */
84 ELM_LIST_LIMIT, /**< Set a minimum 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 item in that direction fits well. Can have effects bounded by setting the list object's maximum size hints. */
85 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. Can have effects bounded by setting the list object's maximum size hints. */
86 ELM_LIST_LAST /**< Indicates error if returned by elm_list_mode_get() */
87} Elm_List_Mode;
88
89/**
90 * Add a new list widget to the given parent Elementary
91 * (container) object.
92 *
93 * @param parent The parent object.
94 * @return a new list widget handle or @c NULL, on errors.
95 *
96 * This function inserts a new list widget on the canvas.
97 *
98 * @ingroup List
99 */
100EAPI Evas_Object *elm_list_add(Evas_Object *parent);
101
102/**
103 * Starts the list.
104 *
105 * @param obj The list object
106 *
107 * @note Call before running show() on the list object.
108 * @warning If not called, it won't display the list properly.
109 *
110 * @code
111 * li = elm_list_add(win);
112 * elm_list_item_append(li, "First", NULL, NULL, NULL, NULL);
113 * elm_list_item_append(li, "Second", NULL, NULL, NULL, NULL);
114 * elm_list_go(li);
115 * evas_object_show(li);
116 * @endcode
117 *
118 * @ingroup List
119 */
120EAPI void elm_list_go(Evas_Object *obj);
121
122/**
123 * Enable or disable multiple items selection on the list object.
124 *
125 * @param obj The list object
126 * @param multi @c EINA_TRUE to enable multi selection or @c EINA_FALSE to
127 * disable it.
128 *
129 * Disabled by default. If disabled, the user can select a single item of
130 * the list each time. Selected items are highlighted on list.
131 * If enabled, many items can be selected.
132 *
133 * If a selected item is selected again, it will be unselected.
134 *
135 * @see elm_list_multi_select_get()
136 *
137 * @ingroup List
138 */
139EAPI void elm_list_multi_select_set(Evas_Object *obj, Eina_Bool multi);
140
141/**
142 * Get a value whether multiple items selection is enabled or not.
143 *
144 * @see elm_list_multi_select_set() for details.
145 *
146 * @param obj The list object.
147 * @return @c EINA_TRUE means multiple items selection is enabled.
148 * @c EINA_FALSE indicates it's disabled. If @p obj is @c NULL,
149 * @c EINA_FALSE is returned.
150 *
151 * @ingroup List
152 */
153EAPI Eina_Bool elm_list_multi_select_get(const Evas_Object *obj);
154
155/**
156 * Set which mode to use for the list object.
157 *
158 * @param obj The list object
159 * @param mode One of #Elm_List_Mode: #ELM_LIST_COMPRESS, #ELM_LIST_SCROLL,
160 * #ELM_LIST_LIMIT or #ELM_LIST_EXPAND.
161 *
162 * Set list's resize behavior, transverse axis scroll and
163 * items cropping. See each mode's description for more details.
164 *
165 * @note Default value is #ELM_LIST_SCROLL.
166 *
167 * Only one can be set, if a previous one was set, it will be changed
168 * by the new mode set. Bitmask won't work as well.
169 *
170 * @see elm_list_mode_get()
171 *
172 * @ingroup List
173 */
174EAPI void elm_list_mode_set(Evas_Object *obj, Elm_List_Mode mode);
175
176/**
177 * Get the mode the list is at.
178 *
179 * @param obj The list object
180 * @return One of #Elm_List_Mode: #ELM_LIST_COMPRESS, #ELM_LIST_SCROLL,
181 * #ELM_LIST_LIMIT, #ELM_LIST_EXPAND or #ELM_LIST_LAST on errors.
182 *
183 * @note see elm_list_mode_set() for more information.
184 *
185 * @ingroup List
186 */
187EAPI Elm_List_Mode elm_list_mode_get(const Evas_Object *obj);
188
189/**
190 * Enable or disable horizontal mode on the list object.
191 *
192 * @param obj The list object.
193 * @param horizontal @c EINA_TRUE to enable horizontal or @c EINA_FALSE to
194 * disable it, i.e., to enable vertical mode.
195 *
196 * @note Vertical mode is set by default.
197 *
198 * On horizontal mode items are displayed on list from left to right,
199 * instead of from top to bottom. Also, the list will scroll horizontally.
200 * Each item will presents left icon on top and right icon, or end, at
201 * the bottom.
202 *
203 * @see elm_list_horizontal_get()
204 *
205 * @ingroup List
206 */
207EAPI void elm_list_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
208
209/**
210 * Get a value whether horizontal mode is enabled or not.
211 *
212 * @param obj The list object.
213 * @return @c EINA_TRUE means horizontal mode selection is enabled.
214 * @c EINA_FALSE indicates it's disabled. If @p obj is @c NULL,
215 * @c EINA_FALSE is returned.
216 *
217 * @see elm_list_horizontal_set() for details.
218 *
219 * @ingroup List
220 */
221EAPI Eina_Bool elm_list_horizontal_get(const Evas_Object *obj);
222
223/**
224 * Set the list select mode.
225 *
226 * @param obj The list object
227 * @param mode The select mode
228 *
229 * elm_list_select_mode_set() changes item select mode in the list widget.
230 * - ELM_OBJECT_SELECT_MODE_DEFAULT : Items will only call their selection func and
231 * callback when first becoming selected. Any further clicks will
232 * do nothing, unless you set always select mode.
233 * - ELM_OBJECT_SELECT_MODE_ALWAYS : This means that, even if selected,
234 * every click will make the selected callbacks be called.
235 * - ELM_OBJECT_SELECT_MODE_NONE : This will turn off the ability to select items
236 * entirely and they will neither appear selected nor call selected
237 * callback functions.
238 *
239 * @see elm_list_select_mode_get()
240 *
241 * @ingroup List
242 */
243EAPI void
244elm_list_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode);
245
246/**
247 * Get the list select mode.
248 *
249 * @param obj The list object
250 * @return The select mode
251 * (If getting mode is failed, it returns ELM_OBJECT_SELECT_MODE_MAX)
252 *
253 * @see elm_list_select_mode_set()
254 *
255 * @ingroup List
256 */
257EAPI Elm_Object_Select_Mode
258elm_list_select_mode_get(const Evas_Object *obj);
259
260/**
261 * Set bouncing behaviour when the scrolled content reaches an edge.
262 *
263 * Tell the internal scroller object whether it should bounce or not
264 * when it reaches the respective edges for each axis.
265 *
266 * @param obj The list object
267 * @param h_bounce Whether to bounce or not in the horizontal axis.
268 * @param v_bounce Whether to bounce or not in the vertical axis.
269 *
270 * @see elm_scroller_bounce_set()
271 *
272 * @ingroup List
273 */
274EAPI void elm_list_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
275
276/**
277 * Get the bouncing behaviour of the internal scroller.
278 *
279 * Get whether the internal scroller should bounce when the edge of each
280 * axis is reached scrolling.
281 *
282 * @param obj The list object.
283 * @param h_bounce Pointer to store the bounce state of the horizontal
284 * axis.
285 * @param v_bounce Pointer to store the bounce state of the vertical
286 * axis.
287 *
288 * @see elm_scroller_bounce_get()
289 * @see elm_list_bounce_set()
290 *
291 * @ingroup List
292 */
293EAPI void elm_list_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
294
295/**
296 * Set the scrollbar policy.
297 *
298 * @param obj The list object
299 * @param policy_h Horizontal scrollbar policy.
300 * @param policy_v Vertical scrollbar policy.
301 *
302 * This sets the scrollbar visibility policy for the given scroller.
303 * #ELM_SCROLLER_POLICY_AUTO means the scrollbar is made visible if it
304 * is needed, and otherwise kept hidden. #ELM_SCROLLER_POLICY_ON turns
305 * it on all the time, and #ELM_SCROLLER_POLICY_OFF always keeps it off.
306 * This applies respectively for the horizontal and vertical scrollbars.
307 *
308 * The both are disabled by default, i.e., are set to
309 * #ELM_SCROLLER_POLICY_OFF.
310 *
311 * @ingroup List
312 */
313EAPI void elm_list_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
314
315/**
316 * Get the scrollbar policy.
317 *
318 * @see elm_list_scroller_policy_get() for details.
319 *
320 * @param obj The list object.
321 * @param policy_h Pointer to store horizontal scrollbar policy.
322 * @param policy_v Pointer to store vertical scrollbar policy.
323 *
324 * @ingroup List
325 */
326EAPI void elm_list_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
327
328/**
329 * Append a new item to the list object.
330 *
331 * @param obj The list object.
332 * @param label The label of the list item.
333 * @param icon The icon object to use for the left side of the item. An
334 * icon can be any Evas object, but usually it is an icon created
335 * with elm_icon_add().
336 * @param end The icon object to use for the right side of the item. An
337 * icon can be any Evas object.
338 * @param func The function to call when the item is clicked.
339 * @param data The data to associate with the item for related callbacks.
340 *
341 * @return The created item or @c NULL upon failure.
342 *
343 * A new item will be created and appended to the list, i.e., will
344 * be set as @b last item.
345 *
346 * Items created with this method can be deleted with elm_object_item_del().
347 *
348 * Associated @p data can be properly freed when item is deleted if a
349 * callback function is set with elm_widget_item_del_cb_set().
350 *
351 * If a function is passed as argument, it will be called every time this item
352 * is selected, i.e., the user clicks over an unselected item.
353 * If always select is enabled it will call this function every time
354 * user clicks over an item (already selected or not).
355 * If such function isn't needed, just passing
356 * @c NULL as @p func is enough. The same should be done for @p data.
357 *
358 * Simple example (with no function callback or data associated):
359 * @code
360 * li = elm_list_add(win);
361 * ic = elm_icon_add(win);
362 * elm_icon_file_set(ic, "path/to/image", NULL);
363 * elm_icon_resizable_set(ic, EINA_TRUE, EINA_TRUE);
364 * elm_list_item_append(li, "label", ic, NULL, NULL, NULL);
365 * elm_list_go(li);
366 * evas_object_show(li);
367 * @endcode
368 *
369 * @see elm_list_select_mode_set()
370 * @see elm_object_item_del()
371 * @see elm_widget_item_del_cb_set()
372 * @see elm_list_clear()
373 * @see elm_icon_add()
374 *
375 * @ingroup List
376 */
377EAPI Elm_Object_Item *elm_list_item_append(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data);
378
379/**
380 * Prepend a new item to the list object.
381 *
382 * @param obj The list object.
383 * @param label The label of the list item.
384 * @param icon The icon object to use for the left side of the item. An
385 * icon can be any Evas object, but usually it is an icon created
386 * with elm_icon_add().
387 * @param end The icon object to use for the right side of the item. An
388 * icon can be any Evas object.
389 * @param func The function to call when the item is clicked.
390 * @param data The data to associate with the item for related callbacks.
391 *
392 * @return The created item or @c NULL upon failure.
393 *
394 * A new item will be created and prepended to the list, i.e., will
395 * be set as @b first item.
396 *
397 * Items created with this method can be deleted with elm_object_item_del().
398 *
399 * Associated @p data can be properly freed when item is deleted if a
400 * callback function is set with elm_widget_item_del_cb_set().
401 *
402 * If a function is passed as argument, it will be called every time this item
403 * is selected, i.e., the user clicks over an unselected item.
404 * If always select is enabled it will call this function every time
405 * user clicks over an item (already selected or not).
406 * If such function isn't needed, just passing
407 * @c NULL as @p func is enough. The same should be done for @p data.
408 *
409 * @see elm_list_item_append() for a simple code example.
410 * @see elm_list_select_mode_set()
411 * @see elm_object_item_del()
412 * @see elm_widget_item_del_cb_set()
413 * @see elm_list_clear()
414 * @see elm_icon_add()
415 *
416 * @ingroup List
417 */
418EAPI Elm_Object_Item *elm_list_item_prepend(Evas_Object *obj, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data);
419
420/**
421 * Insert a new item into the list object before item @p before.
422 *
423 * @param obj The list object.
424 * @param before The list item to insert before.
425 * @param label The label of the list item.
426 * @param icon The icon object to use for the left side of the item. An
427 * icon can be any Evas object, but usually it is an icon created
428 * with elm_icon_add().
429 * @param end The icon object to use for the right side of the item. An
430 * icon can be any Evas object.
431 * @param func The function to call when the item is clicked.
432 * @param data The data to associate with the item for related callbacks.
433 *
434 * @return The created item or @c NULL upon failure.
435 *
436 * A new item will be created and added to the list. Its position in
437 * this list will be just before item @p before.
438 *
439 * Items created with this method can be deleted with elm_object_item_del().
440 *
441 * Associated @p data can be properly freed when item is deleted if a
442 * callback function is set with elm_widget_item_del_cb_set().
443 *
444 * If a function is passed as argument, it will be called every time this item
445 * is selected, i.e., the user clicks over an unselected item.
446 * If always select is enabled it will call this function every time
447 * user clicks over an item (already selected or not).
448 * If such function isn't needed, just passing
449 * @c NULL as @p func is enough. The same should be done for @p data.
450 *
451 * @see elm_list_item_append() for a simple code example.
452 * @see elm_list_select_mode_set()
453 * @see elm_object_item_del()
454 * @see elm_widget_item_del_cb_set()
455 * @see elm_list_clear()
456 * @see elm_icon_add()
457 *
458 * @ingroup List
459 */
460EAPI Elm_Object_Item *elm_list_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data);
461
462/**
463 * Insert a new item into the list object after item @p after.
464 *
465 * @param obj The list object.
466 * @param after The list item to insert after.
467 * @param label The label of the list item.
468 * @param icon The icon object to use for the left side of the item. An
469 * icon can be any Evas object, but usually it is an icon created
470 * with elm_icon_add().
471 * @param end The icon object to use for the right side of the item. An
472 * icon can be any Evas object.
473 * @param func The function to call when the item is clicked.
474 * @param data The data to associate with the item for related callbacks.
475 *
476 * @return The created item or @c NULL upon failure.
477 *
478 * A new item will be created and added to the list. Its position in
479 * this list will be just after item @p after.
480 *
481 * Items created with this method can be deleted with elm_object_item_del().
482 *
483 * Associated @p data can be properly freed when item is deleted if a
484 * callback function is set with elm_widget_item_del_cb_set().
485 *
486 * If a function is passed as argument, it will be called every time this item
487 * is selected, i.e., the user clicks over an unselected item.
488 * If always select is enabled it will call this function every time
489 * user clicks over an item (already selected or not).
490 * If such function isn't needed, just passing
491 * @c NULL as @p func is enough. The same should be done for @p data.
492 *
493 * @see elm_list_item_append() for a simple code example.
494 * @see elm_list_select_mode_set()
495 * @see elm_object_item_del()
496 * @see elm_widget_item_del_cb_set()
497 * @see elm_list_clear()
498 * @see elm_icon_add()
499 *
500 * @ingroup List
501 */
502EAPI Elm_Object_Item *elm_list_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *label, Evas_Object *icon, Evas_Object *end, Evas_Smart_Cb func, const void *data);
503
504/**
505 * Insert a new item into the sorted list object.
506 *
507 * @param obj The list object.
508 * @param label The label of the list item.
509 * @param icon The icon object to use for the left side of the item. An
510 * icon can be any Evas object, but usually it is an icon created
511 * with elm_icon_add().
512 * @param end The icon object to use for the right side of the item. An
513 * icon can be any Evas object.
514 * @param func The function to call when the item is clicked.
515 * @param data The data to associate with the item for related callbacks.
516 * @param cmp_func The comparing function to be used to sort list
517 * items <b>by #Elm_Object_Item item handles</b>. This function will
518 * receive two items and compare them, returning a non-negative integer
519 * if the second item should be place after the first, or negative value
520 * if should be placed before.
521 *
522 * @return The created item or @c NULL upon failure.
523 *
524 * @note This function inserts values into a list object assuming it was
525 * sorted and the result will be sorted.
526 *
527 * A new item will be created and added to the list. Its position in
528 * this list will be found comparing the new item with previously inserted
529 * items using function @p cmp_func.
530 *
531 * Items created with this method can be deleted with elm_object_item_del().
532 *
533 * Associated @p data can be properly freed when item is deleted if a
534 * callback function is set with elm_widget_item_del_cb_set().
535 *
536 * If a function is passed as argument, it will be called every time this item
537 * is selected, i.e., the user clicks over an unselected item.
538 * If always select is enabled it will call this function every time
539 * user clicks over an item (already selected or not).
540 * If such function isn't needed, just passing
541 * @c NULL as @p func is enough. The same should be done for @p data.
542 *
543 * @see elm_list_item_append() for a simple code example.
544 * @see elm_list_select_mode_set()
545 * @see elm_object_item_del()
546 * @see elm_widget_item_del_cb_set()
547 * @see elm_list_clear()
548 * @see elm_icon_add()
549 *
550 * @ingroup List
551 */
552EAPI Elm_Object_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);
553
554/**
555 * Remove all list's items.
556 *
557 * @param obj The list object
558 *
559 * @see elm_object_item_del()
560 * @see elm_list_item_append()
561 *
562 * @ingroup List
563 */
564EAPI void elm_list_clear(Evas_Object *obj);
565
566/**
567 * Get a list of all the list items.
568 *
569 * @param obj The list object
570 * @return An @c Eina_List of list items, #Elm_Object_Item,
571 * or @c NULL on failure.
572 *
573 * @see elm_list_item_append()
574 * @see elm_object_item_del()
575 * @see elm_list_clear()
576 *
577 * @ingroup List
578 */
579EAPI const Eina_List *elm_list_items_get(const Evas_Object *obj);
580
581/**
582 * Get the selected item.
583 *
584 * @param obj The list object.
585 * @return The selected list item.
586 *
587 * The selected item can be unselected with function
588 * elm_list_item_selected_set().
589 *
590 * The selected item always will be highlighted on list.
591 *
592 * @see elm_list_selected_items_get()
593 *
594 * @ingroup List
595 */
596EAPI Elm_Object_Item *elm_list_selected_item_get(const Evas_Object *obj);
597
598/**
599 * Return a list of the currently selected list items.
600 *
601 * @param obj The list object.
602 * @return An @c Eina_List of list items, #Elm_Object_Item,
603 * or @c NULL on failure.
604 *
605 * Multiple items can be selected if multi select is enabled. It can be
606 * done with elm_list_multi_select_set().
607 *
608 * @see elm_list_selected_item_get()
609 * @see elm_list_multi_select_set()
610 *
611 * @ingroup List
612 */
613EAPI const Eina_List *elm_list_selected_items_get(const Evas_Object *obj);
614
615/**
616 * Set the selected state of an item.
617 *
618 * @param it The list item
619 * @param selected The selected state
620 *
621 * This sets the selected state of the given item @p it.
622 * @c EINA_TRUE for selected, @c EINA_FALSE for not selected.
623 *
624 * If a new item is selected the previously selected will be unselected,
625 * unless multiple selection is enabled with elm_list_multi_select_set().
626 * Previously selected item can be get with function
627 * elm_list_selected_item_get().
628 *
629 * Selected items will be highlighted.
630 *
631 * @see elm_list_item_selected_get()
632 * @see elm_list_selected_item_get()
633 * @see elm_list_multi_select_set()
634 *
635 * @ingroup List
636 */
637EAPI void elm_list_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
638
639/*
640 * Get whether the @p item is selected or not.
641 *
642 * @param it The list item.
643 * @return @c EINA_TRUE means item is selected. @c EINA_FALSE indicates
644 * it's not. If @p obj is @c NULL, @c EINA_FALSE is returned.
645 *
646 * @see elm_list_selected_item_set() for details.
647 * @see elm_list_item_selected_get()
648 *
649 * @ingroup List
650 */
651EAPI Eina_Bool elm_list_item_selected_get(const Elm_Object_Item *it);
652
653/**
654 * Set or unset item as a separator.
655 *
656 * @param it The list item.
657 * @param setting @c EINA_TRUE to set item @p it as separator or
658 * @c EINA_FALSE to unset, i.e., item will be used as a regular item.
659 *
660 * Items aren't set as separator by default.
661 *
662 * If set as separator it will display separator theme, so won't display
663 * icons or label.
664 *
665 * @see elm_list_item_separator_get()
666 *
667 * @ingroup List
668 */
669EAPI void elm_list_item_separator_set(Elm_Object_Item *it, Eina_Bool setting);
670
671/**
672 * Get a value whether item is a separator or not.
673 *
674 * @see elm_list_item_separator_set() for details.
675 *
676 * @param it The list item.
677 * @return @c EINA_TRUE means item @p it is a separator. @c EINA_FALSE
678 * indicates it's not. If @p it is @c NULL, @c EINA_FALSE is returned.
679 *
680 * @ingroup List
681 */
682EAPI Eina_Bool elm_list_item_separator_get(const Elm_Object_Item *it);
683
684/**
685 * Show @p item in the list view.
686 *
687 * @param it The list item to be shown.
688 *
689 * It won't animate list until item is visible. If such behavior is wanted,
690 * use elm_list_bring_in() instead.
691 *
692 * @ingroup List
693 */
694EAPI void elm_list_item_show(Elm_Object_Item *it);
695
696/**
697 * Bring in the given item to list view.
698 *
699 * @param it The item.
700 *
701 * This causes list to jump to the given item @p item and show it
702 * (by scrolling), if it is not fully visible.
703 *
704 * This may use animation to do so and take a period of time.
705 *
706 * If animation isn't wanted, elm_list_item_show() can be used.
707 *
708 * @ingroup List
709 */
710EAPI void elm_list_item_bring_in(Elm_Object_Item *it);
711
712/**
713 * Gets the base object of the item.
714 *
715 * @param it The list item
716 * @return The base object associated with @p item
717 *
718 * Base object is the @c Evas_Object that represents that item.
719 *
720 * @ingroup List
721 */
722EAPI Evas_Object *elm_list_item_object_get(const Elm_Object_Item *it);
723
724/**
725 * Get the item before @p it in list.
726 *
727 * @param it The list item.
728 * @return The item before @p it, or @c NULL if none or on failure.
729 *
730 * @note If it is the first item, @c NULL will be returned.
731 *
732 * @see elm_list_item_append()
733 * @see elm_list_items_get()
734 *
735 * @ingroup List
736 */
737EAPI Elm_Object_Item *elm_list_item_prev(const Elm_Object_Item *it);
738
739/**
740 * Get the item after @p it in list.
741 *
742 * @param it The list item.
743 * @return The item after @p it, or @c NULL if none or on failure.
744 *
745 * @note If it is the last item, @c NULL will be returned.
746 *
747 * @see elm_list_item_append()
748 * @see elm_list_items_get()
749 *
750 * @ingroup List
751 */
752EAPI Elm_Object_Item *elm_list_item_next(const Elm_Object_Item *it);
753
754/**
755 * Get the first item in the list
756 *
757 * This returns the first item in the list.
758 *
759 * @param obj The list object
760 * @return The first item, or NULL if none
761 *
762 * @ingroup List
763 */
764EAPI Elm_Object_Item *elm_list_first_item_get(const Evas_Object *obj);
765
766/**
767 * Get the last item in the list
768 *
769 * This returns the last item in the list.
770 *
771 * @return The last item, or NULL if none
772 *
773 * @ingroup List
774 */
775EAPI Elm_Object_Item *elm_list_last_item_get(const Evas_Object *obj);
776
777/**
778 * @}
779 */
diff --git a/libraries/elementary/src/lib/elm_macros.h b/libraries/elementary/src/lib/elm_macros.h
new file mode 100644
index 0000000..906b883
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_macros.h
@@ -0,0 +1,3 @@
1/* handy macros */
2#define ELM_RECTS_INTERSECT(x, y, w, h, xx, yy, ww, hh) (((x) < ((xx) + (ww))) && ((y) < ((yy) + (hh))) && (((x) + (w)) > (xx)) && (((y) + (h)) > (yy)))
3#define ELM_PI 3.14159265358979323846
diff --git a/libraries/elementary/src/lib/elm_main.c b/libraries/elementary/src/lib/elm_main.c
new file mode 100644
index 0000000..4f860ba
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_main.c
@@ -0,0 +1,1490 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#ifdef HAVE_FORK
6#include <dlfcn.h> /* dlopen,dlclose,etc */
7#endif
8
9#ifdef HAVE_CRT_EXTERNS_H
10# include <crt_externs.h>
11#endif
12
13#ifdef HAVE_EVIL
14# include <Evil.h>
15#endif
16
17#include <Elementary.h>
18#include "elm_priv.h"
19
20#define SEMI_BROKEN_QUICKLAUNCH 1
21
22static Elm_Version _version = { VMAJ, VMIN, VMIC, VREV };
23EAPI Elm_Version *elm_version = &_version;
24
25Eina_Bool
26_elm_dangerous_call_check(const char *call)
27{
28 char buf[256];
29 const char *eval;
30
31 snprintf(buf, sizeof(buf), "%i.%i.%i.%i", VMAJ, VMIN, VMIC, VREV);
32 eval = getenv("ELM_NO_FINGER_WAGGLING");
33 if ((eval) && (!strcmp(eval, buf)))
34 return 0;
35 printf("ELEMENTARY FINGER WAGGLE!!!!!!!!!!\n"
36 "\n"
37 " %s() used.\n"
38 "PLEASE see the API documentation for this function. This call\n"
39 "should almost never be used. Only in very special cases.\n"
40 "\n"
41 "To remove this warning please set the environment variable:\n"
42 " ELM_NO_FINGER_WAGGLING\n"
43 "To the value of the Elementary version + revision number. e.g.:\n"
44 " 1.2.5.40295\n"
45 "\n"
46 ,
47 call);
48 return 1;
49}
50
51static Eina_Bool _elm_signal_exit(void *data,
52 int ev_type,
53 void *ev);
54
55static Eina_Prefix *pfx = NULL;
56char *_elm_appname = NULL;
57const char *_elm_data_dir = NULL;
58const char *_elm_lib_dir = NULL;
59int _elm_log_dom = -1;
60
61EAPI int ELM_EVENT_POLICY_CHANGED = 0;
62
63static int _elm_init_count = 0;
64static int _elm_sub_init_count = 0;
65static int _elm_ql_init_count = 0;
66static int _elm_policies[ELM_POLICY_LAST];
67static Ecore_Event_Handler *_elm_exit_handler = NULL;
68static Eina_Bool quicklaunch_on = 0;
69
70static Eina_Bool
71_elm_signal_exit(void *data __UNUSED__,
72 int ev_type __UNUSED__,
73 void *ev __UNUSED__)
74{
75 elm_exit();
76 return ECORE_CALLBACK_PASS_ON;
77}
78
79void
80_elm_rescale(void)
81{
82 edje_scale_set(_elm_config->scale);
83 _elm_win_rescale(NULL, EINA_FALSE);
84 _elm_ews_wm_rescale(NULL, EINA_FALSE);
85}
86
87static void *app_mainfunc = NULL;
88static const char *app_domain = NULL;
89static const char *app_checkfile = NULL;
90
91static const char *app_compile_bin_dir = NULL;
92static const char *app_compile_lib_dir = NULL;
93static const char *app_compile_data_dir = NULL;
94static const char *app_compile_locale_dir = NULL;
95static const char *app_prefix_dir = NULL;
96static const char *app_bin_dir = NULL;
97static const char *app_lib_dir = NULL;
98static const char *app_data_dir = NULL;
99static const char *app_locale_dir = NULL;
100
101static Eina_Prefix *app_pfx = NULL;
102
103static void
104_prefix_check(void)
105{
106 int argc = 0;
107 char **argv = NULL;
108 const char *dirs[4] = { NULL, NULL, NULL, NULL };
109 char *caps = NULL, *p1, *p2;
110 char buf[PATH_MAX];
111
112 if (app_pfx) return;
113 if (!app_domain) return;
114
115 ecore_app_args_get(&argc, &argv);
116 if (argc < 1) return;
117
118 dirs[0] = app_compile_bin_dir;
119 dirs[1] = app_compile_lib_dir;
120 dirs[2] = app_compile_data_dir;
121 dirs[3] = app_compile_locale_dir;
122
123 if (!dirs[0]) dirs[0] = "/usr/local/bin";
124 if (!dirs[1]) dirs[1] = "/usr/local/lib";
125 if (!dirs[2])
126 {
127 snprintf(buf, sizeof(buf), "/usr/local/share/%s", app_domain);
128 dirs[2] = buf;
129 }
130 if (!dirs[3]) dirs[3] = dirs[2];
131
132 if (app_domain)
133 {
134 caps = alloca(strlen(app_domain) + 1);
135 for (p1 = (char *)app_domain, p2 = caps; *p1; p1++, p2++)
136 *p2 = toupper(*p1);
137 *p2 = 0;
138 }
139 app_pfx = eina_prefix_new(argv[0], app_mainfunc, caps, app_domain,
140 app_checkfile, dirs[0], dirs[1], dirs[2], dirs[3]);
141}
142
143static void
144_prefix_shutdown(void)
145{
146 if (app_pfx) eina_prefix_free(app_pfx);
147 if (app_domain) eina_stringshare_del(app_domain);
148 if (app_checkfile) eina_stringshare_del(app_checkfile);
149 if (app_compile_bin_dir) eina_stringshare_del(app_compile_bin_dir);
150 if (app_compile_lib_dir) eina_stringshare_del(app_compile_lib_dir);
151 if (app_compile_data_dir) eina_stringshare_del(app_compile_data_dir);
152 if (app_compile_locale_dir) eina_stringshare_del(app_compile_locale_dir);
153 if (app_prefix_dir) eina_stringshare_del(app_prefix_dir);
154 if (app_bin_dir) eina_stringshare_del(app_bin_dir);
155 if (app_lib_dir) eina_stringshare_del(app_lib_dir);
156 if (app_data_dir) eina_stringshare_del(app_data_dir);
157 if (app_locale_dir) eina_stringshare_del(app_locale_dir);
158 app_mainfunc = NULL;
159 app_domain = NULL;
160 app_checkfile = NULL;
161 app_compile_bin_dir = NULL;
162 app_compile_lib_dir = NULL;
163 app_compile_data_dir = NULL;
164 app_compile_locale_dir = NULL;
165 app_prefix_dir = NULL;
166 app_bin_dir = NULL;
167 app_lib_dir = NULL;
168 app_data_dir = NULL;
169 app_locale_dir = NULL;
170 app_pfx = NULL;
171}
172
173EAPI int
174elm_init(int argc,
175 char **argv)
176{
177 _elm_init_count++;
178 if (_elm_init_count > 1) return _elm_init_count;
179 elm_quicklaunch_init(argc, argv);
180 elm_quicklaunch_sub_init(argc, argv);
181 _prefix_shutdown();
182 return _elm_init_count;
183}
184
185EAPI int
186elm_shutdown(void)
187{
188 _elm_init_count--;
189 if (_elm_init_count > 0) return _elm_init_count;
190 _elm_win_shutdown();
191 while (_elm_win_deferred_free) ecore_main_loop_iterate();
192// wrningz :(
193// _prefix_shutdown();
194 elm_quicklaunch_sub_shutdown();
195 elm_quicklaunch_shutdown();
196 return _elm_init_count;
197}
198
199EAPI void
200elm_app_info_set(void *mainfunc, const char *dom, const char *checkfile)
201{
202 app_mainfunc = mainfunc;
203 eina_stringshare_replace(&app_domain, dom);
204 eina_stringshare_replace(&app_checkfile, checkfile);
205}
206
207EAPI void
208elm_app_compile_bin_dir_set(const char *dir)
209{
210 eina_stringshare_replace(&app_compile_bin_dir, dir);
211}
212
213EAPI void
214elm_app_compile_lib_dir_set(const char *dir)
215{
216 eina_stringshare_replace(&app_compile_lib_dir, dir);
217}
218
219EAPI void
220elm_app_compile_data_dir_set(const char *dir)
221{
222 eina_stringshare_replace(&app_compile_data_dir, dir);
223}
224
225EAPI void
226elm_app_compile_locale_set(const char *dir)
227{
228 eina_stringshare_replace(&app_compile_locale_dir, dir);
229}
230
231EAPI const char *
232elm_app_prefix_dir_get(void)
233{
234 if (app_prefix_dir) return app_prefix_dir;
235 _prefix_check();
236 if (!app_pfx) return "";
237 app_prefix_dir = eina_prefix_get(app_pfx);
238 return app_prefix_dir;
239}
240
241EAPI const char *
242elm_app_bin_dir_get(void)
243{
244 if (app_bin_dir) return app_bin_dir;
245 _prefix_check();
246 if (!app_pfx) return "";
247 app_bin_dir = eina_prefix_bin_get(app_pfx);
248 return app_bin_dir;
249}
250
251EAPI const char *
252elm_app_lib_dir_get(void)
253{
254 if (app_lib_dir) return app_lib_dir;
255 _prefix_check();
256 if (!app_pfx) return "";
257 app_lib_dir = eina_prefix_lib_get(app_pfx);
258 return app_lib_dir;
259}
260
261EAPI const char *
262elm_app_data_dir_get(void)
263{
264 if (app_data_dir) return app_data_dir;
265 _prefix_check();
266 if (!app_pfx) return "";
267 app_data_dir = eina_prefix_data_get(app_pfx);
268 return app_data_dir;
269}
270
271EAPI const char *
272elm_app_locale_dir_get(void)
273{
274 if (app_locale_dir) return app_locale_dir;
275 _prefix_check();
276 if (!app_pfx) return "";
277 app_locale_dir = eina_prefix_locale_get(app_pfx);
278 return app_locale_dir;
279}
280
281#ifdef ELM_EDBUS
282static int _elm_need_e_dbus = 0;
283#endif
284EAPI Eina_Bool
285elm_need_e_dbus(void)
286{
287#ifdef ELM_EDBUS
288 if (_elm_need_e_dbus++) return EINA_TRUE;
289 e_dbus_init();
290 return EINA_TRUE;
291#else
292 return EINA_FALSE;
293#endif
294}
295
296static void
297_elm_unneed_e_dbus(void)
298{
299#ifdef ELM_EDBUS
300 if (--_elm_need_e_dbus) return;
301
302 _elm_need_e_dbus = 0;
303 e_dbus_shutdown();
304#endif
305}
306
307#ifdef ELM_EFREET
308static int _elm_need_efreet = 0;
309#endif
310EAPI Eina_Bool
311elm_need_efreet(void)
312{
313#ifdef ELM_EFREET
314 if (_elm_need_efreet++) return EINA_TRUE;
315 efreet_init();
316 efreet_mime_init();
317 efreet_trash_init();
318 /*
319 {
320 Eina_List **list;
321
322 list = efreet_icon_extra_list_get();
323 if (list)
324 {
325 e_user_dir_concat_static(buf, "icons");
326 *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
327 e_prefix_data_concat_static(buf, "data/icons");
328 *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buf));
329 }
330 }
331 */
332 return EINA_TRUE;
333#else
334 return EINA_FALSE;
335#endif
336}
337
338static void
339_elm_unneed_efreet(void)
340{
341#ifdef ELM_EFREET
342 if (--_elm_need_efreet) return;
343
344 _elm_need_efreet = 0;
345 efreet_trash_shutdown();
346 efreet_mime_shutdown();
347 efreet_shutdown();
348#endif
349}
350
351EAPI void
352elm_quicklaunch_mode_set(Eina_Bool ql_on)
353{
354 quicklaunch_on = ql_on;
355}
356
357EAPI Eina_Bool
358elm_quicklaunch_mode_get(void)
359{
360 return quicklaunch_on;
361}
362
363EAPI int
364elm_quicklaunch_init(int argc,
365 char **argv)
366{
367 _elm_ql_init_count++;
368 if (_elm_ql_init_count > 1) return _elm_ql_init_count;
369 eina_init();
370 _elm_log_dom = eina_log_domain_register("elementary", EINA_COLOR_LIGHTBLUE);
371 if (!_elm_log_dom)
372 {
373 EINA_LOG_ERR("could not register elementary log domain.");
374 _elm_log_dom = EINA_LOG_DOMAIN_GLOBAL;
375 }
376
377 eet_init();
378 ecore_init();
379
380#ifdef HAVE_ELEMENTARY_EMAP
381 emap_init();
382#endif
383 ecore_app_args_set(argc, (const char **)argv);
384
385 memset(_elm_policies, 0, sizeof(_elm_policies));
386 if (!ELM_EVENT_POLICY_CHANGED)
387 ELM_EVENT_POLICY_CHANGED = ecore_event_type_new();
388
389 ecore_file_init();
390
391 _elm_exit_handler = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, _elm_signal_exit, NULL);
392
393 if (argv) _elm_appname = strdup(ecore_file_file_get(argv[0]));
394
395 pfx = eina_prefix_new(argv ? argv[0] : NULL, elm_quicklaunch_init,
396 "ELM", "elementary", "config/profile.cfg",
397 PACKAGE_LIB_DIR, /* don't have a bin dir currently */
398 PACKAGE_LIB_DIR,
399 PACKAGE_DATA_DIR,
400 LOCALE_DIR);
401 if (pfx)
402 {
403 _elm_data_dir = eina_stringshare_add(eina_prefix_data_get(pfx));
404 _elm_lib_dir = eina_stringshare_add(eina_prefix_lib_get(pfx));
405 }
406 if (!_elm_data_dir) _elm_data_dir = eina_stringshare_add("/");
407 if (!_elm_lib_dir) _elm_lib_dir = eina_stringshare_add("/");
408
409 return _elm_ql_init_count;
410}
411
412EAPI int
413elm_quicklaunch_sub_init(int argc,
414 char **argv)
415{
416 _elm_sub_init_count++;
417 if (_elm_sub_init_count > 1) return _elm_sub_init_count;
418 if (quicklaunch_on)
419 {
420 _elm_config_init();
421#ifdef SEMI_BROKEN_QUICKLAUNCH
422 return _elm_sub_init_count;
423#endif
424 }
425 if (!quicklaunch_on)
426 {
427 ecore_app_args_set(argc, (const char **)argv);
428 evas_init();
429 edje_init();
430 _elm_module_init();
431 _elm_config_init();
432 _elm_config_sub_init();
433 ecore_evas_init(); // FIXME: check errors
434#ifdef HAVE_ELEMENTARY_ECORE_IMF
435 ecore_imf_init();
436#endif
437#ifdef HAVE_ELEMENTARY_ECORE_CON
438 ecore_con_init();
439 ecore_con_url_init();
440#endif
441 _elm_ews_wm_init();
442 }
443 return _elm_sub_init_count;
444}
445
446EAPI int
447elm_quicklaunch_sub_shutdown(void)
448{
449 _elm_sub_init_count--;
450 if (_elm_sub_init_count > 0) return _elm_sub_init_count;
451 if (quicklaunch_on)
452 {
453#ifdef SEMI_BROKEN_QUICKLAUNCH
454 return _elm_sub_init_count;
455#endif
456 }
457 if (!quicklaunch_on)
458 {
459 _elm_win_shutdown();
460 _elm_module_shutdown();
461 _elm_ews_wm_shutdown();
462#ifdef HAVE_ELEMENTARY_ECORE_CON
463 ecore_con_url_shutdown();
464 ecore_con_shutdown();
465#endif
466#ifdef HAVE_ELEMENTARY_ECORE_IMF
467 ecore_imf_shutdown();
468#endif
469 ecore_evas_shutdown();
470 _elm_config_sub_shutdown();
471#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
472 if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
473 ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
474 ENGINE_COMPARE(ELM_XRENDER_X11) ||
475 ENGINE_COMPARE(ELM_OPENGL_X11) ||
476 ENGINE_COMPARE(ELM_SOFTWARE_SDL) ||
477 ENGINE_COMPARE(ELM_SOFTWARE_16_SDL) ||
478 ENGINE_COMPARE(ELM_OPENGL_SDL) ||
479 ENGINE_COMPARE(ELM_OPENGL_COCOA) ||
480 ENGINE_COMPARE(ELM_SOFTWARE_WIN32) ||
481 ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE) ||
482 ENGINE_COMPARE(ELM_EWS))
483#undef ENGINE_COMPARE
484 evas_cserve_disconnect();
485 edje_shutdown();
486 evas_shutdown();
487 }
488 return _elm_sub_init_count;
489}
490
491EAPI int
492elm_quicklaunch_shutdown(void)
493{
494 _elm_ql_init_count--;
495 if (_elm_ql_init_count > 0) return _elm_ql_init_count;
496 if (pfx) eina_prefix_free(pfx);
497 pfx = NULL;
498 eina_stringshare_del(_elm_data_dir);
499 _elm_data_dir = NULL;
500 eina_stringshare_del(_elm_lib_dir);
501 _elm_lib_dir = NULL;
502
503 free(_elm_appname);
504 _elm_appname = NULL;
505
506 _elm_config_shutdown();
507
508 ecore_event_handler_del(_elm_exit_handler);
509 _elm_exit_handler = NULL;
510
511 _elm_theme_shutdown();
512 _elm_unneed_efreet();
513 _elm_unneed_e_dbus();
514 _elm_unneed_ethumb();
515 _elm_unneed_web();
516 ecore_file_shutdown();
517
518#ifdef HAVE_ELEMENTARY_EMAP
519 emap_shutdown();
520#endif
521
522 ecore_shutdown();
523 eet_shutdown();
524
525 if ((_elm_log_dom > -1) && (_elm_log_dom != EINA_LOG_DOMAIN_GLOBAL))
526 {
527 eina_log_domain_unregister(_elm_log_dom);
528 _elm_log_dom = -1;
529 }
530
531 _elm_widget_type_clear();
532
533 eina_shutdown();
534 return _elm_ql_init_count;
535}
536
537EAPI void
538elm_quicklaunch_seed(void)
539{
540#ifndef SEMI_BROKEN_QUICKLAUNCH
541 if (quicklaunch_on)
542 {
543 Evas_Object *win, *bg, *bt;
544
545 win = elm_win_add(NULL, "seed", ELM_WIN_BASIC);
546 bg = elm_bg_add(win);
547 elm_win_resize_object_add(win, bg);
548 evas_object_show(bg);
549 bt = elm_button_add(win);
550 elm_object_text_set(bt, " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~-_=+\\|]}[{;:'\",<.>/?");
551 elm_win_resize_object_add(win, bt);
552 ecore_main_loop_iterate();
553 evas_object_del(win);
554 ecore_main_loop_iterate();
555#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
556 if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
557 ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
558 ENGINE_COMPARE(ELM_XRENDER_X11) ||
559 ENGINE_COMPARE(ELM_OPENGL_X11))
560#undef ENGINE_COMPARE
561 {
562# ifdef HAVE_ELEMENTARY_X
563 ecore_x_sync();
564# endif
565 }
566 ecore_main_loop_iterate();
567 }
568#endif
569}
570
571#ifdef HAVE_FORK
572static void *qr_handle = NULL;
573#endif
574static int (*qr_main)(int argc,
575 char **argv) = NULL;
576
577EAPI Eina_Bool
578elm_quicklaunch_prepare(int argc __UNUSED__,
579 char **argv)
580{
581#ifdef HAVE_FORK
582 char *exe = elm_quicklaunch_exe_path_get(argv[0]);
583 if (!exe)
584 {
585 ERR("requested quicklaunch binary '%s' does not exist\n", argv[0]);
586 return EINA_FALSE;
587 }
588 else
589 {
590 char *exe2, *p;
591 char *exename;
592
593 exe2 = malloc(strlen(exe) + 1 + 10);
594 strcpy(exe2, exe);
595 p = strrchr(exe2, '/');
596 if (p) p++;
597 else p = exe2;
598 exename = alloca(strlen(p) + 1);
599 strcpy(exename, p);
600 *p = 0;
601 strcat(p, "../lib/");
602 strcat(p, exename);
603 strcat(p, ".so");
604 if (!access(exe2, R_OK | X_OK))
605 {
606 free(exe);
607 exe = exe2;
608 }
609 else
610 free(exe2);
611 }
612 qr_handle = dlopen(exe, RTLD_NOW | RTLD_GLOBAL);
613 if (!qr_handle)
614 {
615 fprintf(stderr, "dlerr: %s\n", dlerror());
616 WRN("dlopen('%s') failed: %s", exe, dlerror());
617 free(exe);
618 return EINA_FALSE;
619 }
620 INF("dlopen('%s') = %p", exe, qr_handle);
621 qr_main = dlsym(qr_handle, "elm_main");
622 INF("dlsym(%p, 'elm_main') = %p", qr_handle, qr_main);
623 if (!qr_main)
624 {
625 WRN("not quicklauncher capable: no elm_main in '%s'", exe);
626 dlclose(qr_handle);
627 qr_handle = NULL;
628 free(exe);
629 return EINA_FALSE;
630 }
631 free(exe);
632 return EINA_TRUE;
633#else
634 return EINA_FALSE;
635 (void)argv;
636#endif
637}
638
639#ifdef HAVE_FORK
640static void
641save_env(void)
642{
643 int i, size;
644 extern char **environ;
645 char **oldenv, **p;
646
647 oldenv = environ;
648
649 for (i = 0, size = 0; environ[i]; i++)
650 size += strlen(environ[i]) + 1;
651
652 p = malloc((i + 1) * sizeof(char *));
653 if (!p) return;
654
655 environ = p;
656
657 for (i = 0; oldenv[i]; i++)
658 environ[i] = strdup(oldenv[i]);
659 environ[i] = NULL;
660}
661
662#endif
663
664EAPI Eina_Bool
665elm_quicklaunch_fork(int argc,
666 char **argv,
667 char *cwd,
668 void (postfork_func) (void *data),
669 void *postfork_data)
670{
671#ifdef HAVE_FORK
672 pid_t child;
673 int ret;
674 int real_argc;
675 char **real_argv;
676
677 // FIXME:
678 // need to accept current environment from elementary_run
679 if (!qr_main)
680 {
681 int i;
682 char **args;
683
684 child = fork();
685 if (child > 0) return EINA_TRUE;
686 else if (child < 0)
687 {
688 perror("could not fork");
689 return EINA_FALSE;
690 }
691 setsid();
692 if (chdir(cwd) != 0)
693 perror("could not chdir");
694 args = alloca((argc + 1) * sizeof(char *));
695 for (i = 0; i < argc; i++) args[i] = argv[i];
696 args[argc] = NULL;
697 WRN("%s not quicklaunch capable, fallback...", argv[0]);
698 execvp(argv[0], args);
699 ERR("failed to execute '%s': %s", argv[0], strerror(errno));
700 exit(-1);
701 }
702 child = fork();
703 if (child > 0) return EINA_TRUE;
704 else if (child < 0)
705 {
706 perror("could not fork");
707 return EINA_FALSE;
708 }
709 if (postfork_func) postfork_func(postfork_data);
710
711 if (quicklaunch_on)
712 {
713#ifdef SEMI_BROKEN_QUICKLAUNCH
714 ecore_app_args_set(argc, (const char **)argv);
715 evas_init();
716 edje_init();
717 _elm_config_sub_init();
718#define ENGINE_COMPARE(name) (!strcmp(_elm_config->engine, name))
719 if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
720 ENGINE_COMPARE(ELM_SOFTWARE_16_X11) ||
721 ENGINE_COMPARE(ELM_XRENDER_X11) ||
722 ENGINE_COMPARE(ELM_OPENGL_X11))
723#undef ENGINE_COMPARE
724 {
725# ifdef HAVE_ELEMENTARY_X
726 ecore_x_init(NULL);
727# endif
728 }
729 ecore_evas_init(); // FIXME: check errors
730# ifdef HAVE_ELEMENTARY_ECORE_IMF
731 ecore_imf_init();
732# endif
733 _elm_module_init();
734#endif
735 }
736
737 setsid();
738 if (chdir(cwd) != 0)
739 perror("could not chdir");
740 // FIXME: this is very linux specific. it changes argv[0] of the process
741 // so ps etc. report what you'd expect. for other unixes and os's this
742 // may just not work
743 save_env();
744 if (argv)
745 {
746 char *lastarg, *p;
747
748 ecore_app_args_get(&real_argc, &real_argv);
749 lastarg = real_argv[real_argc - 1] + strlen(real_argv[real_argc - 1]);
750 for (p = real_argv[0]; p < lastarg; p++) *p = 0;
751 strcpy(real_argv[0], argv[0]);
752 }
753 ecore_app_args_set(argc, (const char **)argv);
754 ret = qr_main(argc, argv);
755 exit(ret);
756 return EINA_TRUE;
757#else
758 return EINA_FALSE;
759 (void)argc;
760 (void)argv;
761 (void)cwd;
762 (void)postfork_func;
763 (void)postfork_data;
764#endif
765}
766
767EAPI void
768elm_quicklaunch_cleanup(void)
769{
770#ifdef HAVE_FORK
771 if (qr_handle)
772 {
773 dlclose(qr_handle);
774 qr_handle = NULL;
775 qr_main = NULL;
776 }
777#endif
778}
779
780EAPI int
781elm_quicklaunch_fallback(int argc,
782 char **argv)
783{
784 int ret;
785 elm_quicklaunch_init(argc, argv);
786 elm_quicklaunch_sub_init(argc, argv);
787 elm_quicklaunch_prepare(argc, argv);
788 ret = qr_main(argc, argv);
789 exit(ret);
790 return ret;
791}
792
793EAPI char *
794elm_quicklaunch_exe_path_get(const char *exe)
795{
796 static char *path = NULL;
797 static Eina_List *pathlist = NULL;
798 const char *pathitr;
799 const Eina_List *l;
800 char buf[PATH_MAX];
801 if (exe[0] == '/') return strdup(exe);
802 if ((exe[0] == '.') && (exe[1] == '/')) return strdup(exe);
803 if ((exe[0] == '.') && (exe[1] == '.') && (exe[2] == '/')) return strdup(exe);
804 if (!path)
805 {
806 const char *p, *pp;
807 char *buf2;
808 path = getenv("PATH");
809 buf2 = alloca(strlen(path) + 1);
810 p = path;
811 pp = p;
812 for (;; )
813 {
814 if ((*p == ':') || (!*p))
815 {
816 int len;
817
818 len = p - pp;
819 strncpy(buf2, pp, len);
820 buf2[len] = 0;
821 pathlist = eina_list_append(pathlist, eina_stringshare_add(buf2));
822 if (!*p) break;
823 p++;
824 pp = p;
825 }
826 else
827 {
828 if (!*p) break;
829 p++;
830 }
831 }
832 }
833 EINA_LIST_FOREACH(pathlist, l, pathitr)
834 {
835 snprintf(buf, sizeof(buf), "%s/%s", pathitr, exe);
836 if (!access(buf, R_OK | X_OK)) return strdup(buf);
837 }
838 return NULL;
839}
840
841EAPI void
842elm_run(void)
843{
844 ecore_main_loop_begin();
845}
846
847EAPI void
848elm_exit(void)
849{
850 ecore_main_loop_quit();
851}
852
853EAPI Eina_Bool
854elm_policy_set(unsigned int policy,
855 int value)
856{
857 Elm_Event_Policy_Changed *ev;
858
859 if (policy >= ELM_POLICY_LAST)
860 return EINA_FALSE;
861
862 if (value == _elm_policies[policy])
863 return EINA_TRUE;
864
865 /* TODO: validade policy? */
866
867 ev = malloc(sizeof(*ev));
868 ev->policy = policy;
869 ev->new_value = value;
870 ev->old_value = _elm_policies[policy];
871
872 _elm_policies[policy] = value;
873
874 ecore_event_add(ELM_EVENT_POLICY_CHANGED, ev, NULL, NULL);
875
876 return EINA_TRUE;
877}
878
879EAPI int
880elm_policy_get(unsigned int policy)
881{
882 if (policy >= ELM_POLICY_LAST)
883 return 0;
884 return _elm_policies[policy];
885}
886
887EAPI void
888elm_language_set(const char *lang)
889{
890 setlocale(LC_ALL, lang);
891 _elm_win_translate();
892}
893
894EAPI Eina_Bool
895elm_object_mirrored_get(const Evas_Object *obj)
896{
897 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
898 return elm_widget_mirrored_get(obj);
899}
900
901EAPI void
902elm_object_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
903{
904 EINA_SAFETY_ON_NULL_RETURN(obj);
905 elm_widget_mirrored_set(obj, mirrored);
906}
907
908EAPI Eina_Bool
909elm_object_mirrored_automatic_get(const Evas_Object *obj)
910{
911 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
912 return elm_widget_mirrored_automatic_get(obj);
913}
914
915EAPI void
916elm_object_mirrored_automatic_set(Evas_Object *obj, Eina_Bool automatic)
917{
918 EINA_SAFETY_ON_NULL_RETURN(obj);
919 elm_widget_mirrored_automatic_set(obj, automatic);
920}
921
922/**
923 * @}
924 */
925
926EAPI void
927elm_object_scale_set(Evas_Object *obj,
928 double scale)
929{
930 EINA_SAFETY_ON_NULL_RETURN(obj);
931 elm_widget_scale_set(obj, scale);
932}
933
934EAPI double
935elm_object_scale_get(const Evas_Object *obj)
936{
937 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, 0.0);
938 return elm_widget_scale_get(obj);
939}
940
941EAPI void
942elm_object_part_text_set(Evas_Object *obj, const char *part, const char *label)
943{
944 EINA_SAFETY_ON_NULL_RETURN(obj);
945 elm_widget_text_part_set(obj, part, label);
946}
947
948EAPI const char *
949elm_object_part_text_get(const Evas_Object *obj, const char *part)
950{
951 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
952 return elm_widget_text_part_get(obj, part);
953}
954
955EAPI void
956elm_object_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text)
957{
958 EINA_SAFETY_ON_NULL_RETURN(obj);
959 elm_widget_domain_translatable_text_part_set(obj, part, domain, text);
960}
961
962EAPI const char *
963elm_object_translatable_text_part_get(const Evas_Object *obj, const char *part)
964{
965 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
966 return elm_widget_translatable_text_part_get(obj, part);
967}
968
969EAPI void
970elm_object_part_content_set(Evas_Object *obj, const char *part, Evas_Object *content)
971{
972 EINA_SAFETY_ON_NULL_RETURN(obj);
973 elm_widget_content_part_set(obj, part, content);
974}
975
976EAPI Evas_Object *
977elm_object_part_content_get(const Evas_Object *obj, const char *part)
978{
979 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
980 return elm_widget_content_part_get(obj, part);
981}
982
983EAPI Evas_Object *
984elm_object_part_content_unset(Evas_Object *obj, const char *part)
985{
986 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
987 return elm_widget_content_part_unset(obj, part);
988}
989
990EAPI Eina_Bool
991elm_object_style_set(Evas_Object *obj,
992 const char *style)
993{
994 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
995 return elm_widget_style_set(obj, style);
996}
997
998EAPI const char *
999elm_object_style_get(const Evas_Object *obj)
1000{
1001 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1002 return elm_widget_style_get(obj);
1003}
1004
1005EAPI void
1006elm_object_disabled_set(Evas_Object *obj,
1007 Eina_Bool disabled)
1008{
1009 EINA_SAFETY_ON_NULL_RETURN(obj);
1010 elm_widget_disabled_set(obj, disabled);
1011}
1012
1013EAPI Eina_Bool
1014elm_object_disabled_get(const Evas_Object *obj)
1015{
1016 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1017 return elm_widget_disabled_get(obj);
1018}
1019
1020EAPI void
1021elm_cache_all_flush(void)
1022{
1023 const Eina_List *l;
1024 Evas_Object *obj;
1025
1026 edje_file_cache_flush();
1027 edje_collection_cache_flush();
1028 eet_clearcache();
1029 EINA_LIST_FOREACH(_elm_win_list, l, obj)
1030 {
1031 Evas *e = evas_object_evas_get(obj);
1032 evas_image_cache_flush(e);
1033 evas_font_cache_flush(e);
1034 evas_render_dump(e);
1035 }
1036}
1037
1038EAPI Eina_Bool
1039elm_object_focus_get(const Evas_Object *obj)
1040{
1041 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1042 return elm_widget_focus_get(obj);
1043}
1044
1045EAPI void
1046elm_object_focus_set(Evas_Object *obj,
1047 Eina_Bool focus)
1048{
1049 EINA_SAFETY_ON_NULL_RETURN(obj);
1050
1051 if (focus == elm_widget_focus_get(obj)) return;
1052
1053 if (focus)
1054 elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
1055 else
1056 elm_widget_focused_object_clear(obj);
1057}
1058
1059EAPI void
1060elm_object_focus_allow_set(Evas_Object *obj,
1061 Eina_Bool enable)
1062{
1063 EINA_SAFETY_ON_NULL_RETURN(obj);
1064 elm_widget_can_focus_set(obj, enable);
1065/*FIXME: According to the elm_object_focus_allow_get(), child_can_focus field
1066of the parent should be updated. Otherwise, the checking of it's child focus allow states should not be in elm_object_focus_allow_get() */
1067}
1068
1069EAPI Eina_Bool
1070elm_object_focus_allow_get(const Evas_Object *obj)
1071{
1072 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1073 return (elm_widget_can_focus_get(obj)) || (elm_widget_child_can_focus_get(obj));
1074}
1075
1076EAPI void
1077elm_object_focus_custom_chain_set(Evas_Object *obj,
1078 Eina_List *objs)
1079{
1080 EINA_SAFETY_ON_NULL_RETURN(obj);
1081 elm_widget_focus_custom_chain_set(obj, objs);
1082}
1083
1084EAPI void
1085elm_object_focus_custom_chain_unset(Evas_Object *obj)
1086{
1087 EINA_SAFETY_ON_NULL_RETURN(obj);
1088 elm_widget_focus_custom_chain_unset(obj);
1089}
1090
1091EAPI const Eina_List *
1092elm_object_focus_custom_chain_get(const Evas_Object *obj)
1093{
1094 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1095 return elm_widget_focus_custom_chain_get(obj);
1096}
1097
1098EAPI void
1099elm_object_focus_custom_chain_append(Evas_Object *obj,
1100 Evas_Object *child,
1101 Evas_Object *relative_child)
1102{
1103 EINA_SAFETY_ON_NULL_RETURN(obj);
1104 elm_widget_focus_custom_chain_append(obj, child, relative_child);
1105}
1106
1107EAPI void
1108elm_object_focus_custom_chain_prepend(Evas_Object *obj,
1109 Evas_Object *child,
1110 Evas_Object *relative_child)
1111{
1112 EINA_SAFETY_ON_NULL_RETURN(obj);
1113 elm_widget_focus_custom_chain_prepend(obj, child, relative_child);
1114}
1115
1116EINA_DEPRECATED EAPI void
1117elm_object_focus_cycle(Evas_Object *obj,
1118 Elm_Focus_Direction dir)
1119{
1120 elm_object_focus_next(obj, dir);
1121}
1122
1123EAPI void
1124elm_object_focus_next(Evas_Object *obj,
1125 Elm_Focus_Direction dir)
1126{
1127 EINA_SAFETY_ON_NULL_RETURN(obj);
1128 elm_widget_focus_cycle(obj, dir);
1129}
1130
1131EAPI void
1132elm_object_tree_focus_allow_set(Evas_Object *obj,
1133 Eina_Bool tree_focusable)
1134{
1135 EINA_SAFETY_ON_NULL_RETURN(obj);
1136 elm_widget_tree_unfocusable_set(obj, !tree_focusable);
1137}
1138
1139EAPI Eina_Bool
1140elm_object_tree_focus_allow_get(const Evas_Object *obj)
1141{
1142 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1143 return !elm_widget_tree_unfocusable_get(obj);
1144}
1145
1146EAPI void
1147elm_object_scroll_hold_push(Evas_Object *obj)
1148{
1149 EINA_SAFETY_ON_NULL_RETURN(obj);
1150 elm_widget_scroll_hold_push(obj);
1151}
1152
1153EAPI void
1154elm_object_scroll_hold_pop(Evas_Object *obj)
1155{
1156 EINA_SAFETY_ON_NULL_RETURN(obj);
1157 elm_widget_scroll_hold_pop(obj);
1158}
1159
1160EAPI void
1161elm_object_scroll_freeze_push(Evas_Object *obj)
1162{
1163 EINA_SAFETY_ON_NULL_RETURN(obj);
1164 elm_widget_scroll_freeze_push(obj);
1165}
1166
1167EAPI void
1168elm_object_scroll_lock_x_set(Evas_Object *obj,
1169 Eina_Bool lock)
1170{
1171 EINA_SAFETY_ON_NULL_RETURN(obj);
1172 elm_widget_drag_lock_x_set(obj, lock);
1173}
1174
1175EAPI void
1176elm_object_scroll_lock_y_set(Evas_Object *obj,
1177 Eina_Bool lock)
1178{
1179 EINA_SAFETY_ON_NULL_RETURN(obj);
1180 elm_widget_drag_lock_y_set(obj, lock);
1181}
1182
1183EAPI Eina_Bool
1184elm_object_scroll_lock_x_get(const Evas_Object *obj)
1185{
1186 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1187 return elm_widget_drag_lock_x_get(obj);
1188}
1189
1190EAPI Eina_Bool
1191elm_object_scroll_lock_y_get(const Evas_Object *obj)
1192{
1193 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1194 return elm_widget_drag_lock_y_get(obj);
1195}
1196
1197EAPI void
1198elm_object_scroll_freeze_pop(Evas_Object *obj)
1199{
1200 EINA_SAFETY_ON_NULL_RETURN(obj);
1201 elm_widget_scroll_freeze_pop(obj);
1202}
1203
1204EAPI Eina_Bool
1205elm_object_widget_check(const Evas_Object *obj)
1206{
1207 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, EINA_FALSE);
1208 return elm_widget_is(obj);
1209}
1210
1211EAPI Evas_Object *
1212elm_object_parent_widget_get(const Evas_Object *obj)
1213{
1214 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1215 return elm_widget_parent_widget_get(obj);
1216}
1217
1218EAPI Evas_Object *
1219elm_object_top_widget_get(const Evas_Object *obj)
1220{
1221 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1222 return elm_widget_top_get(obj);
1223}
1224
1225EAPI const char *
1226elm_object_widget_type_get(const Evas_Object *obj)
1227{
1228 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1229 return elm_widget_type_get(obj);
1230}
1231
1232EAPI void
1233elm_object_signal_emit(Evas_Object *obj,
1234 const char *emission,
1235 const char *source)
1236{
1237 EINA_SAFETY_ON_NULL_RETURN(obj);
1238 elm_widget_signal_emit(obj, emission, source);
1239}
1240
1241EAPI void
1242elm_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data)
1243{
1244 EINA_SAFETY_ON_NULL_RETURN(obj);
1245 EINA_SAFETY_ON_NULL_RETURN(func);
1246 elm_widget_signal_callback_add(obj, emission, source, func, data);
1247}
1248
1249EAPI void *
1250elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func)
1251{
1252 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1253 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1254 return elm_widget_signal_callback_del(obj, emission, source, func);
1255}
1256
1257EAPI void
1258elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data)
1259{
1260 EINA_SAFETY_ON_NULL_RETURN(obj);
1261 EINA_SAFETY_ON_NULL_RETURN(func);
1262 elm_widget_event_callback_add(obj, func, data);
1263}
1264
1265EAPI void *
1266elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data)
1267{
1268 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
1269 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1270 return elm_widget_event_callback_del(obj, func, data);
1271}
1272
1273EAPI void
1274elm_object_tree_dump(const Evas_Object *top)
1275{
1276#ifdef ELM_DEBUG
1277 elm_widget_tree_dump(top);
1278#else
1279 return;
1280 (void)top;
1281#endif
1282}
1283
1284EAPI void
1285elm_object_tree_dot_dump(const Evas_Object *top,
1286 const char *file)
1287{
1288#ifdef ELM_DEBUG
1289 FILE *f = fopen(file, "wb");
1290 elm_widget_tree_dot_dump(top, f);
1291 fclose(f);
1292#else
1293 return;
1294 (void)top;
1295 (void)file;
1296#endif
1297}
1298
1299EAPI void
1300elm_coords_finger_size_adjust(int times_w,
1301 Evas_Coord *w,
1302 int times_h,
1303 Evas_Coord *h)
1304{
1305 if ((w) && (*w < (_elm_config->finger_size * times_w)))
1306 *w = _elm_config->finger_size * times_w;
1307 if ((h) && (*h < (_elm_config->finger_size * times_h)))
1308 *h = _elm_config->finger_size * times_h;
1309}
1310
1311EAPI Evas_Object *
1312elm_object_item_widget_get(const Elm_Object_Item *it)
1313{
1314 return WIDGET(it);
1315}
1316
1317EAPI void
1318elm_object_item_part_content_set(Elm_Object_Item *it,
1319 const char *part,
1320 Evas_Object *content)
1321{
1322 _elm_widget_item_part_content_set((Elm_Widget_Item *)it, part, content);
1323}
1324
1325EAPI Evas_Object *
1326elm_object_item_part_content_get(const Elm_Object_Item *it,
1327 const char *part)
1328{
1329 return _elm_widget_item_part_content_get((Elm_Widget_Item *)it, part);
1330}
1331
1332EAPI Evas_Object *
1333elm_object_item_part_content_unset(Elm_Object_Item *it, const char *part)
1334{
1335 return _elm_widget_item_part_content_unset((Elm_Widget_Item *)it, part);
1336}
1337
1338EAPI void
1339elm_object_item_part_text_set(Elm_Object_Item *it,
1340 const char *part,
1341 const char *label)
1342{
1343 _elm_widget_item_part_text_set((Elm_Widget_Item *)it, part, label);
1344}
1345
1346EAPI const char *
1347elm_object_item_part_text_get(const Elm_Object_Item *it, const char *part)
1348{
1349 return _elm_widget_item_part_text_get((Elm_Widget_Item *)it, part);
1350}
1351
1352EAPI void
1353elm_object_access_info_set(Evas_Object *obj, const char *txt)
1354{
1355 elm_widget_access_info_set(obj, txt);
1356}
1357
1358EAPI Evas_Object *
1359elm_object_name_find(const Evas_Object *obj, const char *name, int recurse)
1360{
1361 return elm_widget_name_find(obj, name, recurse);
1362}
1363
1364EAPI void
1365elm_object_item_access_info_set(Elm_Object_Item *it, const char *txt)
1366{
1367 _elm_widget_item_access_info_set((Elm_Widget_Item *)it, txt);
1368}
1369
1370EAPI void *
1371elm_object_item_data_get(const Elm_Object_Item *it)
1372{
1373 return elm_widget_item_data_get(it);
1374}
1375
1376EAPI void
1377elm_object_item_data_set(Elm_Object_Item *it, void *data)
1378{
1379 elm_widget_item_data_set(it, data);
1380}
1381
1382EAPI void
1383elm_object_item_signal_emit(Elm_Object_Item *it, const char *emission, const char *source)
1384{
1385 _elm_widget_item_signal_emit((Elm_Widget_Item *)it, emission, source);
1386}
1387
1388EAPI void elm_object_item_disabled_set(Elm_Object_Item *it, Eina_Bool disabled)
1389{
1390 _elm_widget_item_disabled_set((Elm_Widget_Item *)it, disabled);
1391}
1392
1393EAPI Eina_Bool elm_object_item_disabled_get(const Elm_Object_Item *it)
1394{
1395 return _elm_widget_item_disabled_get((Elm_Widget_Item *)it);
1396}
1397
1398EAPI void elm_object_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb del_cb)
1399{
1400 _elm_widget_item_del_cb_set((Elm_Widget_Item *)it, del_cb);
1401}
1402
1403EAPI void elm_object_item_del(Elm_Object_Item *it)
1404{
1405 _elm_widget_item_del((Elm_Widget_Item *)it);
1406}
1407
1408EAPI void
1409elm_object_item_tooltip_text_set(Elm_Object_Item *it, const char *text)
1410{
1411 elm_widget_item_tooltip_text_set(it, text);
1412}
1413
1414EAPI void
1415elm_object_item_tooltip_content_cb_set(Elm_Object_Item *it, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
1416{
1417 elm_widget_item_tooltip_content_cb_set(it, func, data, del_cb);
1418}
1419
1420EAPI void
1421elm_object_item_tooltip_unset(Elm_Object_Item *it)
1422{
1423 elm_widget_item_tooltip_unset(it);
1424}
1425
1426EAPI Eina_Bool
1427elm_object_item_tooltip_window_mode_set(Elm_Object_Item *it, Eina_Bool disable)
1428{
1429 return elm_widget_item_tooltip_window_mode_set(it, disable);
1430}
1431
1432EAPI Eina_Bool
1433elm_object_item_tooltip_window_mode_get(const Elm_Object_Item *it)
1434{
1435 return elm_widget_item_tooltip_window_mode_get(it);
1436}
1437
1438EAPI void
1439elm_object_item_tooltip_style_set(Elm_Object_Item *it, const char *style)
1440{
1441 elm_widget_item_tooltip_style_set(it, style);
1442}
1443
1444EAPI const char *
1445elm_object_item_tooltip_style_get(const Elm_Object_Item *it)
1446{
1447 return elm_widget_item_tooltip_style_get(it);
1448}
1449
1450EAPI void
1451elm_object_item_cursor_set(Elm_Object_Item *it, const char *cursor)
1452{
1453 elm_widget_item_cursor_set(it, cursor);
1454}
1455
1456EAPI const char *
1457elm_object_item_cursor_get(const Elm_Object_Item *it)
1458{
1459 return elm_widget_item_cursor_get(it);
1460}
1461
1462EAPI void
1463elm_object_item_cursor_unset(Elm_Object_Item *it)
1464{
1465 elm_widget_item_cursor_unset(it);
1466}
1467
1468EAPI void
1469elm_object_item_cursor_style_set(Elm_Object_Item *it, const char *style)
1470{
1471 elm_widget_item_cursor_style_set(it, style);
1472}
1473
1474EAPI const char *
1475elm_object_item_cursor_style_get(const Elm_Object_Item *it)
1476{
1477 return elm_widget_item_cursor_style_get(it);
1478}
1479
1480EAPI void
1481elm_object_item_cursor_engine_only_set(Elm_Object_Item *it, Eina_Bool engine_only)
1482{
1483 elm_widget_item_cursor_engine_only_set(it, engine_only);
1484}
1485
1486EAPI Eina_Bool
1487elm_object_item_cursor_engine_only_get(const Elm_Object_Item *it)
1488{
1489 return elm_widget_item_cursor_engine_only_get(it);
1490}
diff --git a/libraries/elementary/src/lib/elm_map.c b/libraries/elementary/src/lib/elm_map.c
new file mode 100644
index 0000000..54b7292
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_map.c
@@ -0,0 +1,5669 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4
5#include "Elementary.h"
6#include "elm_priv.h"
7#include "els_scroller.h"
8
9#define OVERLAY_CLASS_ZOOM_MAX 255
10
11#ifdef HAVE_ELEMENTARY_ECORE_CON
12
13typedef struct _Widget_Data Widget_Data;
14typedef struct _Path Path;
15typedef struct _Color Color;
16typedef struct _Region Region;
17typedef struct _Pan Pan;
18typedef struct _Grid Grid;
19typedef struct _Grid_Item Grid_Item;
20typedef struct _Overlay_Default Overlay_Default;
21typedef struct _Overlay_Class Overlay_Class;
22typedef struct _Overlay_Group Overlay_Group;
23typedef struct _Overlay_Bubble Overlay_Bubble;
24typedef struct _Overlay_Route Overlay_Route;
25typedef struct _Overlay_Line Overlay_Line;
26typedef struct _Overlay_Polygon Overlay_Polygon;
27typedef struct _Overlay_Circle Overlay_Circle;
28typedef struct _Overlay_Scale Overlay_Scale;
29typedef struct _Path_Node Path_Node;
30typedef struct _Path_Waypoint Path_Waypoint;
31typedef struct _Route_Dump Route_Dump;
32typedef struct _Name_Dump Name_Dump;
33typedef struct _Delayed_Data Delayed_Data;
34typedef struct _Source_Tile Source_Tile;
35typedef struct _Source_Route Source_Route;
36typedef struct _Source_Name Source_Name;
37
38typedef char *(*Elm_Map_Module_Source_Name_Func)(void);
39typedef int (*Elm_Map_Module_Tile_Zoom_Min_Func)(void);
40typedef int (*Elm_Map_Module_Tile_Zoom_Max_Func)(void);
41typedef char *(*Elm_Map_Module_Tile_Url_Func)(const Evas_Object *obj, int x, int y, int zoom);
42typedef Eina_Bool (*Elm_Map_Module_Tile_Geo_to_Coord_Func)(const Evas_Object *obj, int zoom, double lon, double lat, int size, int *x, int *y);
43typedef Eina_Bool (*Elm_Map_Module_Tile_Coord_to_Geo_Func)(const Evas_Object *obj, int zoom, int x, int y, int size, double *lon, double *lat);
44typedef double (*Elm_Map_Module_Tile_Scale_Func)(const Evas_Object *obj, double lon, double lat, int zoom);
45typedef char *(*Elm_Map_Module_Route_Url_Func)(const Evas_Object *obj, const char *type_name, int method, double flon, double flat, double tlon, double tlat);
46typedef char *(*Elm_Map_Module_Name_Url_Func)(const Evas_Object *obj, int method, const char *name, double lon, double lat);
47
48#define ROUND(z) (((z) < 0) ? (int)ceil((z) - 0.005) : (int)floor((z) + 0.005))
49#define EVAS_MAP_POINT 4
50#define DEFAULT_TILE_SIZE 256
51#define MAX_CONCURRENT_DOWNLOAD 10
52#define MARER_MAX_NUMBER 30
53#define OVERLAY_GROUPING_SCALE 2
54
55#define CACHE_ROOT "/tmp/elm_map"
56#define CACHE_TILE_ROOT CACHE_ROOT"/%d/%d/%d"
57#define CACHE_TILE_PATH "%s/%d.png"
58#define CACHE_ROUTE_ROOT CACHE_ROOT"/route"
59#define CACHE_NAME_ROOT CACHE_ROOT"/name"
60
61#define ROUTE_YOURS_URL "http://www.yournavigation.org/api/dev/route.php"
62#define ROUTE_TYPE_MOTORCAR "motocar"
63#define ROUTE_TYPE_BICYCLE "bicycle"
64#define ROUTE_TYPE_FOOT "foot"
65#define YOURS_DISTANCE "distance"
66#define YOURS_DESCRIPTION "description"
67#define YOURS_COORDINATES "coordinates"
68
69#define NAME_NOMINATIM_URL "http://nominatim.openstreetmap.org"
70#define NOMINATIM_RESULT "result"
71#define NOMINATIM_PLACE "place"
72#define NOMINATIM_ATTR_LON "lon"
73#define NOMINATIM_ATTR_LAT "lat"
74
75enum _Route_Xml_Attribute
76{
77 ROUTE_XML_NONE,
78 ROUTE_XML_DISTANCE,
79 ROUTE_XML_DESCRIPTION,
80 ROUTE_XML_COORDINATES,
81 ROUTE_XML_LAST
82} Route_Xml_Attibute;
83
84enum _Name_Xml_Attribute
85{
86 NAME_XML_NONE,
87 NAME_XML_NAME,
88 NAME_XML_LON,
89 NAME_XML_LAT,
90 NAME_XML_LAST
91} Name_Xml_Attibute;
92
93enum _Track_Xml_Attribute
94{
95 TRACK_XML_NONE,
96 TRACK_XML_COORDINATES,
97 TRACK_XML_LAST
98} Track_Xml_Attibute;
99
100struct _Path
101{
102 Evas_Coord x, y;
103};
104
105struct _Region
106{
107 double lon, lat;
108};
109
110struct _Delayed_Data
111{
112 void (*func)(void *data);
113 Widget_Data *wd;
114 Elm_Map_Zoom_Mode mode;
115 int zoom;
116 double lon, lat;
117 Eina_List *overlays;
118};
119
120// FIXME: Currently tile size must be 256*256
121// and the map size is pow(2.0, z) * (tile size)
122struct _Source_Tile
123{
124 const char *name;
125 int zoom_min;
126 int zoom_max;
127 Elm_Map_Module_Tile_Url_Func url_cb;
128 Elm_Map_Module_Tile_Geo_to_Coord_Func geo_to_coord;
129 Elm_Map_Module_Tile_Coord_to_Geo_Func coord_to_geo;
130 Elm_Map_Module_Tile_Scale_Func scale_cb;
131};
132
133struct _Source_Route
134{
135 const char *name;
136 Elm_Map_Module_Route_Url_Func url_cb;
137};
138
139struct _Source_Name
140{
141 const char *name;
142 Elm_Map_Module_Name_Url_Func url_cb;
143};
144
145struct _Color
146{
147 int r, g, b, a;
148};
149
150struct _Overlay_Group
151{
152 Widget_Data *wd;
153 Elm_Map_Overlay *overlay; // virtual group type overlay
154 Elm_Map_Overlay *clas; // class overlay for this virtual group
155 Overlay_Default *ovl; // rendered overlay
156 Eina_List *members;
157 Eina_Bool in : 1;
158 Eina_Bool boss : 1;
159};
160
161struct _Overlay_Default
162{
163 Widget_Data *wd;
164 Evas_Coord w, h;
165
166 double lon, lat;
167 Evas_Coord x, y;
168
169 // Display priority is content > icon > clas_obj > clas_icon > layout
170 Evas_Object *content;
171 Evas_Object *icon;
172
173 Color c;
174 // if clas_content or icon exists, do not inherit from class
175 Evas_Object *clas_content; // Duplicated from class content
176 Evas_Object *clas_icon; // Duplicated from class icon
177 Evas_Object *layout;
178};
179
180struct _Overlay_Class
181{
182 Widget_Data *wd;
183 Eina_List *members;
184 int zoom_max;
185 Evas_Object *content;
186 Evas_Object *icon;
187};
188
189struct _Overlay_Bubble
190{
191 Widget_Data *wd;
192 Evas_Object *pobj;
193 Evas_Object *obj, *sc, *bx;
194 double lon, lat;
195 Evas_Coord x, y, w, h;
196};
197
198struct _Overlay_Route
199{
200 Widget_Data *wd;
201
202 Evas_Object *obj;
203 Eina_List *paths;
204 Eina_List *nodes;
205};
206
207struct _Overlay_Line
208{
209 Widget_Data *wd;
210 double flon, flat, tlon, tlat;
211 Evas_Object *obj;
212};
213
214struct _Overlay_Polygon
215{
216 Widget_Data *wd;
217 Eina_List *regions; // list of Regions
218 Evas_Object *obj;
219};
220
221struct _Overlay_Circle
222{
223 Widget_Data *wd;
224 double lon, lat;
225 double radius; // Intial pixel in intial view
226 double ratio; // initial-radius/map-size
227 Evas_Object *obj;
228};
229
230struct _Overlay_Scale
231{
232 Widget_Data *wd;
233 Evas_Coord x, y;
234 Evas_Coord w, h;
235 Evas_Object *obj;
236 };
237
238struct _Elm_Map_Overlay
239{
240 Widget_Data *wd;
241
242 Eina_Bool paused : 1;
243 Eina_Bool hide : 1;
244 Evas_Coord zoom_min;
245 Color c;
246 void *data; // user set data
247
248 Elm_Map_Overlay_Type type;
249 void *ovl; // Overlay Data for each type
250
251 Elm_Map_Overlay_Get_Cb cb;
252 void *cb_data;
253
254 // These are not used if overlay type is class or group
255 Overlay_Group *grp;
256};
257
258struct _Elm_Map_Route
259{
260 Widget_Data *wd;
261
262 char *fname;
263 Elm_Map_Route_Type type;
264 Elm_Map_Route_Method method;
265 double flon, flat, tlon, tlat;
266 Elm_Map_Route_Cb cb;
267 void *data;
268 Ecore_File_Download_Job *job;
269
270
271 Eina_List *nodes;
272 Eina_List *waypoint;
273 struct
274 {
275 int node_count;
276 int waypoint_count;
277 const char *nodes;
278 const char *waypoints;
279 double distance; /* unit : km */
280 } info;
281
282 Path_Node *n;
283 Path_Waypoint *w;
284};
285
286struct _Path_Node
287{
288 Widget_Data *wd;
289
290 int idx;
291 struct
292 {
293 double lon, lat;
294 char *address;
295 } pos;
296};
297
298struct _Path_Waypoint
299{
300 Widget_Data *wd;
301
302 const char *point;
303};
304
305struct _Elm_Map_Name
306{
307 Widget_Data *wd;
308
309 int method;
310 char *address;
311 double lon, lat;
312
313 char *fname;
314 Ecore_File_Download_Job *job;
315 Elm_Map_Name_Cb cb;
316 void *data;
317};
318
319struct _Route_Dump
320{
321 int id;
322 char *fname;
323 double distance;
324 char *description;
325 char *coordinates;
326};
327
328struct _Name_Dump
329{
330 int id;
331 char *address;
332 double lon;
333 double lat;
334};
335
336struct _Grid_Item
337{
338 Grid *g;
339
340 Widget_Data *wd;
341 Evas_Object *img;
342 const char *file;
343 const char *url;
344 int x, y; // Tile coordinate
345 Eina_Bool file_have : 1;
346
347 Ecore_File_Download_Job *job;
348};
349
350struct _Grid
351{
352 Widget_Data *wd;
353 int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
354 int tw, th; // size of grid in tiles
355 Eina_Matrixsparse *grid;
356};
357
358struct _Pan
359{
360 Evas_Object_Smart_Clipped_Data __clipped_data;
361 Widget_Data *wd;
362};
363
364struct _Widget_Data
365{
366 Evas_Object *obj;
367 Evas_Object *scr;
368 Evas_Object *ges;
369 Evas_Object *pan_smart;
370 Evas_Object *sep_maps_overlays; // Tiles are below this and overlays are on top
371 Evas_Map *map;
372
373 Eina_Array *src_tile_mods;
374 Source_Tile *src_tile;
375 Eina_List *src_tiles;
376 const char **src_tile_names;
377
378 Eina_Array *src_route_mods;
379 Source_Route *src_route;
380 Eina_List *src_routes;
381 const char **src_route_names;
382
383 Eina_Array *src_name_mods;
384 Source_Name *src_name;
385 Eina_List *src_names;
386 const char **src_name_names;
387
388 int zoom_min, zoom_max;
389 int tsize;
390
391 int id;
392 Eina_List *grids;
393
394 int zoom;
395 double zoom_detail;
396 struct
397 {
398 int w, h; // Current pixel width, heigth of a grid
399 int tile; // Current pixel size of a grid item
400 } size;
401 Elm_Map_Zoom_Mode mode;
402 struct
403 {
404 double zoom;
405 double diff;
406 int cnt;
407 } ani;
408 Ecore_Timer *zoom_timer;
409 Ecore_Animator *zoom_animator;
410
411 int try_num;
412 int finish_num;
413 int download_num;
414 Eina_List *download_list;
415 Ecore_Idler *download_idler;
416 Eina_Hash *ua;
417 const char *user_agent;
418
419 Evas_Coord pan_x, pan_y;
420 Eina_List *delayed_jobs;
421
422 Ecore_Timer *scr_timer;
423 Ecore_Timer *long_timer;
424 Evas_Event_Mouse_Down ev;
425 Eina_Bool on_hold : 1;
426 Eina_Bool paused : 1;
427
428 double pinch_zoom;
429 struct
430 {
431 Evas_Coord cx, cy;
432 double a, d;
433 } rotate;
434
435 Eina_Bool wheel_disabled : 1;
436
437 Eina_List *routes;
438 Eina_List *track;
439 Eina_List *names;
440
441 Eina_List *overlays;
442};
443
444static char *_mapnik_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom);
445static char *_osmarender_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom);
446static char *_cyclemap_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom);
447static char *_mapquest_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom);
448static char *_mapquest_aerial_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom);
449static char *_yours_url_cb(const Evas_Object *obj __UNUSED__, const char *type_name, int method, double flon, double flat, double tlon, double tlat);
450static char *_nominatim_url_cb(const Evas_Object *obj, int method, const char *name, double lon, double lat);
451/*
452static char *_monav_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
453static char *_ors_url_cb(Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat);
454*/
455static double _scale_cb(const Evas_Object *obj __UNUSED__, double lon __UNUSED__, double lat, int zoom);
456
457const Source_Tile src_tiles[] =
458{
459 {"Mapnik", 0, 18, _mapnik_url_cb, NULL, NULL, _scale_cb},
460 {"Osmarender", 0, 17, _osmarender_url_cb, NULL, NULL, _scale_cb},
461 {"CycleMap", 0, 16, _cyclemap_url_cb, NULL, NULL, _scale_cb},
462 {"MapQuest", 0, 18, _mapquest_url_cb, NULL, NULL, _scale_cb},
463 {"MapQuest Open Aerial", 0, 11, _mapquest_aerial_url_cb, NULL, NULL, _scale_cb}
464};
465
466// FIXME: Fix more open sources
467const Source_Route src_routes[] =
468{
469 {"Yours", _yours_url_cb} // http://www.yournavigation.org/
470 //{"Monav", _monav_url_cb},
471 //{"ORS", _ors_url_cb}, // http://www.openrouteservice.org
472};
473
474// Refer : http://wiki.openstreetmap.org/wiki/FAQ
475// meters per pixel when latitude is 0 (equator)
476// meters per pixel = _osm_scale_meter[zoom] * cos (latitude)
477const double _osm_scale_meter[] =
478{78206, 39135.758482, 19567.879241, 9783.939621, 4891.969810,
479 2445.984905, 1222.992453, 611.496226, 305.748113, 152.874057, 76.437028,
480 38.218514, 19.109257, 9.554629, 4.777314, 2.388657, 1.194329, 0.597164,
481 0.29858};
482
483// Scale in meters
484const double _scale_tb[] =
485{10000000, 5000000, 2000000, 1000000, 500000, 200000, 100000, 50000,
486 20000, 10000, 5000, 2000, 1000, 500, 500, 200, 100, 50, 20, 10, 5, 2, 1};
487
488// FIXME: Add more open sources
489const Source_Name src_names[] =
490{
491 {"Nominatim", _nominatim_url_cb}
492};
493
494static const char *widtype = NULL;
495static Evas_Smart_Class parent_sc = EVAS_SMART_CLASS_INIT_NULL;
496static Evas_Smart_Class sc;
497static Evas_Smart *smart;
498static int idnum = 1;
499
500static const char SIG_CLICKED[] = "clicked";
501static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
502static const char SIG_PRESS[] = "press";
503static const char SIG_LONGPRESSED[] = "longpressed";
504static const char SIG_SCROLL[] = "scroll";
505static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
506static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
507static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
508static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
509static const char SIG_ZOOM_START[] = "zoom,start";
510static const char SIG_ZOOM_STOP[] = "zoom,stop";
511static const char SIG_ZOOM_CHANGE[] = "zoom,change";
512static const char SIG_TILE_LOAD[] = "tile,load";
513static const char SIG_TILE_LOADED[] = "tile,loaded";
514static const char SIG_TILE_LOADED_FAIL[] = "tile,loaded,fail";
515static const char SIG_ROUTE_LOAD[] = "route,load";
516static const char SIG_ROUTE_LOADED[] = "route,loaded";
517static const char SIG_ROUTE_LOADED_FAIL[] = "route,loaded,fail";
518static const char SIG_NAME_LOAD[] = "name,load";
519static const char SIG_NAME_LOADED[] = "name,loaded";
520static const char SIG_NAME_LOADED_FAIL[] = "name,loaded,fail";
521static const char SIG_OVERLAY_CLICKED[] = "overlay,clicked";
522static const Evas_Smart_Cb_Description _signals[] = {
523 {SIG_CLICKED, ""},
524 {SIG_CLICKED_DOUBLE, ""},
525 {SIG_PRESS, ""},
526 {SIG_LONGPRESSED, ""},
527 {SIG_SCROLL, ""},
528 {SIG_SCROLL_DRAG_START, ""},
529 {SIG_SCROLL_DRAG_STOP, ""},
530 {SIG_SCROLL_ANIM_START, ""},
531 {SIG_SCROLL_ANIM_STOP, ""},
532 {SIG_ZOOM_START, ""},
533 {SIG_ZOOM_STOP, ""},
534 {SIG_ZOOM_CHANGE, ""},
535 {SIG_TILE_LOAD, ""},
536 {SIG_TILE_LOADED, ""},
537 {SIG_TILE_LOADED_FAIL, ""},
538 {SIG_ROUTE_LOAD, ""},
539 {SIG_ROUTE_LOADED, ""},
540 {SIG_ROUTE_LOADED_FAIL, ""},
541 {SIG_NAME_LOAD, ""},
542 {SIG_NAME_LOADED, ""},
543 {SIG_NAME_LOADED_FAIL, ""},
544 {SIG_OVERLAY_CLICKED, ""},
545 {NULL, NULL}
546};
547
548static void
549_edj_overlay_size_get(Widget_Data *wd, Evas_Coord *w, Evas_Coord *h)
550{
551 EINA_SAFETY_ON_NULL_RETURN(wd);
552 EINA_SAFETY_ON_NULL_RETURN(w);
553 EINA_SAFETY_ON_NULL_RETURN(h);
554
555 Evas_Object *edj;
556 const char *s;
557
558 edj = edje_object_add(evas_object_evas_get(wd->obj));
559 _elm_theme_object_set(wd->obj, edj, "map/marker", "radio",
560 elm_widget_style_get(wd->obj));
561 s = edje_object_data_get(edj, "size_w");
562 if (s) *w = atoi(s);
563 else *w = 0;
564 s = edje_object_data_get(edj, "size_h");
565 if (s) *h = atoi(s);
566 else *h = 0;
567 evas_object_del(edj);
568}
569
570static void
571_rotate(Evas_Coord x, Evas_Coord y, Evas_Coord cx, Evas_Coord cy, double degree, Evas_Coord *xx, Evas_Coord *yy)
572{
573 double r = (degree * M_PI) / 180.0;
574 if (xx) *xx = ((x - cx) * cos(r)) + ((y - cy) * cos(r + M_PI_2)) + cx;
575 if (yy) *yy = ((x - cx) * sin(r)) + ((y - cy) * sin(r + M_PI_2)) + cy;
576}
577
578static void
579_obj_rotate(Widget_Data *wd, Evas_Object *obj)
580{
581 Evas_Coord w, h, ow, oh;
582 evas_map_util_points_populate_from_object(wd->map, obj);
583
584 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
585 evas_object_image_size_get(obj, &w, &h);
586 if ((w > ow) || (h > oh))
587 {
588 evas_map_point_image_uv_set(wd->map, 0, 0, 0);
589 evas_map_point_image_uv_set(wd->map, 1, w, 0);
590 evas_map_point_image_uv_set(wd->map, 2, w, h);
591 evas_map_point_image_uv_set(wd->map, 3, 0, h);
592 }
593 evas_map_util_rotate(wd->map, wd->rotate.d, wd->rotate.cx, wd->rotate.cy);
594
595 evas_object_map_set(obj, wd->map);
596 evas_object_map_enable_set(obj, EINA_TRUE);
597}
598
599static void
600_obj_place(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
601{
602 EINA_SAFETY_ON_NULL_RETURN(obj);
603
604 evas_object_move(obj, x, y);
605 evas_object_resize(obj, w, h);
606 evas_object_show(obj);
607}
608
609static void
610_coord_to_region_convert(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord size, double *lon, double *lat)
611{
612 EINA_SAFETY_ON_NULL_RETURN(wd);
613 int zoom = floor(log(size / wd->size.tile) / log(2));
614 if ((wd->src_tile) && (wd->src_tile->coord_to_geo))
615 {
616 if (wd->src_tile->coord_to_geo(wd->obj, zoom, x, y, size, lon, lat))
617 return;
618 }
619
620 if (lon) *lon = (x / (double)size * 360.0) - 180;
621 if (lat)
622 {
623 double n = ELM_PI - (2.0 * ELM_PI * y / size);
624 *lat = 180.0 / ELM_PI * atan(0.5 * (exp(n) - exp(-n)));
625 }
626}
627
628static void
629_region_to_coord_convert(Widget_Data *wd, double lon, double lat, Evas_Coord size, Evas_Coord *x, Evas_Coord *y)
630{
631 EINA_SAFETY_ON_NULL_RETURN(wd);
632
633 int zoom = floor(log(size / 256) / log(2));
634 if ((wd->src_tile) && (wd->src_tile->geo_to_coord))
635 {
636 if (wd->src_tile->geo_to_coord(wd->obj, zoom, lon, lat, size, x, y)) return;
637 }
638
639 if (x) *x = floor((lon + 180.0) / 360.0 * size);
640 if (y)
641 *y = floor((1.0 - log(tan(lat * ELM_PI / 180.0) + (1.0 / cos(lat * ELM_PI / 180.0)))
642 / ELM_PI) / 2.0 * size);
643}
644
645static void
646_viewport_coord_get(Widget_Data *wd, Evas_Coord *vx, Evas_Coord *vy, Evas_Coord *vw, Evas_Coord *vh)
647{
648 EINA_SAFETY_ON_NULL_RETURN(wd);
649
650 Evas_Coord x, y, w, h;
651 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
652 elm_smart_scroller_child_viewport_size_get(wd->scr, &w, &h);
653 if (w > wd->size.w) x -= ((w - wd->size.w) / 2);
654 if (h > wd->size.h) y -= ((h - wd->size.h) / 2);
655 if (vx) *vx = x;
656 if (vy) *vy = y;
657 if (vw) *vw = w;
658 if (vh) *vh = h;
659}
660
661// Map coordinates to canvas geometry without rotate
662static void
663_coord_to_canvas_no_rotate(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord *xx, Evas_Coord *yy)
664{
665 Evas_Coord vx, vy, sx, sy;
666 _viewport_coord_get(wd, &vx, &vy, NULL, NULL);
667 evas_object_geometry_get(wd->pan_smart, &sx, &sy, NULL, NULL);
668 if (xx) *xx = x - vx + sx;
669 if (yy) *yy = y - vy + sy;
670}
671
672// Map coordinates to canvas geometry
673static void
674_coord_to_canvas(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord *xx, Evas_Coord *yy)
675{
676 _coord_to_canvas_no_rotate(wd, x, y, &x, &y);
677 _rotate(x, y, wd->rotate.cx, wd->rotate.cy, wd->rotate.d, &x, &y);
678 if (xx) *xx = x;
679 if (yy) *yy = y;
680}
681
682// Canvas geometry to map coordinates
683static void
684_canvas_to_coord(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Evas_Coord *xx, Evas_Coord *yy)
685{
686 Evas_Coord vx, vy, sx, sy;
687 _viewport_coord_get(wd, &vx, &vy, NULL, NULL);
688 evas_object_geometry_get(wd->pan_smart, &sx, &sy, NULL, NULL);
689 _rotate(x - sx + vx, y - sy + vy, wd->rotate.cx - sx + vx,
690 wd->rotate.cy - sy + vy, -wd->rotate.d, &x, &y);
691 if (xx) *xx = x;
692 if (yy) *yy = y;
693}
694
695static void
696_region_show(void *data)
697{
698 EINA_SAFETY_ON_NULL_RETURN(data);
699 Delayed_Data *dd = data;
700 int x, y, w, h;
701
702 _region_to_coord_convert(dd->wd, dd->lon, dd->lat, dd->wd->size.w, &x, &y);
703 _viewport_coord_get(dd->wd, NULL, NULL, &w, &h);
704 x = x - (w / 2);
705 y = y - (h / 2);
706 elm_smart_scroller_child_region_show(dd->wd->scr, x, y, w, h);
707 evas_object_smart_changed(dd->wd->pan_smart);
708}
709
710static void
711_grid_item_coord_get(Grid_Item *gi, int *x, int *y, int *w, int *h)
712{
713 EINA_SAFETY_ON_NULL_RETURN(gi);
714
715 if (x) *x = gi->x * gi->wd->size.tile;
716 if (y) *y = gi->y * gi->wd->size.tile;
717 if (w) *w = gi->wd->size.tile;
718 if (h) *h = gi->wd->size.tile;
719}
720
721static Eina_Bool
722_grid_item_in_viewport(Grid_Item *gi)
723{
724 EINA_SAFETY_ON_NULL_RETURN_VAL(gi, EINA_FALSE);
725
726 Evas_Coord vx, vy, vw, vh;
727 Evas_Coord x, y, w, h;
728
729 _viewport_coord_get(gi->wd, &vx, &vy, &vw, &vh);
730 _grid_item_coord_get(gi, &x, &y, &w, &h);
731 return ELM_RECTS_INTERSECT(x, y, w, h, vx, vy, vw, vh);
732}
733
734static void
735_grid_item_update(Grid_Item *gi)
736{
737 evas_object_image_file_set(gi->img, gi->file, NULL);
738 if (!gi->wd->zoom_timer && !gi->wd->scr_timer)
739 evas_object_image_smooth_scale_set(gi->img, EINA_TRUE);
740 else evas_object_image_smooth_scale_set(gi->img, EINA_FALSE);
741
742 Evas_Load_Error err = evas_object_image_load_error_get(gi->img);
743 if (err != EVAS_LOAD_ERROR_NONE)
744 {
745 ERR("Image loading error (%s): %s", gi->file, evas_load_error_str(err));
746 ecore_file_remove(gi->file);
747 gi->file_have = EINA_FALSE;
748 }
749 else
750 {
751 Evas_Coord x, y, w, h;
752 _grid_item_coord_get(gi, &x, &y, &w, &h);
753 _coord_to_canvas_no_rotate(gi->wd, x, y, &x, &y);
754 _obj_place(gi->img, x, y, w, h);
755 _obj_rotate(gi->wd, gi->img);
756 gi->file_have = EINA_TRUE;
757 }
758}
759
760static void
761_grid_item_load(Grid_Item *gi)
762{
763 EINA_SAFETY_ON_NULL_RETURN(gi);
764 if (gi->file_have) _grid_item_update(gi);
765 else if (!gi->job)
766 {
767 gi->wd->download_list = eina_list_remove(gi->wd->download_list, gi);
768 gi->wd->download_list = eina_list_append(gi->wd->download_list, gi);
769 }
770}
771
772static void
773_grid_item_unload(Grid_Item *gi)
774{
775 EINA_SAFETY_ON_NULL_RETURN(gi);
776 if (gi->file_have)
777 {
778 evas_object_hide(gi->img);
779 evas_object_image_file_set(gi->img, NULL, NULL);
780 }
781 else if (gi->job)
782 {
783 ecore_file_download_abort(gi->job);
784 ecore_file_remove(gi->file);
785 gi->job = NULL;
786 gi->wd->try_num--;
787 }
788 else gi->wd->download_list = eina_list_remove(gi->wd->download_list, gi);
789
790}
791
792static Grid_Item *
793_grid_item_create(Grid *g, Evas_Coord x, Evas_Coord y)
794{
795 EINA_SAFETY_ON_NULL_RETURN_VAL(g, NULL);
796 char buf[PATH_MAX];
797 char buf2[PATH_MAX];
798 char *url;
799 Grid_Item *gi;
800
801 gi = ELM_NEW(Grid_Item);
802 gi->wd = g->wd;
803 gi->g = g;
804 gi->x = x;
805 gi->y = y;
806
807 gi->file_have = EINA_FALSE;
808 gi->job = NULL;
809
810 gi->img = evas_object_image_add(evas_object_evas_get(g->wd->obj));
811 evas_object_image_smooth_scale_set(gi->img, EINA_FALSE);
812 evas_object_image_scale_hint_set(gi->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
813 evas_object_image_filled_set(gi->img, EINA_TRUE);
814 evas_object_smart_member_add(gi->img, g->wd->pan_smart);
815 evas_object_pass_events_set(gi->img, EINA_TRUE);
816 evas_object_stack_below(gi->img, g->wd->sep_maps_overlays);
817
818 snprintf(buf, sizeof(buf), CACHE_TILE_ROOT, g->wd->id, g->zoom, x);
819 snprintf(buf2, sizeof(buf2), CACHE_TILE_PATH, buf, y);
820 if (!ecore_file_exists(buf)) ecore_file_mkpath(buf);
821
822 eina_stringshare_replace(&gi->file, buf2);
823 url = g->wd->src_tile->url_cb(g->wd->obj, x, y, g->zoom);
824 if ((!url) || (!strlen(url)))
825 {
826 eina_stringshare_replace(&gi->url, NULL);
827 ERR("Getting source url failed: %s", gi->file);
828 }
829 else eina_stringshare_replace(&gi->url, url);
830 if (url) free(url);
831 eina_matrixsparse_data_idx_set(g->grid, y, x, gi);
832 return gi;
833}
834
835static void
836_grid_item_free(Grid_Item *gi)
837{
838 EINA_SAFETY_ON_NULL_RETURN(gi);
839 _grid_item_unload(gi);
840 if (gi->g && gi->g->grid) eina_matrixsparse_data_idx_set(gi->g->grid,
841 gi->y, gi->x, NULL);
842 if (gi->url) eina_stringshare_del(gi->url);
843 if (gi->file) eina_stringshare_del(gi->file);
844 if (gi->img) evas_object_del(gi->img);
845 if (gi->file_have) ecore_file_remove(gi->file);
846 free(gi);
847}
848
849static void
850_downloaded_cb(void *data, const char *file __UNUSED__, int status)
851{
852 Grid_Item *gi = data;
853
854 if (status == 200)
855 {
856 DBG("Download success from %s to %s", gi->url, gi->file);
857 _grid_item_update(gi);
858 gi->wd->finish_num++;
859 evas_object_smart_callback_call(gi->wd->obj, SIG_TILE_LOADED, NULL);
860 }
861 else
862 {
863 WRN("Download failed from %s to %s (%d) ", gi->url, gi->file, status);
864 ecore_file_remove(gi->file);
865 gi->file_have = EINA_FALSE;
866 evas_object_smart_callback_call(gi->wd->obj, SIG_TILE_LOADED_FAIL, NULL);
867 }
868
869 gi->job = NULL;
870 gi->wd->download_num--;
871 if (!gi->wd->download_num)
872 edje_object_signal_emit(elm_smart_scroller_edje_object_get(gi->wd->scr),
873 "elm,state,busy,stop", "elm");
874}
875
876static Eina_Bool
877_download_job(void *data)
878{
879 EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
880 Widget_Data *wd = data;
881
882 Eina_List *l, *ll;
883 Grid_Item *gi;
884
885 if (!eina_list_count(wd->download_list))
886 {
887 wd->download_idler = NULL;
888 return ECORE_CALLBACK_CANCEL;
889 }
890
891 EINA_LIST_REVERSE_FOREACH_SAFE(wd->download_list, l, ll, gi)
892 {
893 if ((gi->g->zoom != wd->zoom) || !(_grid_item_in_viewport(gi)))
894 {
895 wd->download_list = eina_list_remove(wd->download_list, gi);
896 continue;
897 }
898 if (wd->download_num >= MAX_CONCURRENT_DOWNLOAD)
899 return ECORE_CALLBACK_RENEW;
900
901 Eina_Bool ret = ecore_file_download_full(gi->url, gi->file,
902 _downloaded_cb, NULL,
903 gi, &(gi->job), wd->ua);
904 if ((!ret) || (!gi->job))
905 ERR("Can't start to download from %s to %s", gi->url, gi->file);
906 else
907 {
908 wd->download_list = eina_list_remove(wd->download_list, gi);
909 wd->try_num++;
910 wd->download_num++;
911 evas_object_smart_callback_call(gi->wd->obj, SIG_TILE_LOAD,
912 NULL);
913 if (wd->download_num == 1)
914 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
915 "elm,state,busy,start", "elm");
916 }
917 }
918 return ECORE_CALLBACK_RENEW;
919}
920
921static void
922_grid_viewport_get(Grid *g, int *x, int *y, int *w, int *h)
923{
924 EINA_SAFETY_ON_NULL_RETURN(g);
925 int xx, yy, ww, hh;
926 Evas_Coord vx, vy, vw, vh;
927
928 _viewport_coord_get(g->wd, &vx, &vy, &vw, &vh);
929 if (vx < 0) vx = 0;
930 if (vy < 0) vy = 0;
931
932 xx = (vx / g->wd->size.tile) - 1;
933 if (xx < 0) xx = 0;
934
935 yy = (vy / g->wd->size.tile) - 1;
936 if (yy < 0) yy = 0;
937
938 ww = (vw / g->wd->size.tile) + 3;
939 if (xx + ww >= g->tw) ww = g->tw - xx;
940
941 hh = (vh / g->wd->size.tile) + 3;
942 if (yy + hh >= g->th) hh = g->th - yy;
943
944 if (x) *x = xx;
945 if (y) *y = yy;
946 if (w) *w = ww;
947 if (h) *h = hh;
948}
949
950static void
951_grid_unload(Grid *g)
952{
953 EINA_SAFETY_ON_NULL_RETURN(g);
954 Eina_Iterator *it;
955 Eina_Matrixsparse_Cell *cell;
956 Grid_Item *gi;
957
958 it = eina_matrixsparse_iterator_new(g->grid);
959 EINA_ITERATOR_FOREACH(it, cell)
960 {
961 gi = eina_matrixsparse_cell_data_get(cell);
962 _grid_item_unload(gi);
963 }
964 eina_iterator_free(it);
965}
966
967static void
968_grid_load(Grid *g)
969{
970 EINA_SAFETY_ON_NULL_RETURN(g);
971 int x, y, xx, yy, ww, hh;
972 Eina_Iterator *it;
973 Eina_Matrixsparse_Cell *cell;
974 Grid_Item *gi;
975
976 it = eina_matrixsparse_iterator_new(g->grid);
977 EINA_ITERATOR_FOREACH(it, cell)
978 {
979 gi = eina_matrixsparse_cell_data_get(cell);
980 if (!_grid_item_in_viewport(gi)) _grid_item_unload(gi);
981 }
982 eina_iterator_free(it);
983
984 _grid_viewport_get(g, &xx, &yy, &ww, &hh);
985 for (y = yy; y < yy + hh; y++)
986 {
987 for (x = xx; x < xx + ww; x++)
988 {
989 gi = eina_matrixsparse_data_idx_get(g->grid, y, x);
990 if (!gi) gi = _grid_item_create(g, x, y);
991 _grid_item_load(gi);
992 }
993 }
994}
995
996static void
997_grid_place(Widget_Data *wd)
998{
999 EINA_SAFETY_ON_NULL_RETURN(wd);
1000 Eina_List *l;
1001 Grid *g;
1002
1003 EINA_LIST_FOREACH(wd->grids, l, g)
1004 {
1005 if (wd->zoom == g->zoom) _grid_load(g);
1006 else _grid_unload(g);
1007 }
1008 if (!wd->download_idler) wd->download_idler = ecore_idler_add(_download_job, wd);
1009}
1010
1011static void
1012_grid_all_create(Widget_Data *wd)
1013{
1014 EINA_SAFETY_ON_NULL_RETURN(wd);
1015 EINA_SAFETY_ON_NULL_RETURN(wd->src_tile);
1016
1017 int zoom;
1018 for (zoom = wd->src_tile->zoom_min; zoom <= wd->src_tile->zoom_max; zoom++)
1019 {
1020 Grid *g;
1021 int tnum;
1022 g = ELM_NEW(Grid);
1023 g->wd = wd;
1024 g->zoom = zoom;
1025 tnum = pow(2.0, g->zoom);
1026 g->tw = tnum;
1027 g->th = tnum;
1028 g->grid = eina_matrixsparse_new(g->th, g->tw, NULL, NULL);
1029 wd->grids = eina_list_append(wd->grids, g);
1030 }
1031}
1032
1033static void
1034_grid_all_clear(Widget_Data *wd)
1035{
1036 EINA_SAFETY_ON_NULL_RETURN(wd);
1037
1038 Grid *g;
1039 EINA_LIST_FREE(wd->grids, g)
1040 {
1041 Eina_Matrixsparse_Cell *cell;
1042 Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1043 EINA_ITERATOR_FOREACH(it, cell)
1044 {
1045 Grid_Item *gi;
1046 gi = eina_matrixsparse_cell_data_get(cell);
1047 if (gi) _grid_item_free(gi);
1048 }
1049 eina_iterator_free(it);
1050
1051 eina_matrixsparse_free(g->grid);
1052 free(g);
1053 }
1054}
1055
1056static void
1057_track_place(Widget_Data *wd)
1058{
1059#ifdef ELM_EMAP
1060 EINA_SAFETY_ON_NULL_RETURN(wd);
1061
1062 Eina_List *l;
1063 Evas_Object *route;
1064 int xmin, xmax, ymin, ymax;
1065 Evas_Coord px, py, ow, oh;
1066 px = wd->pan_x;
1067 py = wd->pan_y;
1068 _viewport_coord_get(wd, NULL, NULL, &ow, &oh);
1069
1070 Evas_Coord size = wd->size.w;
1071
1072 EINA_LIST_FOREACH(wd->track, l, route)
1073 {
1074 double lon_min, lon_max;
1075 double lat_min, lat_max;
1076 elm_route_longitude_min_max_get(route, &lon_min, &lon_max);
1077 elm_route_latitude_min_max_get(route, &lat_min, &lat_max);
1078 _region_to_coord_convert(wd, lon_min, lat_max, size, &xmin, &ymin);
1079 _region_to_coord_convert(wd, lon_max, lat_min, size, &xmax, &ymax);
1080
1081 if ( !(xmin < px && xmax < px) && !(xmin > px+ow && xmax > px+ow))
1082 {
1083 if ( !(ymin < py && ymax < py) && !(ymin > py+oh && ymax > py+oh))
1084 {
1085 //display the route
1086 evas_object_move(route, xmin - px, ymin - py);
1087 evas_object_resize(route, xmax - xmin, ymax - ymin);
1088
1089 evas_object_raise(route);
1090 _obj_rotate(wd, route);
1091 evas_object_show(route);
1092
1093 continue;
1094 }
1095 }
1096 //the route is not display
1097 evas_object_hide(route);
1098 }
1099#else
1100 (void) wd;
1101#endif
1102}
1103
1104static void
1105_delayed_do(Widget_Data *wd)
1106{
1107 Delayed_Data *dd;
1108 dd = eina_list_nth(wd->delayed_jobs, 0);
1109 if (dd && !dd->wd->zoom_animator)
1110 {
1111 dd->func(dd);
1112 wd->delayed_jobs = eina_list_remove(wd->delayed_jobs, dd);
1113 free(dd);
1114 }
1115}
1116
1117static void
1118_smooth_update(Widget_Data *wd)
1119{
1120 EINA_SAFETY_ON_NULL_RETURN(wd);
1121 Eina_List *l;
1122 Grid *g;
1123
1124 EINA_LIST_FOREACH(wd->grids, l, g)
1125 {
1126 Eina_Iterator *it = eina_matrixsparse_iterator_new(g->grid);
1127 Eina_Matrixsparse_Cell *cell;
1128
1129 EINA_ITERATOR_FOREACH(it, cell)
1130 {
1131 Grid_Item *gi = eina_matrixsparse_cell_data_get(cell);
1132 if (_grid_item_in_viewport(gi))
1133 evas_object_image_smooth_scale_set(gi->img, EINA_TRUE);
1134 }
1135 eina_iterator_free(it);
1136 }
1137}
1138
1139static Eina_Bool
1140_zoom_timeout(void *data)
1141{
1142 EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
1143 Widget_Data *wd = data;
1144 _smooth_update(wd);
1145 wd->zoom_timer = NULL;
1146 evas_object_smart_callback_call(wd->obj, SIG_ZOOM_STOP, NULL);
1147 return ECORE_CALLBACK_CANCEL;
1148}
1149
1150static void
1151zoom_do(Widget_Data *wd, double zoom)
1152{
1153 EINA_SAFETY_ON_NULL_RETURN(wd);
1154 if (zoom > wd->src_tile->zoom_max) zoom = wd->src_tile->zoom_max;
1155 else if (zoom < wd->src_tile->zoom_min) zoom = wd->src_tile->zoom_min;
1156 if (zoom > wd->zoom_max) zoom = wd->zoom_max;
1157 else if (zoom < wd->zoom_min) zoom = wd->zoom_min;
1158
1159 Evas_Coord vx, vy, vw, vh;
1160 Evas_Coord ow, oh;
1161
1162 wd->zoom = ROUND(zoom);
1163 wd->zoom_detail = zoom;
1164 ow = wd->size.w;
1165 oh = wd->size.h;
1166 wd->size.tile = pow(2.0, (zoom - wd->zoom)) * wd->tsize;
1167 wd->size.w = pow(2.0, wd->zoom) * wd->size.tile;
1168 wd->size.h = wd->size.w;;
1169
1170 // Fix to zooming with (viewport center vx, vy) as the center to prevent
1171 // from zooming with (0,0) as the cetner. (scroller default behavior)
1172 _viewport_coord_get(wd, &vx, &vy, &vw, &vh);
1173 if ((vw > 0) && (vh > 0) && (ow > 0) && (oh > 0))
1174 {
1175 Evas_Coord x, y;
1176 double sx, sy;
1177 if (vw > ow) sx = 0.5;
1178 else sx = (double)(vx + (double)(vw / 2)) / ow;
1179 if (vh > oh) sy = 0.5;
1180 else sy = (double)(vy + (double)(vh / 2)) / oh;
1181
1182 if (sx > 1.0) sx = 1.0;
1183 if (sy > 1.0) sy = 1.0;
1184
1185 x = ceil((sx * wd->size.w) - (vw / 2));
1186 y = ceil((sy * wd->size.h) - (vh / 2));
1187 if (x < 0) x = 0;
1188 else if (x > (wd->size.w - vw)) x = wd->size.w - vw;
1189 if (y < 0) y = 0;
1190 else if (y > (wd->size.h - vh)) y = wd->size.h - vh;
1191 elm_smart_scroller_child_region_show(wd->scr, x, y, vw, vh);
1192 }
1193 if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer);
1194 else evas_object_smart_callback_call(wd->obj, SIG_ZOOM_START, NULL);
1195 wd->zoom_timer = ecore_timer_add(0.25, _zoom_timeout, wd);
1196 evas_object_smart_callback_call(wd->obj, SIG_ZOOM_CHANGE, NULL);
1197
1198 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
1199 evas_object_smart_changed(wd->pan_smart);
1200}
1201
1202static Eina_Bool
1203_zoom_anim(void *data)
1204{
1205 Widget_Data *wd = data;
1206 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, ECORE_CALLBACK_CANCEL);
1207
1208 if (wd->ani.cnt <= 0)
1209 {
1210 wd->zoom_animator = NULL;
1211 evas_object_smart_changed(wd->pan_smart);
1212 return ECORE_CALLBACK_CANCEL;
1213 }
1214 else
1215 {
1216 wd->ani.zoom += wd->ani.diff;
1217 wd->ani.cnt--;
1218 zoom_do(wd, wd->ani.zoom);
1219 return ECORE_CALLBACK_RENEW;
1220 }
1221}
1222
1223static void
1224zoom_with_animation(Widget_Data *wd, double zoom, int cnt)
1225{
1226 EINA_SAFETY_ON_NULL_RETURN(wd);
1227 if (cnt == 0) return;
1228
1229 wd->ani.cnt = cnt;
1230 wd->ani.zoom = wd->zoom;
1231 wd->ani.diff = (double)(zoom - wd->zoom) / cnt;
1232 if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
1233 wd->zoom_animator = ecore_animator_add(_zoom_anim, wd);
1234}
1235
1236static void
1237_sizing_eval(Widget_Data *wd)
1238{
1239 EINA_SAFETY_ON_NULL_RETURN(wd);
1240
1241 Evas_Coord maxw = -1, maxh = -1;
1242
1243 evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
1244 evas_object_size_hint_max_set(wd->obj, maxw, maxh);
1245}
1246
1247static void
1248_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1249{
1250 _sizing_eval(data);
1251}
1252
1253static Eina_Bool
1254_scr_timeout(void *data)
1255{
1256 EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
1257 Widget_Data *wd = data;
1258 _smooth_update(wd);
1259 wd->scr_timer = NULL;
1260 evas_object_smart_callback_call(wd->obj, SIG_SCROLL_DRAG_STOP, NULL);
1261 return ECORE_CALLBACK_CANCEL;
1262}
1263
1264static void
1265_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1266{
1267 EINA_SAFETY_ON_NULL_RETURN(data);
1268 Widget_Data *wd = data;
1269
1270 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
1271 else evas_object_smart_callback_call(wd->obj, SIG_SCROLL_DRAG_START, NULL);
1272 wd->scr_timer = ecore_timer_add(0.25, _scr_timeout, wd);
1273 evas_object_smart_callback_call(wd->obj, SIG_SCROLL, NULL);
1274}
1275
1276static void
1277_scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1278{
1279 EINA_SAFETY_ON_NULL_RETURN(data);
1280 Widget_Data *wd = data;
1281 evas_object_smart_callback_call(wd->obj, SIG_SCROLL_ANIM_START, NULL);
1282}
1283
1284static void
1285_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1286{
1287 EINA_SAFETY_ON_NULL_RETURN(data);
1288 Widget_Data *wd = data;
1289 evas_object_smart_callback_call(wd->obj, SIG_SCROLL_ANIM_STOP, NULL);
1290}
1291
1292static Eina_Bool
1293_long_press(void *data)
1294{
1295 EINA_SAFETY_ON_NULL_RETURN_VAL(data, ECORE_CALLBACK_CANCEL);
1296 Widget_Data *wd = data;
1297
1298 wd->long_timer = NULL;
1299 evas_object_smart_callback_call(wd->obj, SIG_LONGPRESSED, &wd->ev);
1300 return ECORE_CALLBACK_CANCEL;
1301}
1302
1303static void
1304_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1305{
1306 EINA_SAFETY_ON_NULL_RETURN(data);
1307 Widget_Data *wd = data;
1308 Evas_Event_Mouse_Down *ev = event_info;
1309
1310 if (ev->button != 1) return;
1311
1312 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
1313 else wd->on_hold = EINA_FALSE;
1314
1315 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
1316 evas_object_smart_callback_call(wd->obj, SIG_CLICKED_DOUBLE, ev);
1317 else evas_object_smart_callback_call(wd->obj, SIG_PRESS, ev);
1318
1319 if (wd->long_timer) ecore_timer_del(wd->long_timer);
1320 wd->ev = *ev;
1321 wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, wd);
1322}
1323
1324static void
1325_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1326{
1327 EINA_SAFETY_ON_NULL_RETURN(data);
1328 Widget_Data *wd = data;
1329
1330 Evas_Event_Mouse_Up *ev = event_info;
1331 EINA_SAFETY_ON_NULL_RETURN(ev);
1332
1333 if (ev->button != 1) return;
1334 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
1335 else wd->on_hold = EINA_FALSE;
1336 if (wd->long_timer)
1337 {
1338 ecore_timer_del(wd->long_timer);
1339 wd->long_timer = NULL;
1340 }
1341 if (!wd->on_hold) evas_object_smart_callback_call(wd->obj, SIG_CLICKED, ev);
1342 wd->on_hold = EINA_FALSE;
1343}
1344
1345static void
1346_mouse_wheel_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1347{
1348 EINA_SAFETY_ON_NULL_RETURN(data);
1349 Widget_Data *wd = data;
1350
1351 if (!wd->paused)
1352 {
1353 Evas_Event_Mouse_Wheel *ev = (Evas_Event_Mouse_Wheel*) event_info;
1354 zoom_do(wd, wd->zoom_detail - ((double)ev->z / 10));
1355 }
1356}
1357
1358static void
1359_region_max_min_get(Eina_List *overlays, double *max_longitude, double *min_longitude, double *max_latitude, double *min_latitude)
1360{
1361 double max_lon = -180, min_lon = 180;
1362 double max_lat = -90, min_lat = 90;
1363 Elm_Map_Overlay *overlay;
1364 EINA_LIST_FREE(overlays, overlay)
1365 {
1366 double lon, lat;
1367 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1368 {
1369 Overlay_Default *ovl = overlay->ovl;
1370 lon = ovl->lon;
1371 lat = ovl->lat;
1372 }
1373 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
1374 {
1375 // FIXME: class center coord is alright??
1376 Overlay_Class *ovl = overlay->ovl;
1377 double max_lo, min_lo, max_la, min_la;
1378 _region_max_min_get(ovl->members, &max_lo, &min_lo, &max_la,
1379 &min_la);
1380 lon = (max_lo + min_lo) / 2;
1381 lat = (max_la + min_la) / 2;
1382 }
1383 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
1384 {
1385 Overlay_Bubble *ovl = overlay->ovl;
1386 lon = ovl->lon;
1387 lat = ovl->lat;
1388 }
1389 else
1390 {
1391 WRN("Not supported overlay type: %d", overlay->type);
1392 continue;
1393 }
1394 if (lon> max_lon) max_lon = lon;
1395 if (lon< min_lon) min_lon = lon;
1396 if (lat > max_lat) max_lat = lat;
1397 if (lat < min_lat) min_lat = lat;
1398 }
1399 if (max_longitude) *max_longitude = max_lon;
1400 if (min_longitude) *min_longitude = min_lon;
1401 if (max_latitude) *max_latitude = max_lat;
1402 if (min_latitude) *min_latitude = min_lat;
1403}
1404
1405static Evas_Object *
1406_icon_dup(const Evas_Object *icon, Evas_Object *parent)
1407{
1408 if (!icon || !parent) return NULL;
1409 // Evas_Object do not support object duplication??
1410 const char *file = NULL, *group = NULL;
1411 Eina_Bool size_up, size_down;
1412 Evas_Object *dupp;
1413
1414 dupp = elm_icon_add(parent);
1415 elm_icon_file_get(icon, &file, &group);
1416 elm_icon_file_set(dupp, file, group);
1417 elm_icon_animated_set(dupp, elm_icon_animated_get(icon));
1418 elm_icon_animated_play_set(dupp, elm_icon_animated_play_get(icon));
1419 elm_icon_standard_set(dupp, elm_icon_standard_get(icon));
1420 elm_icon_order_lookup_set(dupp, elm_icon_order_lookup_get(icon));
1421 elm_icon_no_scale_set(dupp, elm_icon_no_scale_get(icon));
1422 elm_icon_resizable_get(icon, &size_up, &size_down);
1423 elm_icon_resizable_set(dupp, size_up, size_down);
1424 elm_icon_fill_outside_set(dupp, elm_icon_fill_outside_get(icon));
1425 elm_icon_prescale_set(dupp, elm_icon_prescale_get(icon));
1426 elm_icon_aspect_fixed_set(dupp, elm_icon_aspect_fixed_get(icon));
1427 return dupp;
1428}
1429
1430static void
1431_overlay_clicked_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *ev __UNUSED__)
1432{
1433 EINA_SAFETY_ON_NULL_RETURN(data);
1434 Elm_Map_Overlay *overlay = data;
1435
1436 evas_object_smart_callback_call(overlay->wd->obj, SIG_OVERLAY_CLICKED,
1437 overlay);
1438 if (overlay->cb) overlay->cb(overlay->cb_data, overlay->wd->obj,
1439 overlay);
1440}
1441
1442static void
1443_overlay_default_hide(Overlay_Default *ovl)
1444{
1445 EINA_SAFETY_ON_NULL_RETURN(ovl);
1446 if (ovl->content) evas_object_hide(ovl->content);
1447 if (ovl->icon) evas_object_hide(ovl->icon);
1448 if (ovl->clas_content) evas_object_hide(ovl->clas_content);
1449 if (ovl->clas_icon) evas_object_hide(ovl->clas_icon);
1450 if (ovl->layout) evas_object_hide(ovl->layout);
1451}
1452
1453static void
1454_overlay_default_show(Overlay_Default *ovl)
1455{
1456 EINA_SAFETY_ON_NULL_RETURN(ovl);
1457 Evas_Object *disp;
1458 Evas_Coord x, y, w, h;
1459
1460 evas_object_hide(ovl->layout);
1461 if (ovl->content)
1462 {
1463 disp = ovl->content;
1464 evas_object_geometry_get(disp, NULL, NULL, &w, &h);
1465 if (w <= 0 || h <= 0) evas_object_size_hint_min_get(disp, &w, &h);
1466 }
1467 else if (!(ovl->icon) && ovl->clas_content)
1468 {
1469 disp = ovl->clas_content;
1470
1471 evas_object_geometry_get(disp, NULL, NULL, &w, &h);
1472 if (w <= 0 || h <= 0) evas_object_size_hint_min_get(disp, &w, &h);
1473 }
1474 else
1475 {
1476 if (ovl->icon) evas_object_show(ovl->icon);
1477 else if (ovl->clas_icon) evas_object_show(ovl->clas_icon);
1478 disp = ovl->layout;
1479 w = ovl->w;
1480 h = ovl->h;
1481 }
1482 _coord_to_canvas(ovl->wd, ovl->x, ovl->y, &x, &y);
1483 _obj_place(disp, x - (w / 2), y - (h / 2), w, h);
1484}
1485
1486static void
1487_overlay_default_coord_get(Overlay_Default *ovl, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1488{
1489 EINA_SAFETY_ON_NULL_RETURN(ovl);
1490 if (x) *x = ovl->x;
1491 if (y) *y = ovl->y;
1492 if (w) *w = ovl->w;
1493 if (h) *h = ovl->h;
1494}
1495
1496static void
1497_overlay_default_coord_set(Overlay_Default *ovl, Evas_Coord x, Evas_Coord y)
1498{
1499 EINA_SAFETY_ON_NULL_RETURN(ovl);
1500 ovl->x = x;
1501 ovl->y = y;
1502}
1503
1504static void
1505_overlay_default_coord_update(Overlay_Default *ovl)
1506{
1507 EINA_SAFETY_ON_NULL_RETURN(ovl);
1508 _region_to_coord_convert(ovl->wd, ovl->lon, ovl->lat, ovl->wd->size.w,
1509 &ovl->x, &ovl->y);
1510}
1511
1512static void
1513_overlay_default_layout_text_update(Overlay_Default *ovl, const char *text)
1514{
1515 if (!ovl->content && !ovl->icon && !ovl->clas_content && !ovl->clas_icon)
1516 edje_object_part_text_escaped_set(elm_layout_edje_get(ovl->layout), "elm.text",
1517 text);
1518}
1519
1520static void
1521_overlay_default_content_update(Overlay_Default *ovl, Evas_Object *content, Elm_Map_Overlay *overlay)
1522{
1523 EINA_SAFETY_ON_NULL_RETURN(ovl);
1524 if (ovl->content == content) return;
1525 if (ovl->content) evas_object_del(ovl->content);
1526 ovl->content = content;
1527
1528 if (ovl->content)
1529 evas_object_event_callback_add(ovl->content, EVAS_CALLBACK_MOUSE_DOWN,
1530 _overlay_clicked_cb, overlay);
1531}
1532
1533static void
1534_overlay_default_clas_content_update(Overlay_Default *ovl, const Evas_Object *content __UNUSED__)
1535{
1536 EINA_SAFETY_ON_NULL_RETURN(ovl);
1537 if (ovl->clas_content) evas_object_del(ovl->clas_content);
1538 // Evas_Object can not be duplicated.
1539 //ovl->clas_content = _content_dup(content);
1540}
1541
1542static void
1543_overlay_default_layout_update(Overlay_Default *ovl)
1544{
1545 EINA_SAFETY_ON_NULL_RETURN(ovl);
1546 if (ovl->icon)
1547 {
1548 evas_object_color_set(ovl->layout, 255, 255, 255, 255);
1549 elm_layout_theme_set(ovl->layout, "map/marker", "empty",
1550 elm_widget_style_get(ovl->wd->obj));
1551 elm_object_part_content_set(ovl->layout, "elm.icon", ovl->icon);
1552 }
1553 else if (!ovl->icon && ovl->clas_icon)
1554 {
1555 evas_object_color_set(ovl->layout, 255, 255, 255, 255);
1556 elm_layout_theme_set(ovl->layout, "map/marker", "empty",
1557 elm_widget_style_get(ovl->wd->obj));
1558 elm_object_part_content_set(ovl->layout, "elm.icon", ovl->clas_icon);
1559 }
1560 else
1561 {
1562 evas_object_color_set(ovl->layout, ovl->c.r, ovl->c.g, ovl->c.b, ovl->c.a);
1563 elm_layout_theme_set(ovl->layout, "map/marker", "radio",
1564 elm_widget_style_get(ovl->wd->obj));
1565 }
1566}
1567
1568static void
1569_overlay_default_icon_update(Overlay_Default *ovl, Evas_Object *icon)
1570{
1571 EINA_SAFETY_ON_NULL_RETURN(ovl);
1572 if (ovl->icon == icon) return;
1573 if (ovl->icon) evas_object_del(ovl->icon);
1574 ovl->icon = icon;
1575 _overlay_default_layout_update(ovl);
1576}
1577
1578static void
1579_overlay_default_clas_icon_update(Overlay_Default *ovl, const Evas_Object *icon)
1580{
1581 EINA_SAFETY_ON_NULL_RETURN(ovl);
1582 if (ovl->clas_icon) evas_object_del(ovl->clas_icon);
1583 ovl->clas_icon = _icon_dup(icon, ovl->layout);
1584 _overlay_default_layout_update(ovl);
1585}
1586
1587static void
1588_overlay_default_color_update(Overlay_Default *ovl, Color c)
1589{
1590 EINA_SAFETY_ON_NULL_RETURN(ovl);
1591 ovl->c = c;
1592 _overlay_default_layout_update(ovl);
1593}
1594
1595static void
1596_overlay_default_free(Overlay_Default *ovl)
1597{
1598 EINA_SAFETY_ON_NULL_RETURN(ovl);
1599 if (ovl->content) evas_object_del(ovl->content);
1600 if (ovl->icon) evas_object_del(ovl->icon);
1601 if (ovl->clas_content) evas_object_del(ovl->clas_content);
1602 if (ovl->clas_icon) evas_object_del(ovl->clas_icon);
1603 if (ovl->layout) evas_object_del(ovl->layout);
1604 free(ovl);
1605}
1606
1607static Overlay_Default *
1608_overlay_default_new(Elm_Map_Overlay *overlay, double lon, double lat, Color c, double scale)
1609{
1610 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
1611
1612 Overlay_Default *ovl = ELM_NEW(Overlay_Default);
1613 ovl->wd = overlay->wd;
1614 _edj_overlay_size_get(ovl->wd, &(ovl->w), &(ovl->h));
1615 ovl->w *= scale;
1616 ovl->h *= scale;
1617 ovl->layout = elm_layout_add(ovl->wd->obj);
1618 evas_object_smart_member_add(ovl->layout, ovl->wd->pan_smart);
1619 evas_object_stack_above(ovl->layout, ovl->wd->sep_maps_overlays);
1620 elm_layout_theme_set(ovl->layout, "map/marker", "radio",
1621 elm_widget_style_get(ovl->wd->obj));
1622 evas_object_event_callback_add(ovl->layout, EVAS_CALLBACK_MOUSE_DOWN,
1623 _overlay_clicked_cb, overlay);
1624 ovl->lon = lon;
1625 ovl->lat = lat;
1626 _overlay_default_color_update(ovl, c);
1627 return ovl;
1628}
1629
1630static void
1631_overlay_group_hide(Overlay_Group *grp)
1632{
1633 EINA_SAFETY_ON_NULL_RETURN(grp);
1634 if (grp->ovl) _overlay_default_hide(grp->ovl);
1635}
1636
1637static void
1638_overlay_group_show(Overlay_Group *grp)
1639{
1640 EINA_SAFETY_ON_NULL_RETURN(grp);
1641 if (grp->ovl) _overlay_default_show(grp->ovl);
1642}
1643
1644static void
1645_overlay_group_coord_member_update(Overlay_Group *grp, Evas_Coord x, Evas_Coord y, Eina_List *members)
1646{
1647 EINA_SAFETY_ON_NULL_RETURN(grp);
1648 if (!grp->ovl) return;
1649 char text[32];
1650
1651 _overlay_default_coord_set(grp->ovl, x, y);
1652 if (grp->members) eina_list_free(grp->members);
1653 grp->members = members;
1654 snprintf(text, sizeof(text), "%d", eina_list_count(members));
1655 _overlay_default_layout_text_update(grp->ovl, text);
1656}
1657
1658static void
1659_overlay_group_region_get(Overlay_Group *grp, double *lon, double *lat)
1660{
1661 EINA_SAFETY_ON_NULL_RETURN(grp);
1662 Evas_Coord xx, yy;
1663 _overlay_default_coord_get(grp->ovl, &xx, &yy, NULL, NULL);
1664 _coord_to_canvas(grp->wd, xx, yy, &xx, &yy);
1665 elm_map_canvas_to_region_convert(grp->wd->obj, xx, yy, lon, lat);
1666}
1667
1668static void
1669_overlay_group_icon_update(Overlay_Group *grp, const Evas_Object *icon)
1670{
1671 EINA_SAFETY_ON_NULL_RETURN(grp);
1672 if (grp->ovl) _overlay_default_icon_update(grp->ovl,
1673 _icon_dup(icon, grp->wd->obj));
1674}
1675
1676static void
1677_overlay_group_content_update(Overlay_Group *grp __UNUSED__, const Evas_Object *content __UNUSED__)
1678{
1679 EINA_SAFETY_ON_NULL_RETURN(grp);
1680 // Evas_Object can not be duplicated.
1681 //_overlay_default_content_update(grp->ovl, _content_dup(content));
1682 return;
1683}
1684
1685static void
1686_overlay_group_color_update(Overlay_Group *grp, Color c)
1687{
1688 EINA_SAFETY_ON_NULL_RETURN(grp);
1689 _overlay_default_color_update(grp->ovl, c);
1690}
1691
1692static void
1693_overlay_group_cb_set(Overlay_Group *grp, Elm_Map_Overlay_Get_Cb cb, void *data)
1694{
1695 EINA_SAFETY_ON_NULL_RETURN(grp);
1696 grp->overlay->cb = cb;
1697 grp->overlay->data = data;
1698}
1699
1700static void
1701_overlay_group_free(Overlay_Group *grp)
1702{
1703 EINA_SAFETY_ON_NULL_RETURN(grp);
1704 if (grp->overlay) free(grp->overlay);
1705 if (grp->ovl) _overlay_default_free(grp->ovl);
1706 if (grp->members) eina_list_free(grp->members);
1707 free(grp);
1708}
1709
1710static Overlay_Group *
1711_overlay_group_new(Widget_Data *wd)
1712{
1713 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
1714
1715 Overlay_Group *grp = ELM_NEW(Overlay_Group);
1716 grp->wd = wd;
1717 grp->overlay = ELM_NEW(Elm_Map_Overlay); // this is a virtual overlay
1718 grp->overlay->wd = wd;
1719 grp->overlay->type = ELM_MAP_OVERLAY_TYPE_GROUP;
1720 grp->overlay->ovl = grp;
1721 Color c = {0x90, 0xee, 0x90, 0xff};
1722 grp->ovl = _overlay_default_new(grp->overlay, -1, -1, c, 2);
1723 return grp;
1724}
1725
1726static void
1727_overlay_class_cb_set(Overlay_Class *ovl, Elm_Map_Overlay_Get_Cb cb, void *data)
1728{
1729 EINA_SAFETY_ON_NULL_RETURN(ovl);
1730
1731 Eina_List *l;
1732 Elm_Map_Overlay *overlay;
1733
1734 // Update class members' callbacks
1735 EINA_LIST_FOREACH(ovl->members, l, overlay)
1736 _overlay_group_cb_set(overlay->grp, cb, data);
1737}
1738
1739static void
1740_overlay_class_icon_update(Overlay_Class *ovl, Evas_Object *icon)
1741{
1742 EINA_SAFETY_ON_NULL_RETURN(ovl);
1743
1744 Eina_List *l;
1745 Elm_Map_Overlay *overlay;
1746 if (ovl->icon == icon) return;
1747 if (ovl->icon) evas_object_del(ovl->icon);
1748 ovl->icon = icon;
1749
1750 // Update class members' class icons
1751 EINA_LIST_FOREACH(ovl->members, l, overlay)
1752 {
1753 _overlay_group_icon_update(overlay->grp, icon);
1754
1755 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1756 _overlay_default_clas_icon_update(overlay->ovl, icon);
1757
1758 }
1759}
1760
1761static void
1762_overlay_class_content_update(Overlay_Class *ovl, Evas_Object *content)
1763{
1764 EINA_SAFETY_ON_NULL_RETURN(ovl);
1765
1766 Eina_List *l;
1767 Elm_Map_Overlay *overlay;
1768 if (ovl->content == content) return;
1769 if (ovl->content) evas_object_del(ovl->content);
1770 ovl->content = content;
1771
1772 // Update class members' class contents
1773 EINA_LIST_FOREACH(ovl->members, l, overlay)
1774 {
1775 _overlay_group_content_update(overlay->grp, content);
1776
1777 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1778 _overlay_default_clas_content_update(overlay->ovl, content);
1779 }
1780}
1781
1782static void
1783_overlay_class_color_update(Overlay_Class *ovl, Color c)
1784{
1785 EINA_SAFETY_ON_NULL_RETURN(ovl);
1786
1787 Eina_List *l;
1788 Elm_Map_Overlay *overlay;
1789
1790 // Update class members' class contents
1791 EINA_LIST_FOREACH(ovl->members, l, overlay)
1792 _overlay_group_color_update(overlay->grp, c);
1793}
1794
1795static void
1796_overlay_class_free(Overlay_Class *clas)
1797{
1798 EINA_SAFETY_ON_NULL_RETURN(clas);
1799
1800 Eina_List *l;
1801 Elm_Map_Overlay *overlay;
1802
1803 // Update class members' class contents
1804 EINA_LIST_FOREACH(clas->members, l, overlay)
1805 {
1806 overlay->grp->clas = NULL;
1807 _overlay_group_content_update(overlay->grp, NULL);
1808 _overlay_group_icon_update(overlay->grp, NULL);
1809
1810 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
1811 {
1812 _overlay_default_clas_content_update(overlay->ovl, NULL);
1813 _overlay_default_clas_icon_update(overlay->ovl, NULL);
1814 }
1815 }
1816 if (clas->icon) evas_object_del(clas->icon);
1817 if (clas->members) eina_list_free(clas->members);
1818 free(clas);
1819}
1820
1821static Overlay_Class *
1822_overlay_class_new(Widget_Data *wd)
1823{
1824 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
1825 Overlay_Class *ovl = ELM_NEW(Overlay_Class);
1826 ovl->wd = wd;
1827 ovl->icon = NULL;
1828 ovl->zoom_max = OVERLAY_CLASS_ZOOM_MAX;
1829 return ovl;
1830}
1831
1832static void
1833_overlay_bubble_hide(Overlay_Bubble *bubble)
1834{
1835 EINA_SAFETY_ON_NULL_RETURN(bubble);
1836 if (bubble->obj) evas_object_hide(bubble->obj);
1837}
1838
1839static void
1840_overlay_bubble_coord_update(Overlay_Bubble *bubble)
1841{
1842 EINA_SAFETY_ON_NULL_RETURN(bubble);
1843 if (!(bubble->pobj))
1844 {
1845 _region_to_coord_convert(bubble->wd, bubble->lon, bubble->lat,
1846 bubble->wd->size.w, &bubble->x, &bubble->y);
1847 }
1848}
1849
1850static void
1851_overlay_bubble_coord_get(Overlay_Bubble *bubble, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1852{
1853 EINA_SAFETY_ON_NULL_RETURN(bubble);
1854 if (!(bubble->pobj))
1855 {
1856 if (x) *x = bubble->x;
1857 if (y) *y = bubble->y;
1858 if (w) *w = bubble->w;
1859 if (h) *h = bubble->h;
1860 }
1861 else
1862 {
1863 if (x) *x = 0;
1864 if (y) *y = 0;
1865 if (w) *w = 0;
1866 if (h) *h = 0;
1867 }
1868}
1869
1870static void
1871_overlay_bubble_show(Overlay_Bubble *bubble)
1872{
1873 EINA_SAFETY_ON_NULL_RETURN(bubble);
1874 if (!(bubble->pobj))
1875 {
1876 _coord_to_canvas(bubble->wd, bubble->x, bubble->y,
1877 &(bubble->x), &(bubble->y));
1878 _obj_place(bubble->obj, bubble->x - (bubble->w /2),
1879 bubble->y - (bubble->h /2), bubble->w, bubble->h);
1880 }
1881}
1882
1883static void
1884_overlay_bubble_chase(Overlay_Bubble *bubble)
1885{
1886 EINA_SAFETY_ON_NULL_RETURN(bubble);
1887 EINA_SAFETY_ON_NULL_RETURN(bubble->pobj);
1888
1889 Evas_Coord x, y, w;
1890 evas_object_geometry_get(bubble->pobj, &x, &y, &w, NULL);
1891 x = x + (w / 2) - (bubble->w / 2);
1892 y = y - bubble->h;
1893 _obj_place(bubble->obj, x, y, bubble->w, bubble->h);
1894 evas_object_raise(bubble->obj);
1895}
1896
1897static void
1898_overlay_bubble_hide_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1899{
1900 EINA_SAFETY_ON_NULL_RETURN(data);
1901 _overlay_bubble_hide(data);
1902}
1903
1904static void
1905_overlay_bubble_chase_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1906{
1907 EINA_SAFETY_ON_NULL_RETURN(data);
1908 _overlay_bubble_chase(data);
1909}
1910
1911static void
1912_overlay_bubble_free(Overlay_Bubble* bubble)
1913{
1914 EINA_SAFETY_ON_NULL_RETURN(bubble);
1915
1916 evas_object_del(bubble->bx);
1917 evas_object_del(bubble->sc);
1918 evas_object_del(bubble->obj);
1919 if (bubble->pobj)
1920 {
1921 evas_object_event_callback_del_full(bubble->pobj, EVAS_CALLBACK_HIDE,
1922 _overlay_bubble_hide_cb, bubble);
1923 evas_object_event_callback_del_full(bubble->pobj, EVAS_CALLBACK_SHOW,
1924 _overlay_bubble_chase_cb, bubble);
1925 evas_object_event_callback_del_full(bubble->pobj, EVAS_CALLBACK_MOVE,
1926 _overlay_bubble_chase_cb, bubble);
1927 }
1928 free(bubble);
1929}
1930
1931static Overlay_Bubble*
1932_overlay_bubble_new(Elm_Map_Overlay *overlay)
1933{
1934 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
1935
1936 Evas_Coord h;
1937 const char *s;
1938 Overlay_Bubble *bubble = ELM_NEW(Overlay_Bubble);
1939 bubble->wd = overlay->wd;
1940
1941 bubble->obj = edje_object_add(evas_object_evas_get(overlay->wd->obj));
1942 _elm_theme_object_set(overlay->wd->obj, bubble->obj , "map", "marker_bubble",
1943 elm_widget_style_get(overlay->wd->obj));
1944 evas_object_event_callback_add(bubble->obj, EVAS_CALLBACK_MOUSE_UP,
1945 _overlay_bubble_chase_cb, bubble);
1946 evas_object_event_callback_add(bubble->obj, EVAS_CALLBACK_MOUSE_DOWN,
1947 _overlay_clicked_cb, overlay);
1948
1949 bubble->sc = elm_scroller_add(bubble->obj);
1950 elm_widget_style_set(bubble->sc, "map_bubble");
1951 elm_scroller_content_min_limit(bubble->sc, EINA_FALSE, EINA_TRUE);
1952 elm_scroller_policy_set(bubble->sc, ELM_SCROLLER_POLICY_AUTO,
1953 ELM_SCROLLER_POLICY_OFF);
1954 elm_scroller_bounce_set(bubble->sc, _elm_config->thumbscroll_bounce_enable,
1955 EINA_FALSE);
1956 edje_object_part_swallow(bubble->obj, "elm.swallow.content", bubble->sc);
1957
1958 bubble->bx = elm_box_add(bubble->sc);
1959 evas_object_size_hint_align_set(bubble->bx, EVAS_HINT_FILL, EVAS_HINT_FILL);
1960 evas_object_size_hint_weight_set(bubble->bx, EVAS_HINT_EXPAND,
1961 EVAS_HINT_EXPAND);
1962 elm_box_horizontal_set(bubble->bx, EINA_TRUE);
1963 elm_object_content_set(bubble->sc, bubble->bx);
1964
1965 s = edje_object_data_get(bubble->obj, "size_w");
1966 if (s) bubble->w = atoi(s);
1967 else bubble->w = 0;
1968
1969 edje_object_size_min_calc(bubble->obj, NULL, &(bubble->h));
1970 s = edje_object_data_get(bubble->obj, "size_h");
1971 if (s) h = atoi(s);
1972 else h = 0;
1973 if (bubble->h < h) bubble->h = h;
1974
1975 bubble->lon = -1;
1976 bubble->lat = -1;
1977 bubble->x = -1;
1978 bubble->y = -1;
1979 return bubble;
1980}
1981
1982static void
1983_overlay_route_color_update(Overlay_Route *ovl, Color c)
1984{
1985 EINA_SAFETY_ON_NULL_RETURN(ovl);
1986 evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
1987}
1988
1989static void
1990_overlay_route_hide(Overlay_Route *ovl)
1991{
1992 EINA_SAFETY_ON_NULL_RETURN(ovl);
1993 evas_object_hide(ovl->obj);
1994}
1995
1996static void
1997_overlay_route_show(Overlay_Route *r)
1998{
1999 EINA_SAFETY_ON_NULL_RETURN(r);
2000 EINA_SAFETY_ON_NULL_RETURN(r->wd);
2001
2002 Eina_List *l;
2003 Path *p;
2004 Path_Node *n;
2005
2006 evas_object_polygon_points_clear(r->obj);
2007 EINA_LIST_FOREACH(r->nodes, l, n)
2008 {
2009 p = eina_list_nth(r->paths, n->idx);
2010 if (!p) continue;
2011 _region_to_coord_convert(r->wd, n->pos.lon, n->pos.lat, r->wd->size.w,
2012 &p->x, &p->y);
2013 _coord_to_canvas(r->wd, p->x, p->y, &p->x, &p->y);
2014 }
2015 EINA_LIST_FOREACH(r->paths, l, p)
2016 evas_object_polygon_point_add(r->obj, p->x - 3, p->y - 3);
2017
2018 EINA_LIST_REVERSE_FOREACH(r->paths, l, p)
2019 evas_object_polygon_point_add(r->obj, p->x + 3, p->y + 3);
2020 evas_object_show(r->obj);
2021}
2022
2023static void
2024_overlay_route_free(Overlay_Route* route)
2025{
2026 EINA_SAFETY_ON_NULL_RETURN(route);
2027 Path *p;
2028 Path_Node *n;
2029
2030 evas_object_del(route->obj);
2031 EINA_LIST_FREE(route->paths, p) free(p);
2032 EINA_LIST_FREE(route->nodes, n)
2033 {
2034 if (n->pos.address) eina_stringshare_del(n->pos.address);
2035 free(n);
2036 }
2037 free(route);
2038}
2039
2040static Overlay_Route *
2041_overlay_route_new(Widget_Data *wd, const Elm_Map_Route *route, Color c)
2042{
2043 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2044 EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
2045
2046 Eina_List *l;
2047 Path_Node *n;
2048
2049 Overlay_Route *ovl = ELM_NEW(Overlay_Route);
2050 ovl->wd = wd;
2051 ovl->obj = evas_object_polygon_add(evas_object_evas_get(wd->obj));
2052 evas_object_smart_member_add(ovl->obj, wd->pan_smart);
2053 _overlay_route_color_update(ovl, c);
2054
2055 EINA_LIST_FOREACH(route->nodes, l, n)
2056 {
2057 Path *path;
2058 Path_Node *node;
2059
2060 node = ELM_NEW(Path_Node);
2061 node->idx = n->idx;
2062 node->pos.lon = n->pos.lon;
2063 node->pos.lat = n->pos.lat;
2064 if (n->pos.address) node->pos.address = strdup(n->pos.address);
2065 ovl->nodes = eina_list_append(ovl->nodes, node);
2066
2067 path = ELM_NEW(Path);
2068 ovl->paths = eina_list_append(ovl->paths, path);
2069 }
2070 return ovl;
2071}
2072
2073static void
2074_overlay_line_color_update(Overlay_Line *ovl, Color c)
2075{
2076 EINA_SAFETY_ON_NULL_RETURN(ovl);
2077 evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2078}
2079
2080static void
2081_overlay_line_hide(Overlay_Line *ovl)
2082{
2083 EINA_SAFETY_ON_NULL_RETURN(ovl);
2084 if (ovl->obj) evas_object_hide(ovl->obj);
2085}
2086
2087static void
2088_overlay_line_show(Overlay_Line *ovl)
2089{
2090 Evas_Coord fx, fy, tx, ty;
2091 Widget_Data *wd = ovl->wd;
2092
2093 _region_to_coord_convert(wd, ovl->flon, ovl->flat, wd->size.w, &fx, &fy);
2094 _region_to_coord_convert(wd, ovl->tlon, ovl->tlat, wd->size.w, &tx, &ty);
2095 _coord_to_canvas(wd, fx, fy, &fx, &fy);
2096 _coord_to_canvas(wd, tx, ty, &tx, &ty);
2097 evas_object_line_xy_set(ovl->obj, fx, fy, tx, ty);
2098 evas_object_show(ovl->obj);
2099}
2100
2101static void
2102_overlay_line_free(Overlay_Line *ovl)
2103{
2104 EINA_SAFETY_ON_NULL_RETURN(ovl);
2105 evas_object_del(ovl->obj);
2106 free(ovl);
2107}
2108
2109static Overlay_Line *
2110_overlay_line_new(Widget_Data *wd, double flon, double flat, double tlon, double tlat, Color c)
2111{
2112 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2113
2114 Overlay_Line *ovl = ELM_NEW(Overlay_Line);
2115 ovl->wd = wd;
2116 ovl->flon = flon;
2117 ovl->flat = flat;
2118 ovl->tlon = tlon;
2119 ovl->tlat = tlat;
2120 ovl->obj = evas_object_line_add(evas_object_evas_get(wd->obj));
2121 evas_object_smart_member_add(ovl->obj, wd->pan_smart);
2122 _overlay_line_color_update(ovl, c);
2123 return ovl;
2124}
2125
2126static void
2127_overlay_polygon_color_update(Overlay_Polygon *ovl, Color c)
2128{
2129 EINA_SAFETY_ON_NULL_RETURN(ovl);
2130 evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2131}
2132
2133static void
2134_overlay_polygon_hide(Overlay_Polygon *ovl)
2135{
2136 EINA_SAFETY_ON_NULL_RETURN(ovl);
2137 if (ovl->obj) evas_object_hide(ovl->obj);
2138}
2139
2140static void
2141_overlay_polygon_show(Overlay_Polygon *ovl)
2142{
2143 EINA_SAFETY_ON_NULL_RETURN(ovl);
2144 Eina_List *l;
2145 Region *r;
2146 Widget_Data *wd = ovl->wd;
2147
2148 evas_object_polygon_points_clear(ovl->obj);
2149 EINA_LIST_FOREACH(ovl->regions, l, r)
2150 {
2151 Evas_Coord x, y;
2152 _region_to_coord_convert(wd, r->lon, r->lat, wd->size.w, &x, &y);
2153 _coord_to_canvas(wd, x, y, &x, &y);
2154 evas_object_polygon_point_add(ovl->obj, x, y);
2155 }
2156 evas_object_show(ovl->obj);
2157}
2158
2159static void
2160_overlay_polygon_free(Overlay_Polygon *ovl)
2161{
2162 EINA_SAFETY_ON_NULL_RETURN(ovl);
2163 Region *r;
2164 evas_object_del(ovl->obj);
2165 EINA_LIST_FREE(ovl->regions, r) free(r);
2166 free(ovl);
2167}
2168
2169static Overlay_Polygon *
2170_overlay_polygon_new(Widget_Data *wd, Color c)
2171{
2172 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2173
2174 Overlay_Polygon *ovl = ELM_NEW(Overlay_Polygon);
2175 ovl->wd = wd;
2176 ovl->obj = evas_object_polygon_add(evas_object_evas_get(wd->obj));
2177 evas_object_smart_member_add(ovl->obj, wd->pan_smart);
2178 _overlay_polygon_color_update(ovl, c);
2179 return ovl;
2180}
2181
2182static void
2183_overlay_circle_color_update(Overlay_Circle *ovl, Color c)
2184{
2185 EINA_SAFETY_ON_NULL_RETURN(ovl);
2186 Evas_Object *obj = elm_layout_edje_get(ovl->obj);
2187 evas_object_color_set(obj, c.r, c.g, c.b, c.a);
2188}
2189
2190static void
2191_overlay_circle_hide(Overlay_Circle *ovl)
2192{
2193 EINA_SAFETY_ON_NULL_RETURN(ovl);
2194 if (ovl->obj) evas_object_hide(ovl->obj);
2195}
2196
2197static void
2198_overlay_circle_show(Overlay_Circle *ovl)
2199{
2200 EINA_SAFETY_ON_NULL_RETURN(ovl);
2201 double r;
2202 Evas_Coord x, y;
2203 Widget_Data *wd = ovl->wd;
2204
2205 r = (ovl->ratio) * wd->size.w;
2206 _region_to_coord_convert(wd, ovl->lon, ovl->lat, wd->size.w, &x, &y);
2207 _coord_to_canvas(wd, x, y, &x, &y);
2208 _obj_place(ovl->obj, x - r, y - r, r * 2, r * 2);
2209}
2210
2211static void
2212_overlay_circle_free(Overlay_Circle *ovl)
2213{
2214 EINA_SAFETY_ON_NULL_RETURN(ovl);
2215 evas_object_del(ovl->obj);
2216 free(ovl);
2217}
2218
2219static Overlay_Circle *
2220_overlay_circle_new(Widget_Data *wd, double lon, double lat, double radius, Color c)
2221{
2222 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2223
2224 Overlay_Circle *ovl = ELM_NEW(Overlay_Circle);
2225 ovl->wd = wd;
2226 ovl->lon = lon;
2227 ovl->lat = lat;
2228 ovl->radius = radius;
2229 ovl->ratio = radius / wd->size.w;
2230
2231 ovl->obj = elm_layout_add(wd->obj);
2232 evas_object_smart_member_add(ovl->obj, wd->pan_smart);
2233 evas_object_stack_above(ovl->obj, wd->sep_maps_overlays);
2234 elm_layout_theme_set(ovl->obj, "map/circle", "base",
2235 elm_widget_style_get(wd->obj));
2236 _overlay_circle_color_update(ovl, c);
2237 return ovl;
2238}
2239
2240static void
2241_overlay_scale_color_update(Overlay_Scale *ovl, Color c)
2242{
2243 EINA_SAFETY_ON_NULL_RETURN(ovl);
2244 evas_object_color_set(ovl->obj, c.r, c.g, c.b, c.a);
2245}
2246
2247static void
2248_overlay_scale_hide(Overlay_Scale *ovl)
2249{
2250 EINA_SAFETY_ON_NULL_RETURN(ovl);
2251 if (ovl->obj) evas_object_hide(ovl->obj);
2252}
2253
2254 static void
2255_overlay_scale_show(Overlay_Scale *ovl)
2256{
2257 EINA_SAFETY_ON_NULL_RETURN(ovl);
2258 Evas_Coord w;
2259 double lon, lat;
2260 double text;
2261 char buf[32];
2262 double meter;
2263 Widget_Data *wd = ovl->wd;
2264
2265 if ((int)sizeof(_scale_tb) <= wd->zoom)
2266 {
2267 ERR("Zoom level is too high");
2268 return;
2269 }
2270
2271 elm_map_region_get(wd->obj, &lon, &lat);
2272 meter = wd->src_tile->scale_cb(wd->obj, lon, lat, wd->zoom);
2273
2274 w = (_scale_tb[wd->zoom] / meter) * (wd->zoom_detail - wd->zoom + 1);
2275
2276 text = _scale_tb[wd->zoom]/1000;
2277 if (text < 1) snprintf(buf, sizeof(buf), "%d m", (int)(text * 1000));
2278 else snprintf(buf, sizeof(buf), "%d km", (int)text);
2279
2280 edje_object_part_text_escaped_set(elm_layout_edje_get(ovl->obj), "elm.text", buf);
2281 _obj_place(ovl->obj, ovl->x, ovl->y, w, ovl->h);
2282}
2283
2284 static void
2285_overlay_scale_free(Overlay_Scale *ovl)
2286{
2287 EINA_SAFETY_ON_NULL_RETURN(ovl);
2288 evas_object_del(ovl->obj);
2289 free(ovl);
2290}
2291
2292static Overlay_Scale *
2293_overlay_scale_new(Widget_Data *wd, Evas_Coord x, Evas_Coord y, Color c)
2294{
2295 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2296 const char *s;
2297
2298 Overlay_Scale *ovl = ELM_NEW(Overlay_Scale);
2299 ovl->wd = wd;
2300 ovl->x = x;
2301 ovl->y = y;
2302
2303 ovl->obj = elm_layout_add(wd->obj);
2304 evas_object_smart_member_add(ovl->obj, wd->pan_smart);
2305 evas_object_stack_above(ovl->obj, wd->sep_maps_overlays);
2306 elm_layout_theme_set(ovl->obj, "map/scale", "base",
2307 elm_widget_style_get(wd->obj));
2308 s = edje_object_data_get(elm_layout_edje_get(ovl->obj), "size_w");
2309 if (s) ovl->w = atoi(s);
2310 else ovl->w = 100;
2311 s = edje_object_data_get(elm_layout_edje_get(ovl->obj), "size_h");
2312 if (s) ovl->h = atoi(s);
2313 else ovl->h = 60;
2314 _overlay_scale_color_update(ovl, c);
2315 return ovl;
2316}
2317
2318static void
2319_overlay_grouping(Eina_List *clas_membs, Elm_Map_Overlay *boss)
2320{
2321 EINA_SAFETY_ON_NULL_RETURN(clas_membs);
2322 EINA_SAFETY_ON_NULL_RETURN(boss);
2323
2324 Eina_List *l;
2325 Eina_List *grp_membs = NULL;
2326 Elm_Map_Overlay *memb;
2327
2328 int sum_x = 0, sum_y = 0, cnt = 0;
2329 Evas_Coord bx = 0, by = 0, bw = 0, bh = 0;
2330
2331 if (boss->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2332 _overlay_default_coord_get(boss->ovl, &bx, &by, &bw, &bh);
2333 else if (boss->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2334 _overlay_bubble_coord_get(boss->ovl, &bx, &by, &bw, &bh);
2335
2336 EINA_LIST_FOREACH(clas_membs, l, memb)
2337 {
2338 Evas_Coord x = 0, y = 0, w = 0, h = 0;
2339
2340 if (boss == memb || memb->grp->in) continue;
2341 if ((memb->hide) || (memb->zoom_min > memb->wd->zoom)) continue;
2342
2343 if (memb->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2344 _overlay_default_coord_get(memb->ovl, &x, &y, &w, &h);
2345 else if (memb->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2346 _overlay_bubble_coord_get(memb->ovl, &x, &y, &w, &h);
2347
2348 if (bw <= 0 || bh <= 0 || w <= 0 || h <= 0) continue;
2349 if (ELM_RECTS_INTERSECT(x, y, w, h, bx, by,
2350 bw * OVERLAY_GROUPING_SCALE,
2351 bh * OVERLAY_GROUPING_SCALE))
2352 {
2353 // Join group.
2354 memb->grp->boss = EINA_FALSE;
2355 memb->grp->in = EINA_TRUE;
2356 sum_x += x;
2357 sum_y += y;
2358 cnt++;
2359 grp_membs = eina_list_append(grp_membs, memb);
2360 }
2361 }
2362
2363 if (cnt >= 1)
2364 {
2365 // Mark as boss
2366 boss->grp->boss = EINA_TRUE;
2367 boss->grp->in = EINA_TRUE;
2368 sum_x = (sum_x + bx) / (cnt + 1);
2369 sum_y = (sum_y + by) / (cnt + 1);
2370 grp_membs = eina_list_append(grp_membs, boss);
2371 _overlay_group_coord_member_update(boss->grp, sum_x, sum_y, grp_membs);
2372 }
2373}
2374
2375static void
2376_overlay_show(Elm_Map_Overlay *overlay)
2377{
2378 Widget_Data *wd = overlay->wd;
2379 Eina_Bool hide = EINA_FALSE;
2380
2381 if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS) return;
2382
2383 if (overlay->paused) return;
2384 if ((overlay->grp->clas) && (overlay->grp->clas->paused)) return;
2385
2386 if (((overlay->grp->in) || (overlay->hide) ||
2387 (overlay->zoom_min > wd->zoom)))
2388 hide = EINA_TRUE;
2389 if ((overlay->grp->clas) && ((overlay->grp->clas->hide) ||
2390 (overlay->grp->clas->zoom_min > wd->zoom)))
2391 hide = EINA_TRUE;
2392
2393 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2394 {
2395 if (hide) _overlay_default_hide(overlay->ovl);
2396 else _overlay_default_show(overlay->ovl);
2397 }
2398 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2399 {
2400 if (hide) _overlay_bubble_hide(overlay->ovl);
2401 else _overlay_bubble_show(overlay->ovl);
2402 }
2403 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
2404 {
2405 if (hide) _overlay_route_hide(overlay->ovl);
2406 else _overlay_route_show(overlay->ovl);
2407 }
2408 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_LINE)
2409 {
2410 if (hide) _overlay_line_hide(overlay->ovl);
2411 else _overlay_line_show(overlay->ovl);
2412 }
2413 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_POLYGON)
2414 {
2415 if (hide) _overlay_polygon_hide(overlay->ovl);
2416 else _overlay_polygon_show(overlay->ovl);
2417 }
2418 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CIRCLE)
2419 {
2420 if (hide) _overlay_circle_hide(overlay->ovl);
2421 else _overlay_circle_show(overlay->ovl);
2422 }
2423 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_SCALE)
2424 {
2425 if (hide) _overlay_scale_hide(overlay->ovl);
2426 else _overlay_scale_show(overlay->ovl);
2427 }
2428}
2429
2430static void
2431_overlay_place(Widget_Data *wd)
2432{
2433 EINA_SAFETY_ON_NULL_RETURN(wd);
2434
2435 Eina_List *l, *ll;
2436 Elm_Map_Overlay *overlay;
2437
2438 // Reset group & Update overlays coord
2439 EINA_LIST_FOREACH(wd->overlays, l, overlay)
2440 {
2441 if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2442 overlay->grp->in = EINA_FALSE;
2443 overlay->grp->boss = EINA_FALSE;
2444
2445 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2446 _overlay_default_coord_update(overlay->ovl);
2447 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
2448 _overlay_bubble_coord_update(overlay->ovl);
2449 }
2450
2451 // Classify into group boss or follwer
2452 EINA_LIST_FOREACH(wd->overlays, l, overlay)
2453 {
2454 Elm_Map_Overlay *boss;
2455 Overlay_Class *clas;
2456
2457 if (overlay->type != ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2458 if (overlay->hide || (overlay->zoom_min > wd->zoom)) continue;
2459
2460 clas = overlay->ovl;
2461 if (clas->zoom_max < wd->zoom) continue;
2462 EINA_LIST_FOREACH(clas->members, ll, boss)
2463 {
2464 if (boss->type == ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2465 if (boss->hide || (boss->zoom_min > wd->zoom)) continue;
2466 if (boss->grp->in) continue;
2467 _overlay_grouping(clas->members, boss);
2468 }
2469 }
2470
2471 // Place overlays
2472 EINA_LIST_FOREACH(wd->overlays, l, overlay) _overlay_show(overlay);
2473
2474 // Place group overlays on top of overlays
2475 EINA_LIST_FOREACH(wd->overlays, l, overlay)
2476 {
2477 if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS) continue;
2478 if (overlay->grp->boss) _overlay_group_show(overlay->grp);
2479 else _overlay_group_hide(overlay->grp);
2480 }
2481}
2482
2483static Evas_Object *
2484_overlay_obj_get(const Elm_Map_Overlay *overlay)
2485{
2486 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
2487 if (overlay->type == ELM_MAP_OVERLAY_TYPE_GROUP)
2488 {
2489 Overlay_Group *ovl = overlay->ovl;
2490 Overlay_Default *df = ovl->ovl;
2491 return df->layout;
2492 }
2493 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
2494 {
2495 Overlay_Default *ovl = overlay->ovl;
2496 return ovl->layout;
2497 }
2498 else
2499 {
2500 ERR("Not supported overlay type: %d", overlay->type);
2501 return NULL;
2502 }
2503}
2504
2505static void
2506_overlays_show(void *data)
2507{
2508 EINA_SAFETY_ON_NULL_RETURN(data);
2509 Delayed_Data *dd = data;
2510
2511 int zoom, zoom_max;
2512 double max_lon, min_lon, max_lat, min_lat;
2513 Evas_Coord vw, vh;
2514
2515 _region_max_min_get(dd->overlays, &max_lon, &min_lon, &max_lat, &min_lat);
2516 dd->lon = (max_lon + min_lon) / 2;
2517 dd->lat = (max_lat + min_lat) / 2;
2518
2519 zoom = dd->wd->src_tile->zoom_min;
2520 _viewport_coord_get(dd->wd, NULL, NULL, &vw, &vh);
2521 if (dd->wd->src_tile->zoom_max < dd->wd->zoom_max)
2522 zoom_max = dd->wd->src_tile->zoom_max;
2523 else zoom_max = dd->wd->zoom_max;
2524 while (zoom <= zoom_max)
2525 {
2526 Evas_Coord size, max_x, max_y, min_x, min_y;
2527 size = pow(2.0, zoom) * dd->wd->tsize;
2528 _region_to_coord_convert(dd->wd, min_lon, max_lat, size, &min_x, &max_y);
2529 _region_to_coord_convert(dd->wd, max_lon, min_lat, size, &max_x, &min_y);
2530 if ((max_x - min_x) > vw || (max_y - min_y) > vh) break;
2531 zoom++;
2532 }
2533 zoom--;
2534
2535 zoom_do(dd->wd, zoom);
2536 _region_show(dd);
2537 evas_object_smart_changed(dd->wd->pan_smart);
2538}
2539
2540static void
2541_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
2542{
2543 Pan *sd = evas_object_smart_data_get(obj);
2544 EINA_SAFETY_ON_NULL_RETURN(sd);
2545 if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
2546
2547 sd->wd->pan_x = x;
2548 sd->wd->pan_y = y;
2549 evas_object_smart_changed(obj);
2550}
2551
2552static void
2553_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
2554{
2555 Pan *sd = evas_object_smart_data_get(obj);
2556 EINA_SAFETY_ON_NULL_RETURN(sd);
2557 if (x) *x = sd->wd->pan_x;
2558 if (y) *y = sd->wd->pan_y;
2559}
2560
2561static void
2562_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
2563{
2564 Pan *sd = evas_object_smart_data_get(obj);
2565 EINA_SAFETY_ON_NULL_RETURN(sd);
2566 Evas_Coord ow, oh;
2567 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
2568 ow = sd->wd->size.w - ow;
2569 oh = sd->wd->size.h - oh;
2570 if (ow < 0) ow = 0;
2571 if (oh < 0) oh = 0;
2572 if (x) *x = ow;
2573 if (y) *y = oh;
2574}
2575
2576static void
2577_pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
2578{
2579 if (x) *x = 0;
2580 if (y) *y = 0;
2581}
2582
2583static void
2584_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
2585{
2586 Pan *sd = evas_object_smart_data_get(obj);
2587 EINA_SAFETY_ON_NULL_RETURN(sd);
2588 if (w) *w = sd->wd->size.w;
2589 if (h) *h = sd->wd->size.h;
2590}
2591
2592static void
2593_pan_add(Evas_Object *obj)
2594{
2595 Pan *sd;
2596 Evas_Object_Smart_Clipped_Data *cd;
2597 parent_sc.add(obj);
2598 cd = evas_object_smart_data_get(obj);
2599 EINA_SAFETY_ON_NULL_RETURN(cd);
2600 sd = ELM_NEW(Pan);
2601 sd->__clipped_data = *cd;
2602 free(cd);
2603 evas_object_smart_data_set(obj, sd);
2604}
2605
2606static void
2607_pan_resize(Evas_Object *obj, Evas_Coord w __UNUSED__, Evas_Coord h __UNUSED__)
2608{
2609 Pan *sd = evas_object_smart_data_get(obj);
2610 EINA_SAFETY_ON_NULL_RETURN(sd);
2611
2612 _sizing_eval(sd->wd);
2613 elm_map_zoom_mode_set(sd->wd->obj, sd->wd->mode);
2614 evas_object_smart_changed(obj);
2615}
2616
2617static void
2618_pan_calculate(Evas_Object *obj)
2619{
2620 Pan *sd = evas_object_smart_data_get(obj);
2621 EINA_SAFETY_ON_NULL_RETURN(sd);
2622
2623 Evas_Coord w, h;
2624 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2625 if (w <= 0 || h <= 0) return;
2626
2627 _grid_place(sd->wd);
2628 _overlay_place(sd->wd);
2629 _track_place(sd->wd);
2630 _delayed_do(sd->wd);
2631}
2632
2633static void
2634_pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
2635{
2636 EINA_SAFETY_ON_NULL_RETURN(obj);
2637 evas_object_smart_changed(obj);
2638}
2639
2640static void
2641_hold_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2642{
2643 EINA_SAFETY_ON_NULL_RETURN(data);
2644 Widget_Data *wd = data;
2645 elm_smart_scroller_hold_set(wd->scr, 1);
2646}
2647
2648static void
2649_hold_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2650{
2651 EINA_SAFETY_ON_NULL_RETURN(data);
2652 Widget_Data *wd = data;
2653 elm_smart_scroller_hold_set(wd->scr, 0);
2654}
2655
2656static void
2657_freeze_on(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2658{
2659 EINA_SAFETY_ON_NULL_RETURN(data);
2660 Widget_Data *wd = data;
2661 elm_smart_scroller_freeze_set(wd->scr, 1);
2662}
2663
2664static void
2665_freeze_off(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
2666{
2667 EINA_SAFETY_ON_NULL_RETURN(data);
2668 Widget_Data *wd = data;
2669 elm_smart_scroller_freeze_set(wd->scr, 0);
2670}
2671
2672static Eina_Bool
2673cb_dump_name_attrs(void *data, const char *key, const char *value)
2674{
2675 Name_Dump *dump = (Name_Dump*)data;
2676 if (!dump) return EINA_FALSE;
2677
2678 if (!strncmp(key, NOMINATIM_ATTR_LON, sizeof(NOMINATIM_ATTR_LON))) dump->lon = atof(value);
2679 else if (!strncmp(key, NOMINATIM_ATTR_LAT, sizeof(NOMINATIM_ATTR_LAT))) dump->lat = atof(value);
2680
2681 return EINA_TRUE;
2682}
2683
2684static Eina_Bool
2685cb_route_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length)
2686{
2687 Route_Dump *dump = data;
2688 if (!dump) return EINA_FALSE;
2689
2690 switch (type)
2691 {
2692 case EINA_SIMPLE_XML_OPEN:
2693 case EINA_SIMPLE_XML_OPEN_EMPTY:
2694 {
2695 const char *attrs;
2696
2697 attrs = eina_simple_xml_tag_attributes_find(value, length);
2698 if (!attrs)
2699 {
2700 if (!strncmp(value, YOURS_DISTANCE, length)) dump->id = ROUTE_XML_DISTANCE;
2701 else if (!strncmp(value, YOURS_DESCRIPTION, length)) dump->id = ROUTE_XML_DESCRIPTION;
2702 else if (!strncmp(value, YOURS_COORDINATES, length)) dump->id = ROUTE_XML_COORDINATES;
2703 else dump->id = ROUTE_XML_NONE;
2704 }
2705 }
2706 break;
2707 case EINA_SIMPLE_XML_DATA:
2708 {
2709 char *buf = malloc(length);
2710 if (!buf) return EINA_FALSE;
2711 snprintf(buf, length, "%s", value);
2712 if (dump->id == ROUTE_XML_DISTANCE) dump->distance = atof(buf);
2713 else if (!(dump->description) && (dump->id == ROUTE_XML_DESCRIPTION)) dump->description = strdup(buf);
2714 else if (dump->id == ROUTE_XML_COORDINATES) dump->coordinates = strdup(buf);
2715 free(buf);
2716 }
2717 break;
2718 default:
2719 break;
2720 }
2721
2722 return EINA_TRUE;
2723}
2724
2725static Eina_Bool
2726cb_name_dump(void *data, Eina_Simple_XML_Type type, const char *value, unsigned offset __UNUSED__, unsigned length)
2727{
2728 Name_Dump *dump = data;
2729 if (!dump) return EINA_FALSE;
2730
2731 switch (type)
2732 {
2733 case EINA_SIMPLE_XML_OPEN:
2734 case EINA_SIMPLE_XML_OPEN_EMPTY:
2735 {
2736 const char *attrs;
2737 attrs = eina_simple_xml_tag_attributes_find(value, length);
2738 if (attrs)
2739 {
2740 if (!strncmp(value, NOMINATIM_RESULT, sizeof(NOMINATIM_RESULT) - 1)) dump->id = NAME_XML_NAME;
2741 else dump->id = NAME_XML_NONE;
2742
2743 eina_simple_xml_attributes_parse
2744 (attrs, length - (attrs - value), cb_dump_name_attrs, dump);
2745 }
2746 }
2747 break;
2748 case EINA_SIMPLE_XML_DATA:
2749 {
2750 char *buf = malloc(length + 1);
2751 if (!buf) return EINA_FALSE;
2752 snprintf(buf, length + 1, "%s", value);
2753 if (dump->id == NAME_XML_NAME) dump->address = strdup(buf);
2754 free(buf);
2755 }
2756 break;
2757 default:
2758 break;
2759 }
2760
2761 return EINA_TRUE;
2762}
2763
2764static void
2765_kml_parse(Elm_Map_Route *r)
2766{
2767 EINA_SAFETY_ON_NULL_RETURN(r);
2768 EINA_SAFETY_ON_NULL_RETURN(r->fname);
2769
2770 FILE *f;
2771 char **str;
2772 unsigned int ele, idx;
2773 double lon, lat;
2774
2775 Route_Dump dump = {0, r->fname, 0.0, NULL, NULL};
2776
2777 f = fopen(r->fname, "rb");
2778 if (f)
2779 {
2780 long sz;
2781
2782 fseek(f, 0, SEEK_END);
2783 sz = ftell(f);
2784 if (sz > 0)
2785 {
2786 char *buf;
2787
2788 fseek(f, 0, SEEK_SET);
2789 buf = malloc(sz);
2790 if (buf)
2791 {
2792 if (fread(buf, 1, sz, f))
2793 {
2794 eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_route_dump,
2795 &dump);
2796 free(buf);
2797 }
2798 }
2799 }
2800 fclose(f);
2801
2802 if (dump.distance) r->info.distance = dump.distance;
2803 if (dump.description)
2804 {
2805 eina_stringshare_replace(&r->info.waypoints, dump.description);
2806 str = eina_str_split_full(dump.description, "\n", 0, &ele);
2807 r->info.waypoint_count = ele;
2808 for (idx = 0; idx < ele; idx++)
2809 {
2810 Path_Waypoint *wp = ELM_NEW(Path_Waypoint);
2811 if (wp)
2812 {
2813 wp->wd = r->wd;
2814 wp->point = eina_stringshare_add(str[idx]);
2815 DBG("%s", str[idx]);
2816 r->waypoint = eina_list_append(r->waypoint, wp);
2817 }
2818 }
2819 if (str && str[0])
2820 {
2821 free(str[0]);
2822 free(str);
2823 }
2824 }
2825 else WRN("description is not found !");
2826
2827 if (dump.coordinates)
2828 {
2829 eina_stringshare_replace(&r->info.nodes, dump.coordinates);
2830 str = eina_str_split_full(dump.coordinates, "\n", 0, &ele);
2831 r->info.node_count = ele;
2832 for (idx = 0; idx < ele; idx++)
2833 {
2834 sscanf(str[idx], "%lf,%lf", &lon, &lat);
2835 Path_Node *n = ELM_NEW(Path_Node);
2836 if (n)
2837 {
2838 n->wd = r->wd;
2839 n->pos.lon = lon;
2840 n->pos.lat = lat;
2841 n->idx = idx;
2842 DBG("%lf:%lf", lon, lat);
2843 n->pos.address = NULL;
2844 r->nodes = eina_list_append(r->nodes, n);
2845 }
2846 }
2847 if (str && str[0])
2848 {
2849 free(str[0]);
2850 free(str);
2851 }
2852 }
2853 }
2854}
2855
2856static void
2857_name_parse(Elm_Map_Name *n)
2858{
2859 EINA_SAFETY_ON_NULL_RETURN(n);
2860 EINA_SAFETY_ON_NULL_RETURN(n->fname);
2861
2862 FILE *f;
2863
2864 Name_Dump dump = {0, NULL, 0.0, 0.0};
2865
2866 f = fopen(n->fname, "rb");
2867 if (f)
2868 {
2869 long sz;
2870
2871 fseek(f, 0, SEEK_END);
2872 sz = ftell(f);
2873 if (sz > 0)
2874 {
2875 char *buf;
2876
2877 fseek(f, 0, SEEK_SET);
2878 buf = malloc(sz);
2879 if (buf)
2880 {
2881 if (fread(buf, 1, sz, f))
2882 {
2883 eina_simple_xml_parse(buf, sz, EINA_TRUE, cb_name_dump, &dump);
2884 free(buf);
2885 }
2886 }
2887 }
2888 fclose(f);
2889
2890 if (dump.address)
2891 {
2892 INF("[%lf : %lf] ADDRESS : %s", n->lon, n->lat, dump.address);
2893 n->address = strdup(dump.address);
2894 }
2895 n->lon = dump.lon;
2896 n->lat = dump.lat;
2897 }
2898}
2899
2900Grid *_get_current_grid(Widget_Data *wd)
2901{
2902 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2903 Eina_List *l;
2904 Grid *g = NULL, *ret = NULL;
2905 EINA_LIST_FOREACH(wd->grids, l, g)
2906 {
2907 if (wd->zoom == g->zoom)
2908 {
2909 ret = g;
2910 break;
2911 }
2912 }
2913 return ret;
2914}
2915
2916static void
2917_route_cb(void *data, const char *file, int status)
2918{
2919 EINA_SAFETY_ON_NULL_RETURN(data);
2920 EINA_SAFETY_ON_NULL_RETURN(file);
2921
2922 Elm_Map_Route *route = data;
2923 Widget_Data *wd = route->wd;
2924 EINA_SAFETY_ON_NULL_RETURN(wd);
2925
2926 route->job = NULL;
2927 if (status == 200)
2928 {
2929 _kml_parse(route);
2930 INF("Route request success from (%lf, %lf) to (%lf, %lf)",
2931 route->flon, route->flat, route->tlon, route->tlat);
2932 if (route->cb) route->cb(route->data, wd->obj, route);
2933 evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOADED, NULL);
2934 }
2935 else
2936 {
2937 ERR("Route request failed: %d", status);
2938 if (route->cb) route->cb(route->data, wd->obj, NULL);
2939 evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOADED_FAIL, NULL);
2940 }
2941
2942 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
2943 "elm,state,busy,stop", "elm");
2944}
2945
2946static void
2947_name_cb(void *data, const char *file, int status)
2948{
2949 EINA_SAFETY_ON_NULL_RETURN(data);
2950 EINA_SAFETY_ON_NULL_RETURN(file);
2951
2952 Elm_Map_Name *name = data;
2953 Widget_Data *wd = name->wd;
2954 EINA_SAFETY_ON_NULL_RETURN(wd);
2955
2956 name->job = NULL;
2957 if (status == 200)
2958 {
2959 _name_parse(name);
2960 INF("Name request success address:%s, lon:%lf, lat:%lf",
2961 name->address, name->lon, name->lat);
2962 if (name->cb) name->cb(name->data, wd->obj, name);
2963 evas_object_smart_callback_call(wd->obj, SIG_NAME_LOADED, NULL);
2964 }
2965 else
2966 {
2967 ERR("Name request failed: %d", status);
2968 if (name->cb) name->cb(name->data, wd->obj, NULL);
2969 evas_object_smart_callback_call(wd->obj, SIG_NAME_LOADED_FAIL, NULL);
2970 }
2971 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
2972 "elm,state,busy,stop", "elm");
2973}
2974
2975
2976
2977static Elm_Map_Name *
2978_name_request(const Evas_Object *obj, int method, const char *address, double lon, double lat, Elm_Map_Name_Cb name_cb, void *data)
2979{
2980 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2981 Widget_Data *wd = elm_widget_data_get(obj);
2982 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
2983 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src_name, NULL);
2984
2985
2986 char *url;
2987 char fname[PATH_MAX];
2988
2989 if (!ecore_file_exists(CACHE_NAME_ROOT)) ecore_file_mkpath(CACHE_NAME_ROOT);
2990
2991 url = wd->src_name->url_cb(wd->obj, method, address, lon, lat);
2992 if (!url)
2993 {
2994 ERR("Name URL is NULL");
2995 return NULL;
2996 }
2997
2998 Elm_Map_Name *name = ELM_NEW(Elm_Map_Name);
2999 name->wd = wd;
3000 snprintf(fname, sizeof(fname), CACHE_NAME_ROOT"/%d", rand());
3001 name->fname = strdup(fname);
3002 name->method = method;
3003 if (method == ELM_MAP_NAME_METHOD_SEARCH) name->address = strdup(address);
3004 else if (method == ELM_MAP_NAME_METHOD_REVERSE)
3005 {
3006 name->lon = lon;
3007 name->lat = lat;
3008 }
3009 name->cb = name_cb;
3010 name->data = data;
3011
3012 if (!ecore_file_download_full(url, name->fname, _name_cb, NULL, name,
3013 &(name->job), wd->ua) || !(name->job))
3014 {
3015 ERR("Can't request Name from %s to %s", url, name->fname);
3016 if (name->address) free(name->address);
3017 free(name->fname);
3018 free(name);
3019 return NULL;
3020 }
3021 INF("Name requested from %s to %s", url, name->fname);
3022 free(url);
3023
3024 wd->names = eina_list_append(wd->names, name);
3025 evas_object_smart_callback_call(wd->obj, SIG_NAME_LOAD, name);
3026 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
3027 "elm,state,busy,start", "elm");
3028 return name;
3029}
3030
3031static Evas_Event_Flags
3032_pinch_zoom_start_cb(void *data, void *event_info __UNUSED__)
3033{
3034 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EVAS_EVENT_FLAG_NONE);
3035 Widget_Data *wd = data;
3036
3037 wd->pinch_zoom = wd->zoom_detail;
3038 return EVAS_EVENT_FLAG_NONE;
3039}
3040
3041static Evas_Event_Flags
3042_pinch_zoom_cb(void *data, void *event_info)
3043{
3044 Widget_Data *wd = data;
3045 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE);
3046
3047 if (!wd->paused)
3048 {
3049 Elm_Gesture_Zoom_Info *ei = event_info;
3050 zoom_do(wd, wd->pinch_zoom + ei->zoom - 1);
3051 }
3052 return EVAS_EVENT_FLAG_NONE;
3053}
3054
3055static Evas_Event_Flags
3056_pinch_rotate_cb(void *data, void *event_info)
3057{
3058 Widget_Data *wd = data;
3059 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE);
3060
3061 if (!wd->paused)
3062 {
3063 int x, y, w, h;
3064 Elm_Gesture_Rotate_Info *ei = event_info;
3065 evas_object_geometry_get(wd->obj, &x, &y, &w, &h);
3066
3067 wd->rotate.d = wd->rotate.a + ei->angle - ei->base_angle;
3068 wd->rotate.cx = x + ((double)w * 0.5);
3069 wd->rotate.cy = y + ((double)h * 0.5);
3070
3071 evas_object_smart_changed(wd->pan_smart);
3072 }
3073 return EVAS_EVENT_FLAG_NONE;
3074}
3075
3076static Evas_Event_Flags
3077_pinch_rotate_end_cb(void *data, void *event_info __UNUSED__)
3078{
3079 Widget_Data *wd = data;
3080 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EVAS_EVENT_FLAG_NONE);
3081
3082 wd->rotate.a = wd->rotate.d;
3083
3084 return EVAS_EVENT_FLAG_NONE;
3085}
3086
3087static Eina_Bool
3088_source_tile_mod_cb(Eina_Module *m, void *data)
3089{
3090 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
3091
3092 Widget_Data *wd = data;
3093 Source_Tile *s;
3094 Elm_Map_Module_Source_Name_Func name_cb;
3095 Elm_Map_Module_Tile_Zoom_Min_Func zoom_min;
3096 Elm_Map_Module_Tile_Zoom_Max_Func zoom_max;
3097 Elm_Map_Module_Tile_Url_Func url_cb;
3098 Elm_Map_Module_Tile_Geo_to_Coord_Func geo_to_coord;
3099 Elm_Map_Module_Tile_Coord_to_Geo_Func coord_to_geo;
3100 Elm_Map_Module_Tile_Scale_Func scale_cb;
3101 const char *file;
3102
3103 file = eina_module_file_get(m);
3104 if (!eina_module_load(m))
3105 {
3106 ERR("Could not load module \"%s\": %s", file,
3107 eina_error_msg_get(eina_error_get()));
3108 return EINA_FALSE;
3109 }
3110
3111 name_cb = eina_module_symbol_get(m, "map_module_source_name_get");
3112 zoom_min = eina_module_symbol_get(m, "map_module_tile_zoom_min_get");
3113 zoom_max = eina_module_symbol_get(m, "map_module_tile_zoom_max_get");
3114 url_cb = eina_module_symbol_get(m, "map_module_tile_url_get");
3115 geo_to_coord = eina_module_symbol_get(m, "map_module_tile_geo_to_coord");
3116 coord_to_geo = eina_module_symbol_get(m, "map_module_tile_coord_to_geo");
3117 scale_cb = eina_module_symbol_get(m, "map_module_tile_scale_get");
3118 if ((!name_cb) || (!zoom_min) || (!zoom_max) || (!url_cb) ||
3119 (!geo_to_coord) || (!coord_to_geo) || (!scale_cb))
3120 {
3121 WRN("Could not find map module functions from module \"%s\": %s",
3122 file, eina_error_msg_get(eina_error_get()));
3123 eina_module_unload(m);
3124 return EINA_FALSE;
3125 }
3126 s = ELM_NEW(Source_Tile);
3127 s->name = name_cb();
3128 s->zoom_min = zoom_min();
3129 s->zoom_max = zoom_max();
3130 s->url_cb = url_cb;
3131 s->geo_to_coord = geo_to_coord;
3132 s->coord_to_geo = coord_to_geo;
3133 s->scale_cb = scale_cb;
3134 wd->src_tiles = eina_list_append(wd->src_tiles, s);
3135
3136 return EINA_TRUE;
3137}
3138
3139static void
3140_source_tile_load(Widget_Data *wd)
3141{
3142 unsigned int idx;
3143 Eina_List *l;
3144 Source_Tile *s;
3145
3146 // Load from hard coded data
3147 for (idx = 0; idx < (sizeof(src_tiles) / sizeof(Source_Tile)); idx++)
3148 {
3149 s= ELM_NEW(Source_Tile);
3150 s->name = src_tiles[idx].name;
3151 s->zoom_min = src_tiles[idx].zoom_min;
3152 s->zoom_max = src_tiles[idx].zoom_max;
3153 s->url_cb = src_tiles[idx].url_cb;
3154 s->geo_to_coord = src_tiles[idx].geo_to_coord;
3155 s->coord_to_geo = src_tiles[idx].coord_to_geo;
3156 s->scale_cb = src_tiles[idx].scale_cb;
3157 wd->src_tiles = eina_list_append(wd->src_tiles, s);
3158 }
3159
3160 // Load from modules
3161 wd->src_tile_mods = eina_module_list_get(wd->src_tile_mods, MODULES_PATH, 1,
3162 &_source_tile_mod_cb, wd);
3163
3164 // Set default source
3165 wd->src_tile = eina_list_nth(wd->src_tiles, 0);
3166
3167 // Make name strings
3168 idx = 0;
3169 wd->src_tile_names = calloc((eina_list_count(wd->src_tiles) + 1),
3170 sizeof(char *));
3171 EINA_LIST_FOREACH(wd->src_tiles, l, s)
3172 {
3173 eina_stringshare_replace(&wd->src_tile_names[idx], s->name);
3174 INF("source : %s", wd->src_tile_names[idx]);
3175 idx++;
3176 }
3177}
3178
3179static void
3180_source_tile_unload(Widget_Data *wd)
3181{
3182 int idx = 0;
3183 Source_Tile *s;
3184
3185 for (idx = 0; wd->src_tile_names[idx]; idx++)
3186 eina_stringshare_del(wd->src_tile_names[idx]);
3187 EINA_LIST_FREE(wd->src_tiles, s) free(s);
3188 eina_module_list_free(wd->src_tile_mods);
3189}
3190
3191static void
3192_source_tile_set(Widget_Data *wd, const char *source_name)
3193{
3194 EINA_SAFETY_ON_NULL_RETURN(wd);
3195 EINA_SAFETY_ON_NULL_RETURN(source_name);
3196 Source_Tile *s;
3197 Eina_List *l;
3198
3199 if (wd->src_tile && !strcmp(wd->src_tile->name, source_name)) return;
3200
3201 EINA_LIST_FOREACH(wd->src_tiles, l, s)
3202 {
3203 if (!strcmp(s->name, source_name))
3204 {
3205 wd->src_tile = s;
3206 break;
3207 }
3208 }
3209 if (!wd->src_tile)
3210 {
3211 ERR("source name (%s) is not found", source_name);
3212 return;
3213 }
3214
3215 if (wd->src_tile->zoom_max < wd->zoom)
3216 wd->zoom = wd->src_tile->zoom_max;
3217 else if (wd->src_tile->zoom_min > wd->zoom)
3218 wd->zoom = wd->src_tile->zoom_min;
3219
3220 if (wd->src_tile->zoom_max < wd->zoom_max)
3221 wd->zoom_max = wd->src_tile->zoom_max;
3222 if (wd->src_tile->zoom_min > wd->zoom_min)
3223 wd->zoom_min = wd->src_tile->zoom_min;
3224
3225 _grid_all_clear(wd);
3226 _grid_all_create(wd);
3227 zoom_do(wd, wd->zoom);
3228}
3229
3230static Eina_Bool
3231_source_route_mod_cb(Eina_Module *m, void *data)
3232{
3233 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
3234
3235 Widget_Data *wd = data;
3236 Source_Route *s;
3237 Elm_Map_Module_Source_Name_Func name_cb;
3238 Elm_Map_Module_Route_Url_Func url_cb;
3239 const char *file;
3240
3241 file = eina_module_file_get(m);
3242 if (!eina_module_load(m))
3243 {
3244 ERR("Could not load module \"%s\": %s", file,
3245 eina_error_msg_get(eina_error_get()));
3246 return EINA_FALSE;
3247 }
3248
3249 name_cb = eina_module_symbol_get(m, "map_module_source_name_get");
3250 url_cb = eina_module_symbol_get(m, "map_module_route_url_get");
3251
3252 if ((!name_cb) || (!url_cb))
3253 {
3254 WRN("Could not find map module functions from module \"%s\": %s",
3255 file, eina_error_msg_get(eina_error_get()));
3256 eina_module_unload(m);
3257 return EINA_FALSE;
3258 }
3259 s = ELM_NEW(Source_Tile);
3260 s->name = name_cb();
3261 s->url_cb = url_cb;
3262 wd->src_routes = eina_list_append(wd->src_routes, s);
3263
3264 eina_module_unload(m);
3265 return EINA_TRUE;
3266}
3267
3268static void
3269_source_route_load(Widget_Data *wd)
3270{
3271 unsigned int idx;
3272 Eina_List *l;
3273 Source_Route *s;
3274
3275 // Load from hard coded data
3276 for (idx = 0; idx < (sizeof(src_routes) / sizeof(Source_Route)); idx++)
3277 {
3278 s= ELM_NEW(Source_Route);
3279 s->name = src_routes[idx].name;
3280 s->url_cb = src_routes[idx].url_cb;
3281 wd->src_routes = eina_list_append(wd->src_routes, s);
3282 }
3283
3284 // Load from modules
3285 wd->src_route_mods = eina_module_list_get(wd->src_route_mods, MODULES_PATH,
3286 1, &_source_route_mod_cb, wd);
3287
3288 // Set default source
3289 wd->src_route = eina_list_nth(wd->src_routes, 0);
3290
3291 // Make name strings
3292 idx = 0;
3293 wd->src_route_names = calloc((eina_list_count(wd->src_routes) + 1),
3294 sizeof(char *));
3295 EINA_LIST_FOREACH(wd->src_routes, l, s)
3296 {
3297 eina_stringshare_replace(&wd->src_route_names[idx], s->name);
3298 INF("source : %s", wd->src_route_names[idx]);
3299 idx++;
3300 }
3301}
3302
3303static void
3304_source_route_unload(Widget_Data *wd)
3305{
3306 int idx = 0;
3307 Source_Route *s;
3308
3309 for (idx = 0; wd->src_route_names[idx]; idx++)
3310 eina_stringshare_del(wd->src_route_names[idx]);
3311 EINA_LIST_FREE(wd->src_routes, s) free(s);
3312 eina_module_list_free(wd->src_route_mods);
3313}
3314
3315static void
3316_source_route_set(Widget_Data *wd, const char *source_name)
3317{
3318 EINA_SAFETY_ON_NULL_RETURN(wd);
3319 EINA_SAFETY_ON_NULL_RETURN(source_name);
3320 Source_Route *s;
3321 Eina_List *l;
3322
3323 if (wd->src_route && !strcmp(wd->src_route->name, source_name)) return;
3324
3325 EINA_LIST_FOREACH(wd->src_routes, l, s)
3326 {
3327 if (!strcmp(s->name, source_name))
3328 {
3329 wd->src_route = s;
3330 break;
3331 }
3332 }
3333 if (!wd->src_route)
3334 {
3335 ERR("source name (%s) is not found", source_name);
3336 return;
3337 }
3338}
3339
3340static Eina_Bool
3341_source_name_mod_cb(Eina_Module *m, void *data)
3342{
3343 EINA_SAFETY_ON_NULL_RETURN_VAL(data, EINA_FALSE);
3344
3345 Widget_Data *wd = data;
3346 Source_Name *s;
3347 Elm_Map_Module_Source_Name_Func name_cb;
3348 Elm_Map_Module_Name_Url_Func url_cb;
3349 const char *file;
3350
3351 file = eina_module_file_get(m);
3352 if (!eina_module_load(m))
3353 {
3354 ERR("Could not load module \"%s\": %s", file,
3355 eina_error_msg_get(eina_error_get()));
3356 return EINA_FALSE;
3357 }
3358
3359 name_cb = eina_module_symbol_get(m, "map_module_source_name_get");
3360 url_cb = eina_module_symbol_get(m, "map_module_name_url_get");
3361
3362 if ((!name_cb) || (!url_cb))
3363 {
3364 WRN("Could not find map module functions from module \"%s\": %s",
3365 file, eina_error_msg_get(eina_error_get()));
3366 eina_module_unload(m);
3367 return EINA_FALSE;
3368 }
3369 s = ELM_NEW(Source_Tile);
3370 s->name = name_cb();
3371 s->url_cb = url_cb;
3372 wd->src_names = eina_list_append(wd->src_names, s);
3373
3374 eina_module_unload(m);
3375 return EINA_TRUE;
3376}
3377
3378static void
3379_source_name_load(Widget_Data *wd)
3380{
3381 unsigned int idx;
3382 Eina_List *l;
3383 Source_Name *s;
3384
3385 // Load from hard coded data
3386 for (idx = 0; idx < (sizeof(src_names) / sizeof(Source_Name)); idx++)
3387 {
3388 s= ELM_NEW(Source_Name);
3389 s->name = src_names[idx].name;
3390 s->url_cb = src_names[idx].url_cb;
3391 wd->src_names = eina_list_append(wd->src_names, s);
3392 }
3393
3394 // Load from modules
3395 wd->src_name_mods = eina_module_list_get(wd->src_name_mods, MODULES_PATH, 1,
3396 &_source_name_mod_cb, wd);
3397
3398 // Set default source
3399 wd->src_name = eina_list_nth(wd->src_names, 0);
3400
3401 // Make name strings
3402 idx = 0;
3403 wd->src_name_names = calloc((eina_list_count(wd->src_names) + 1),
3404 sizeof(char *));
3405 EINA_LIST_FOREACH(wd->src_names, l, s)
3406 {
3407 eina_stringshare_replace(&wd->src_name_names[idx], s->name);
3408 INF("source : %s", wd->src_name_names[idx]);
3409 idx++;
3410 }
3411}
3412
3413static void
3414_source_name_unload(Widget_Data *wd)
3415{
3416 int idx = 0;
3417 Source_Name *s;
3418
3419 for (idx = 0; wd->src_name_names[idx]; idx++)
3420 eina_stringshare_del(wd->src_name_names[idx]);
3421 EINA_LIST_FREE(wd->src_names, s) free(s);
3422 eina_module_list_free(wd->src_name_mods);
3423}
3424
3425static void
3426_source_name_set(Widget_Data *wd, const char *source_name)
3427{
3428 EINA_SAFETY_ON_NULL_RETURN(wd);
3429 EINA_SAFETY_ON_NULL_RETURN(source_name);
3430
3431 Source_Name *s;
3432 Eina_List *l;
3433
3434 if (wd->src_name && !strcmp(wd->src_name->name, source_name)) return;
3435
3436 EINA_LIST_FOREACH(wd->src_names, l, s)
3437 {
3438 if (!strcmp(s->name, source_name))
3439 {
3440 wd->src_name = s;
3441 break;
3442 }
3443 }
3444 if (!wd->src_name)
3445 {
3446 ERR("source name (%s) is not found", source_name);
3447 return;
3448 }
3449}
3450
3451static void
3452_source_all_load(Widget_Data *wd)
3453{
3454 EINA_SAFETY_ON_NULL_RETURN(wd);
3455 _source_tile_load(wd);
3456 _source_route_load(wd);
3457 _source_name_load(wd);
3458}
3459
3460static void
3461_source_all_unload(Widget_Data *wd)
3462{
3463 EINA_SAFETY_ON_NULL_RETURN(wd);
3464 _source_tile_unload(wd);
3465 _source_route_unload(wd);
3466 _source_name_unload(wd);
3467}
3468
3469static void
3470_zoom_mode_set(void *data)
3471{
3472 EINA_SAFETY_ON_NULL_RETURN(data);
3473 Delayed_Data *dd = data;
3474
3475 dd->wd->mode = dd->mode;
3476 if (dd->mode != ELM_MAP_ZOOM_MODE_MANUAL)
3477 {
3478 Evas_Coord w, h;
3479 Evas_Coord vw, vh;
3480
3481 double zoom;
3482 double diff;
3483
3484 w = dd->wd->size.w;
3485 h = dd->wd->size.h;
3486 zoom = dd->wd->zoom_detail;
3487 _viewport_coord_get(dd->wd, NULL, NULL, &vw, &vh);
3488
3489 if (dd->mode == ELM_MAP_ZOOM_MODE_AUTO_FIT)
3490 {
3491 if ((w < vw) && (h < vh))
3492 {
3493 diff = 0.01;
3494 while ((w < vw) && (h < vh))
3495 {
3496 zoom += diff;
3497 w = pow(2.0, zoom) * dd->wd->tsize;
3498 h = pow(2.0, zoom) * dd->wd->tsize;
3499 }
3500 }
3501 else
3502 {
3503 diff = -0.01;
3504 while ((w > vw) || (h > vh))
3505 {
3506 zoom += diff;
3507 w = pow(2.0, zoom) * dd->wd->tsize;
3508 h = pow(2.0, zoom) * dd->wd->tsize;
3509 }
3510 }
3511
3512 }
3513 else if (dd->mode == ELM_MAP_ZOOM_MODE_AUTO_FILL)
3514 {
3515 if ((w < vw) || (h < vh))
3516 {
3517 diff = 0.01;
3518 while ((w < vw) || (h < vh))
3519 {
3520 zoom += diff;
3521 w = pow(2.0, zoom) * dd->wd->tsize;
3522 h = pow(2.0, zoom) * dd->wd->tsize;
3523 }
3524 }
3525 else
3526 {
3527 diff = -0.01;
3528 while ((w > vw) && (h > vh))
3529 {
3530 zoom += diff;
3531 w = pow(2.0, zoom) * dd->wd->tsize;
3532 h = pow(2.0, zoom) * dd->wd->tsize;
3533 }
3534 }
3535 }
3536 zoom_do(dd->wd, zoom);
3537 }
3538}
3539
3540static void
3541_zoom_set(void *data)
3542{
3543 EINA_SAFETY_ON_NULL_RETURN(data);
3544 Delayed_Data *dd = data;
3545
3546 if (dd->wd->paused) zoom_do(dd->wd, dd->zoom);
3547 else zoom_with_animation(dd->wd, dd->zoom, 10);
3548 evas_object_smart_changed(dd->wd->pan_smart);
3549}
3550
3551static void
3552_region_bring_in(void *data)
3553{
3554 EINA_SAFETY_ON_NULL_RETURN(data);
3555 Delayed_Data *dd = data;
3556 int x, y, w, h;
3557
3558 _region_to_coord_convert(dd->wd, dd->lon, dd->lat, dd->wd->size.w, &x, &y);
3559 _viewport_coord_get(dd->wd, NULL, NULL, &w, &h);
3560 x = x - (w / 2);
3561 y = y - (h / 2);
3562 elm_smart_scroller_region_bring_in(dd->wd->scr, x, y, w, h);
3563 evas_object_smart_changed(dd->wd->pan_smart);
3564}
3565
3566static char *
3567_mapnik_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom)
3568{
3569 char buf[PATH_MAX];
3570 // ((x+y+zoom)%3)+'a' is requesting map images from distributed tile servers (eg., a, b, c)
3571 snprintf(buf, sizeof(buf), "http://%c.tile.openstreetmap.org/%d/%d/%d.png",
3572 ((x + y + zoom) % 3) + 'a', zoom, x, y);
3573 return strdup(buf);
3574}
3575
3576static char *
3577_osmarender_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom)
3578{
3579 char buf[PATH_MAX];
3580 snprintf(buf, sizeof(buf),
3581 "http://%c.tah.openstreetmap.org/Tiles/tile/%d/%d/%d.png",
3582 ((x + y + zoom) % 3) + 'a', zoom, x, y);
3583 return strdup(buf);
3584}
3585
3586static char *
3587_cyclemap_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom)
3588{
3589 char buf[PATH_MAX];
3590 snprintf(buf, sizeof(buf),
3591 "http://%c.tile.opencyclemap.org/cycle/%d/%d/%d.png",
3592 (( x + y + zoom) % 3) + 'a', zoom, x, y);
3593 return strdup(buf);
3594}
3595
3596static char *
3597_mapquest_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom)
3598{
3599 char buf[PATH_MAX];
3600 snprintf(buf, sizeof(buf),
3601 "http://otile%d.mqcdn.com/tiles/1.0.0/osm/%d/%d/%d.png",
3602 ((x + y + zoom) % 4) + 1, zoom, x, y);
3603 return strdup(buf);
3604}
3605
3606static char *
3607_mapquest_aerial_url_cb(const Evas_Object *obj __UNUSED__, int x, int y, int zoom)
3608{
3609 char buf[PATH_MAX];
3610 snprintf(buf, sizeof(buf), "http://oatile%d.mqcdn.com/naip/%d/%d/%d.png",
3611 ((x + y + zoom) % 4) + 1, zoom, x, y);
3612 return strdup(buf);
3613}
3614
3615static char *_yours_url_cb(const Evas_Object *obj __UNUSED__, const char *type_name, int method, double flon, double flat, double tlon, double tlat)
3616{
3617 char buf[PATH_MAX];
3618 snprintf(buf, sizeof(buf),
3619 "%s?flat=%lf&flon=%lf&tlat=%lf&tlon=%lf&v=%s&fast=%d&instructions=1",
3620 ROUTE_YOURS_URL, flat, flon, tlat, tlon, type_name, method);
3621
3622 return strdup(buf);
3623}
3624
3625// TODO: fix monav api
3626/*
3627static char *_monav_url_cb(const Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
3628{
3629 char buf[PATH_MAX];
3630 snprintf(buf, sizeof(buf),
3631 "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
3632 ROUTE_MONAV_URL, flat, flon, tlat, tlon, type_name, method);
3633
3634 return strdup(buf);
3635}
3636*/
3637
3638// TODO: fix ors api
3639/*
3640static char *_ors_url_cb(const Evas_Object *obj __UNUSED__, char *type_name, int method, double flon, double flat, double tlon, double tlat)
3641{
3642 char buf[PATH_MAX];
3643 snprintf(buf, sizeof(buf),
3644 "%s?flat=%f&flon=%f&tlat=%f&tlon=%f&v=%s&fast=%d&instructions=1",
3645 ROUTE_ORS_URL, flat, flon, tlat, tlon, type_name, method);
3646
3647 return strdup(buf);
3648}
3649*/
3650
3651static char *
3652_nominatim_url_cb(const Evas_Object *obj, int method, const char *name, double lon, double lat)
3653{
3654 ELM_CHECK_WIDTYPE(obj, widtype) strdup("");
3655 Widget_Data *wd = elm_widget_data_get(obj);
3656 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, strdup(""));
3657
3658 char **str;
3659 unsigned int ele, idx;
3660 char search_url[PATH_MAX];
3661 char buf[PATH_MAX];
3662
3663 if (method == ELM_MAP_NAME_METHOD_SEARCH)
3664 {
3665 search_url[0] = '\0';
3666 str = eina_str_split_full(name, " ", 0, &ele);
3667 for (idx = 0; idx < ele; idx++)
3668 {
3669 eina_strlcat(search_url, str[idx], sizeof(search_url));
3670 if (!(idx == (ele-1)))
3671 eina_strlcat(search_url, "+", sizeof(search_url));
3672 }
3673 snprintf(buf, sizeof(buf),
3674 "%s/search?q=%s&format=xml&polygon=0&addressdetails=0",
3675 NAME_NOMINATIM_URL, search_url);
3676
3677 if (str && str[0])
3678 {
3679 free(str[0]);
3680 free(str);
3681 }
3682 }
3683 else if (method == ELM_MAP_NAME_METHOD_REVERSE)
3684 snprintf(buf, sizeof(buf),
3685 "%s/reverse?format=xml&lat=%lf&lon=%lf&zoom=%d&addressdetails=0",
3686 NAME_NOMINATIM_URL, lat, lon, (int)wd->zoom);
3687 else strcpy(buf, "");
3688
3689 return strdup(buf);
3690}
3691
3692static double
3693_scale_cb(const Evas_Object *obj __UNUSED__, double lon __UNUSED__, double lat, int zoom)
3694{
3695 if (zoom < 0 || zoom >= (int)sizeof(_osm_scale_meter)) return 0;
3696 return _osm_scale_meter[zoom] / cos(lat * ELM_PI / 180.0);
3697}
3698
3699static void
3700_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
3701{
3702 ELM_CHECK_WIDTYPE(obj, widtype);
3703 Widget_Data *wd = elm_widget_data_get(obj);
3704 EINA_SAFETY_ON_NULL_RETURN(wd);
3705
3706 if (elm_widget_focus_get(obj))
3707 {
3708 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm");
3709 evas_object_focus_set(wd->obj, EINA_TRUE);
3710 }
3711 else
3712 {
3713 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm");
3714 evas_object_focus_set(wd->obj, EINA_FALSE);
3715 }
3716}
3717
3718static void
3719_del_hook(Evas_Object *obj)
3720{
3721 ELM_CHECK_WIDTYPE(obj, widtype);
3722 Widget_Data *wd = elm_widget_data_get(obj);
3723 EINA_SAFETY_ON_NULL_RETURN(wd);
3724
3725 if (wd->map) evas_map_free(wd->map);
3726 free(wd);
3727}
3728
3729static void
3730_del_pre_hook(Evas_Object *obj)
3731{
3732 ELM_CHECK_WIDTYPE(obj, widtype);
3733 Widget_Data *wd = elm_widget_data_get(obj);
3734 EINA_SAFETY_ON_NULL_RETURN(wd);
3735
3736 Eina_List *l, *ll;
3737 Elm_Map_Route *r;
3738 Elm_Map_Name *na;
3739 Evas_Object *track;
3740 Elm_Map_Overlay *overlay;
3741 Delayed_Data *dd;
3742
3743 EINA_LIST_FOREACH_SAFE(wd->routes, l, ll, r) elm_map_route_del(r);
3744 eina_list_free(wd->routes);
3745
3746 EINA_LIST_FOREACH_SAFE(wd->names, l, ll, na) elm_map_name_del(na);
3747 eina_list_free(wd->names);
3748
3749 EINA_LIST_FOREACH_SAFE(wd->overlays, l, ll, overlay)
3750 elm_map_overlay_del(overlay);
3751 eina_list_free(wd->overlays);
3752
3753 EINA_LIST_FREE(wd->track, track) evas_object_del(track);
3754
3755 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
3756 if (wd->long_timer) ecore_timer_del(wd->long_timer);
3757
3758 if (wd->delayed_jobs) EINA_LIST_FREE(wd->delayed_jobs, dd) free(dd);
3759
3760 if (wd->user_agent) eina_stringshare_del(wd->user_agent);
3761 if (wd->ua) eina_hash_free(wd->ua);
3762
3763 if (wd->zoom_timer) ecore_timer_del(wd->zoom_timer);
3764 if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
3765
3766 _grid_all_clear(wd);
3767 // Removal of download list should be after grid clear.
3768 if (wd->download_idler) ecore_idler_del(wd->download_idler);
3769 eina_list_free(wd->download_list);
3770
3771 _source_all_unload(wd);
3772
3773 if (!ecore_file_recursive_rm(CACHE_ROOT))
3774 ERR("Deletion of %s failed", CACHE_ROOT);
3775}
3776
3777static void
3778_theme_hook(Evas_Object *obj)
3779{
3780 ELM_CHECK_WIDTYPE(obj, widtype);
3781 Widget_Data *wd = elm_widget_data_get(obj);
3782 EINA_SAFETY_ON_NULL_RETURN(wd);
3783
3784 elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", elm_widget_style_get(obj));
3785 _sizing_eval(wd);
3786}
3787
3788static Eina_Bool
3789_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
3790{
3791 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3792 Widget_Data *wd = elm_widget_data_get(obj);
3793 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
3794
3795 Evas_Coord x, y;
3796 Evas_Coord vh;
3797 Evas_Coord step_x, step_y, page_x, page_y;
3798
3799 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
3800 Evas_Event_Key_Down *ev = event_info;
3801 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
3802
3803 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
3804 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
3805 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
3806 elm_smart_scroller_child_viewport_size_get(wd->scr, NULL, &vh);
3807
3808 if ((!strcmp(ev->keyname, "Left")) ||
3809 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
3810 {
3811 x -= step_x;
3812 }
3813 else if ((!strcmp(ev->keyname, "Right")) ||
3814 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
3815 {
3816 x += step_x;
3817 }
3818 else if ((!strcmp(ev->keyname, "Up")) ||
3819 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
3820 {
3821 y -= step_y;
3822 }
3823 else if ((!strcmp(ev->keyname, "Down")) ||
3824 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
3825 {
3826 y += step_y;
3827 }
3828 else if ((!strcmp(ev->keyname, "Prior")) ||
3829 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
3830 {
3831 if (page_y < 0)
3832 y -= -(page_y * vh) / 100;
3833 else
3834 y -= page_y;
3835 }
3836 else if ((!strcmp(ev->keyname, "Next")) ||
3837 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
3838 {
3839 if (page_y < 0)
3840 y += -(page_y * vh) / 100;
3841 else
3842 y += page_y;
3843 }
3844 else if (!strcmp(ev->keyname, "KP_Add"))
3845 {
3846 zoom_with_animation(wd, wd->zoom + 1, 10);
3847 return EINA_TRUE;
3848 }
3849 else if (!strcmp(ev->keyname, "KP_Subtract"))
3850 {
3851 zoom_with_animation(wd, wd->zoom - 1, 10);
3852 return EINA_TRUE;
3853 }
3854 else return EINA_FALSE;
3855
3856 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
3857 elm_smart_scroller_child_pos_set(wd->scr, x, y);
3858
3859 return EINA_TRUE;
3860}
3861#endif
3862
3863EAPI Evas_Object *
3864elm_map_add(Evas_Object *parent)
3865{
3866#ifdef HAVE_ELEMENTARY_ECORE_CON
3867 Evas *e;
3868 Widget_Data *wd;
3869 Evas_Object *obj;
3870 Evas_Coord minw, minh;
3871
3872 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
3873 ELM_SET_WIDTYPE(widtype, "map");
3874 elm_widget_type_set(obj, "map");
3875 elm_widget_sub_object_add(parent, obj);
3876 elm_widget_data_set(obj, wd);
3877 elm_widget_can_focus_set(obj, EINA_TRUE);
3878 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
3879 elm_widget_del_hook_set(obj, _del_hook);
3880 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
3881 elm_widget_theme_hook_set(obj, _theme_hook);
3882 elm_widget_event_hook_set(obj, _event_hook);
3883 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, wd);
3884 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, wd);
3885 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, wd);
3886 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, wd);
3887 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
3888 _mouse_down, wd);
3889 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
3890 _mouse_up, wd);
3891 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
3892 _mouse_wheel_cb,wd);
3893 wd->obj = obj;
3894
3895 wd->scr = elm_smart_scroller_add(e);
3896 elm_widget_sub_object_add(obj, wd->scr);
3897 elm_smart_scroller_widget_set(wd->scr, obj);
3898 elm_smart_scroller_object_theme_set(obj, wd->scr, "map", "base", "default");
3899 elm_widget_resize_object_set(obj, wd->scr);
3900 elm_smart_scroller_wheel_disabled_set(wd->scr, EINA_TRUE);
3901 elm_smart_scroller_bounce_allow_set(wd->scr,
3902 _elm_config->thumbscroll_bounce_enable,
3903 _elm_config->thumbscroll_bounce_enable);
3904 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
3905 _changed_size_hints, wd);
3906 evas_object_smart_callback_add(wd->scr, "scroll", _scr, wd);
3907 evas_object_smart_callback_add(wd->scr, "drag", _scr, wd);
3908 evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, wd);
3909 evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, wd);
3910
3911 if (!smart)
3912 {
3913 evas_object_smart_clipped_smart_set(&parent_sc);
3914 sc = parent_sc;
3915 sc.name = "elm_map_pan";
3916 sc.version = EVAS_SMART_CLASS_VERSION;
3917 sc.add = _pan_add;
3918 sc.resize = _pan_resize;
3919 sc.move = _pan_move;
3920 sc.calculate = _pan_calculate;
3921 smart = evas_smart_class_new(&sc);
3922 }
3923 if (smart)
3924 {
3925 Pan *pan;
3926 wd->pan_smart = evas_object_smart_add(e, smart);
3927 pan = evas_object_smart_data_get(wd->pan_smart);
3928 pan->wd = wd;
3929 }
3930 elm_widget_sub_object_add(obj, wd->pan_smart);
3931
3932 elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
3933 _pan_set, _pan_get, _pan_max_get,
3934 _pan_min_get, _pan_child_size_get);
3935 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
3936 &minw, &minh);
3937 evas_object_size_hint_min_set(obj, minw, minh);
3938
3939 wd->ges = elm_gesture_layer_add(obj);
3940 if (!wd->ges) ERR("elm_gesture_layer_add() failed");
3941 elm_gesture_layer_attach(wd->ges, obj);
3942 elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START,
3943 _pinch_zoom_start_cb, wd);
3944 elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE,
3945 _pinch_zoom_cb, wd);
3946 elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_MOVE,
3947 _pinch_rotate_cb, wd);
3948 elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_END,
3949 _pinch_rotate_end_cb, wd);
3950 elm_gesture_layer_cb_set(wd->ges, ELM_GESTURE_ROTATE, ELM_GESTURE_STATE_ABORT,
3951 _pinch_rotate_end_cb, wd);
3952
3953 wd->sep_maps_overlays = evas_object_rectangle_add(evas_object_evas_get(obj));
3954 elm_widget_sub_object_add(obj, wd->sep_maps_overlays);
3955 evas_object_smart_member_add(wd->sep_maps_overlays, wd->pan_smart);
3956
3957 wd->map = evas_map_new(EVAS_MAP_POINT);
3958
3959 _source_all_load(wd);
3960 wd->zoom_min = wd->src_tile->zoom_min;
3961 wd->zoom_max = wd->src_tile->zoom_max;
3962 // FIXME: Tile Provider is better to provide tile size!
3963 wd->tsize = DEFAULT_TILE_SIZE;
3964
3965 srand(time(NULL));
3966
3967 wd->id = ((int)getpid() << 16) | idnum;
3968 idnum++;
3969 _grid_all_create(wd);
3970
3971 zoom_do(wd, 0);
3972
3973 wd->mode = ELM_MAP_ZOOM_MODE_MANUAL;
3974
3975 // TODO: convert Elementary to subclassing of Evas_Smart_Class
3976 // TODO: and save some bytes, making descriptions per-class and not instance!
3977 evas_object_smart_callbacks_descriptions_set(obj, _signals);
3978
3979 if (!ecore_file_download_protocol_available("http://"))
3980 ERR("Ecore must be built with curl support for the map widget!");
3981
3982 return obj;
3983#else
3984 (void) parent;
3985 return NULL;
3986#endif
3987}
3988
3989EAPI void
3990elm_map_zoom_set(Evas_Object *obj, int zoom)
3991{
3992#ifdef HAVE_ELEMENTARY_ECORE_CON
3993 ELM_CHECK_WIDTYPE(obj, widtype);
3994 Widget_Data *wd = elm_widget_data_get(obj);
3995 EINA_SAFETY_ON_NULL_RETURN(wd);
3996 EINA_SAFETY_ON_NULL_RETURN(wd->src_tile);
3997
3998 if (wd->mode != ELM_MAP_ZOOM_MODE_MANUAL) return;
3999 if (zoom < 0) zoom = 0;
4000 if (wd->zoom == zoom) return;
4001 Delayed_Data *data = ELM_NEW(Delayed_Data);
4002 data->func = _zoom_set;
4003 data->wd = wd;
4004 data->zoom = zoom;
4005 data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data);
4006 evas_object_smart_changed(data->wd->pan_smart);
4007#else
4008 (void) obj;
4009 (void) zoom;
4010#endif
4011}
4012
4013EAPI int
4014elm_map_zoom_get(const Evas_Object *obj)
4015{
4016#ifdef HAVE_ELEMENTARY_ECORE_CON
4017 ELM_CHECK_WIDTYPE(obj, widtype) 0;
4018 Widget_Data *wd = elm_widget_data_get(obj);
4019
4020 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, 0);
4021 return wd->zoom;
4022#else
4023 (void) obj;
4024 return 0;
4025#endif
4026}
4027
4028EAPI void
4029elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode)
4030{
4031#ifdef HAVE_ELEMENTARY_ECORE_CON
4032 ELM_CHECK_WIDTYPE(obj, widtype);
4033 Widget_Data *wd = elm_widget_data_get(obj);
4034 EINA_SAFETY_ON_NULL_RETURN(wd);
4035
4036 if ((mode == ELM_MAP_ZOOM_MODE_MANUAL) && (wd->mode == !!mode)) return;
4037
4038 Delayed_Data *data = ELM_NEW(Delayed_Data);
4039 data->mode = mode;
4040 data->func = _zoom_mode_set;
4041 data->wd = wd;
4042 data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data);
4043 evas_object_smart_changed(data->wd->pan_smart);
4044#else
4045 (void) obj;
4046 (void) mode;
4047#endif
4048}
4049
4050EAPI Elm_Map_Zoom_Mode
4051elm_map_zoom_mode_get(const Evas_Object *obj)
4052{
4053#ifdef HAVE_ELEMENTARY_ECORE_CON
4054 ELM_CHECK_WIDTYPE(obj, widtype) ELM_MAP_ZOOM_MODE_MANUAL;
4055 Widget_Data *wd = elm_widget_data_get(obj);
4056 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, ELM_MAP_ZOOM_MODE_MANUAL);
4057
4058 return wd->mode;
4059#else
4060 (void) obj;
4061 return ELM_MAP_ZOOM_MODE_MANUAL;
4062#endif
4063}
4064
4065EAPI void
4066elm_map_zoom_max_set(Evas_Object *obj, int zoom)
4067{
4068#ifdef HAVE_ELEMENTARY_ECORE_CON
4069 ELM_CHECK_WIDTYPE(obj, widtype);
4070 Widget_Data *wd = elm_widget_data_get(obj);
4071 EINA_SAFETY_ON_NULL_RETURN(wd);
4072 EINA_SAFETY_ON_NULL_RETURN(wd->src_tile);
4073
4074 wd->zoom_max = zoom;
4075#else
4076 (void) obj;
4077 (void) zoom;
4078#endif
4079}
4080
4081EAPI int
4082elm_map_zoom_max_get(const Evas_Object *obj)
4083{
4084#ifdef HAVE_ELEMENTARY_ECORE_CON
4085 ELM_CHECK_WIDTYPE(obj, widtype) -1;
4086 Widget_Data *wd = elm_widget_data_get(obj);
4087 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, -1);
4088 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src_tile, -1);
4089
4090 return wd->zoom_max;
4091#else
4092 (void) obj;
4093 return -1;
4094#endif
4095}
4096
4097EAPI void
4098elm_map_zoom_min_set(Evas_Object *obj, int zoom)
4099{
4100#ifdef HAVE_ELEMENTARY_ECORE_CON
4101 ELM_CHECK_WIDTYPE(obj, widtype);
4102 Widget_Data *wd = elm_widget_data_get(obj);
4103 EINA_SAFETY_ON_NULL_RETURN(wd);
4104 EINA_SAFETY_ON_NULL_RETURN(wd->src_tile);
4105
4106 wd->zoom_min = zoom;
4107#else
4108 (void) obj;
4109 (void) zoom;
4110#endif
4111}
4112
4113EAPI int
4114elm_map_zoom_min_get(const Evas_Object *obj)
4115{
4116#ifdef HAVE_ELEMENTARY_ECORE_CON
4117 ELM_CHECK_WIDTYPE(obj, widtype) -1;
4118 Widget_Data *wd = elm_widget_data_get(obj);
4119 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, -1);
4120 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src_tile, -1);
4121
4122 return wd->zoom_min;
4123#else
4124 (void) obj;
4125 return -1;
4126#endif
4127}
4128
4129EAPI void
4130elm_map_region_bring_in(Evas_Object *obj, double lon, double lat)
4131{
4132#ifdef HAVE_ELEMENTARY_ECORE_CON
4133 ELM_CHECK_WIDTYPE(obj, widtype);
4134 Widget_Data *wd = elm_widget_data_get(obj);
4135
4136 Delayed_Data *data = ELM_NEW(Delayed_Data);
4137 data->func = _region_bring_in;
4138 data->wd = wd;
4139 data->lon = lon;
4140 data->lat = lat;
4141 data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data);
4142 evas_object_smart_changed(data->wd->pan_smart);
4143#else
4144 (void) obj;
4145 (void) lon;
4146 (void) lat;
4147#endif
4148}
4149
4150EAPI void
4151elm_map_region_show(Evas_Object *obj, double lon, double lat)
4152{
4153#ifdef HAVE_ELEMENTARY_ECORE_CON
4154 ELM_CHECK_WIDTYPE(obj, widtype);
4155 Widget_Data *wd = elm_widget_data_get(obj);
4156
4157 Delayed_Data *data = ELM_NEW(Delayed_Data);
4158 data->func = _region_show;
4159 data->wd = wd;
4160 data->lon = lon;
4161 data->lat = lat;
4162 data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data);
4163 evas_object_smart_changed(data->wd->pan_smart);
4164#else
4165 (void) obj;
4166 (void) lon;
4167 (void) lat;
4168#endif
4169}
4170
4171EAPI void
4172elm_map_region_get(const Evas_Object *obj, double *lon, double *lat)
4173{
4174#ifdef HAVE_ELEMENTARY_ECORE_CON
4175 ELM_CHECK_WIDTYPE(obj, widtype);
4176 Widget_Data *wd = elm_widget_data_get(obj);
4177 EINA_SAFETY_ON_NULL_RETURN(wd);
4178
4179 double tlon, tlat;
4180 Evas_Coord vx, vy, vw, vh;
4181
4182 _viewport_coord_get(wd, &vx, &vy, &vw, &vh);
4183 _coord_to_region_convert(wd, vx + vw/2, vy + vh/2, wd->size.w, &tlon, &tlat);
4184 if (lon) *lon = tlon;
4185 if (lat) *lat = tlat;
4186#else
4187 (void) obj;
4188 (void) lon;
4189 (void) lat;
4190#endif
4191}
4192
4193EAPI void
4194elm_map_paused_set(Evas_Object *obj, Eina_Bool paused)
4195{
4196#ifdef HAVE_ELEMENTARY_ECORE_CON
4197 ELM_CHECK_WIDTYPE(obj, widtype);
4198 Widget_Data *wd = elm_widget_data_get(obj);
4199 EINA_SAFETY_ON_NULL_RETURN(wd);
4200
4201 if (wd->paused == !!paused) return;
4202 wd->paused = !!paused;
4203 if (wd->paused)
4204 {
4205 if (wd->zoom_animator)
4206 {
4207 if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
4208 wd->zoom_animator = NULL;
4209 zoom_do(wd, wd->zoom);
4210 }
4211 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
4212 "elm,state,busy,stop", "elm");
4213 }
4214 else
4215 {
4216 if (wd->download_num >= 1)
4217 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
4218 "elm,state,busy,start", "elm");
4219 }
4220#else
4221 (void) obj;
4222 (void) paused;
4223#endif
4224}
4225
4226EAPI Eina_Bool
4227elm_map_paused_get(const Evas_Object *obj)
4228{
4229#ifdef HAVE_ELEMENTARY_ECORE_CON
4230 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4231 Widget_Data *wd = elm_widget_data_get(obj);
4232 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
4233
4234 return wd->paused;
4235#else
4236 (void) obj;
4237 return EINA_FALSE;
4238#endif
4239}
4240
4241EAPI void
4242elm_map_rotate_set(Evas_Object *obj, double degree, Evas_Coord cx, Evas_Coord cy)
4243{
4244#ifdef HAVE_ELEMENTARY_ECORE_CON
4245 ELM_CHECK_WIDTYPE(obj, widtype);
4246 Widget_Data *wd = elm_widget_data_get(obj);
4247 EINA_SAFETY_ON_NULL_RETURN(wd);
4248
4249 wd->rotate.d = degree;
4250 wd->rotate.cx = cx;
4251 wd->rotate.cy = cy;
4252
4253 evas_object_smart_changed(wd->pan_smart);
4254#else
4255 (void) obj;
4256 (void) degree;
4257 (void) cx;
4258 (void) cy;
4259#endif
4260}
4261
4262EAPI void
4263elm_map_rotate_get(const Evas_Object *obj, double *degree, Evas_Coord *cx, Evas_Coord *cy)
4264{
4265#ifdef HAVE_ELEMENTARY_ECORE_CON
4266 ELM_CHECK_WIDTYPE(obj, widtype);
4267 Widget_Data *wd = elm_widget_data_get(obj);
4268 EINA_SAFETY_ON_NULL_RETURN(wd);
4269
4270 if (degree) *degree = wd->rotate.d;
4271 if (cx) *cx = wd->rotate.cx;
4272 if (cy) *cy = wd->rotate.cy;
4273#else
4274 (void) obj;
4275 (void) degree;
4276 (void) cx;
4277 (void) cy;
4278#endif
4279}
4280
4281EAPI void
4282elm_map_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled)
4283{
4284#ifdef HAVE_ELEMENTARY_ECORE_CON
4285 ELM_CHECK_WIDTYPE(obj, widtype);
4286 Widget_Data *wd = elm_widget_data_get(obj);
4287 EINA_SAFETY_ON_NULL_RETURN(wd);
4288
4289 if ((!wd->wheel_disabled) && (disabled))
4290 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, wd);
4291 else if ((wd->wheel_disabled) && (!disabled))
4292 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL, _mouse_wheel_cb, wd);
4293 wd->wheel_disabled = !!disabled;
4294#else
4295 (void) obj;
4296 (void) disabled;
4297#endif
4298}
4299
4300EAPI Eina_Bool
4301elm_map_wheel_disabled_get(const Evas_Object *obj)
4302{
4303#ifdef HAVE_ELEMENTARY_ECORE_CON
4304 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
4305 Widget_Data *wd = elm_widget_data_get(obj);
4306 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
4307
4308 return wd->wheel_disabled;
4309#else
4310 (void) obj;
4311 return EINA_FALSE;
4312#endif
4313}
4314
4315EAPI void
4316elm_map_tile_load_status_get(const Evas_Object *obj, int *try_num, int *finish_num)
4317{
4318#ifdef HAVE_ELEMENTARY_ECORE_CON
4319 ELM_CHECK_WIDTYPE(obj, widtype);
4320 Widget_Data *wd = elm_widget_data_get(obj);
4321 EINA_SAFETY_ON_NULL_RETURN(wd);
4322
4323 if (try_num) *try_num = wd->try_num;
4324 if (finish_num) *finish_num = wd->finish_num;
4325#else
4326 (void) obj;
4327 (void) try_num;
4328 (void) finish_num;
4329#endif
4330}
4331
4332EAPI void
4333elm_map_canvas_to_region_convert(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, double *lon, double *lat)
4334{
4335#ifdef HAVE_ELEMENTARY_ECORE_CON
4336 ELM_CHECK_WIDTYPE(obj, widtype);
4337 Widget_Data *wd = elm_widget_data_get(obj);
4338 EINA_SAFETY_ON_NULL_RETURN(wd);
4339 EINA_SAFETY_ON_NULL_RETURN(lon);
4340 EINA_SAFETY_ON_NULL_RETURN(lat);
4341
4342 _canvas_to_coord(wd, x, y, &x, &y);
4343 _coord_to_region_convert(wd, x, y, wd->size.w, lon, lat);
4344#else
4345 (void) obj;
4346 (void) x;
4347 (void) y;
4348 (void) lon;
4349 (void) lat;
4350#endif
4351}
4352
4353EAPI void
4354elm_map_region_to_canvas_convert(const Evas_Object *obj, double lon, double lat, Evas_Coord *x, Evas_Coord *y)
4355{
4356#ifdef HAVE_ELEMENTARY_ECORE_CON
4357 ELM_CHECK_WIDTYPE(obj, widtype);
4358 Widget_Data *wd = elm_widget_data_get(obj);
4359 EINA_SAFETY_ON_NULL_RETURN(wd);
4360 EINA_SAFETY_ON_NULL_RETURN(x);
4361 EINA_SAFETY_ON_NULL_RETURN(y);
4362
4363 _region_to_coord_convert(wd, lon, lat, wd->size.w, x, y);
4364 _coord_to_canvas(wd, *x, *y, x, y);
4365#else
4366 (void) obj;
4367 (void) lon;
4368 (void) lat;
4369 (void) x;
4370 (void) y;
4371#endif
4372}
4373
4374EAPI void
4375elm_map_user_agent_set(Evas_Object *obj, const char *user_agent)
4376{
4377#ifdef HAVE_ELEMENTARY_ECORE_CON
4378 ELM_CHECK_WIDTYPE(obj, widtype);
4379 Widget_Data *wd = elm_widget_data_get(obj);
4380 EINA_SAFETY_ON_NULL_RETURN(wd);
4381 EINA_SAFETY_ON_NULL_RETURN(user_agent);
4382
4383 eina_stringshare_replace(&wd->user_agent, user_agent);
4384
4385 if (!wd->ua) wd->ua = eina_hash_string_small_new(NULL);
4386 eina_hash_set(wd->ua, "User-Agent", wd->user_agent);
4387#else
4388 (void) obj;
4389 (void) user_agent;
4390#endif
4391}
4392
4393EAPI const char *
4394elm_map_user_agent_get(const Evas_Object *obj)
4395{
4396#ifdef HAVE_ELEMENTARY_ECORE_CON
4397 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4398 Widget_Data *wd = elm_widget_data_get(obj);
4399 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
4400
4401 return wd->user_agent;
4402#else
4403 (void) obj;
4404 return NULL;
4405#endif
4406}
4407
4408EAPI void
4409elm_map_source_set(Evas_Object *obj, Elm_Map_Source_Type type, const char *source_name)
4410{
4411#ifdef HAVE_ELEMENTARY_ECORE_CON
4412 ELM_CHECK_WIDTYPE(obj, widtype);
4413 Widget_Data *wd = elm_widget_data_get(obj);
4414 EINA_SAFETY_ON_NULL_RETURN(wd);
4415 EINA_SAFETY_ON_NULL_RETURN(source_name);
4416
4417 if (type == ELM_MAP_SOURCE_TYPE_TILE) _source_tile_set(wd, source_name);
4418 else if (type == ELM_MAP_SOURCE_TYPE_ROUTE)
4419 _source_route_set(wd, source_name);
4420 else if (type == ELM_MAP_SOURCE_TYPE_NAME) _source_name_set(wd, source_name);
4421 else ERR("Not supported map source type: %d", type);
4422
4423#else
4424 (void) obj;
4425 (void) source_name;
4426#endif
4427}
4428
4429EAPI const char *
4430elm_map_source_get(const Evas_Object *obj, Elm_Map_Source_Type type)
4431{
4432#ifdef HAVE_ELEMENTARY_ECORE_CON
4433 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4434 Widget_Data *wd = elm_widget_data_get(obj);
4435 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
4436 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src_tile, NULL);
4437
4438 if (type == ELM_MAP_SOURCE_TYPE_TILE) return wd->src_tile->name;
4439 else if (type == ELM_MAP_SOURCE_TYPE_ROUTE) return wd->src_route->name;
4440 else if (type == ELM_MAP_SOURCE_TYPE_NAME) return wd->src_name->name;
4441 else ERR("Not supported map source type: %d", type);
4442 return NULL;
4443#else
4444 (void) obj;
4445 return NULL;
4446#endif
4447}
4448
4449EAPI const char **
4450elm_map_sources_get(const Evas_Object *obj, Elm_Map_Source_Type type)
4451{
4452#ifdef HAVE_ELEMENTARY_ECORE_CON
4453 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4454 Widget_Data *wd = elm_widget_data_get(obj);
4455 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
4456
4457 if (type == ELM_MAP_SOURCE_TYPE_TILE) return wd->src_tile_names;
4458 else if (type == ELM_MAP_SOURCE_TYPE_ROUTE) return wd->src_route_names;
4459 else if (type == ELM_MAP_SOURCE_TYPE_NAME) return wd->src_name_names;
4460 else ERR("Not supported map source type: %d", type);
4461 return NULL;
4462#else
4463 (void) obj;
4464 return NULL;
4465#endif
4466}
4467
4468EAPI Elm_Map_Route *
4469elm_map_route_add(Evas_Object *obj, Elm_Map_Route_Type type, Elm_Map_Route_Method method, double flon, double flat, double tlon, double tlat, Elm_Map_Route_Cb route_cb, void *data)
4470{
4471#ifdef HAVE_ELEMENTARY_ECORE_CON
4472 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4473 Widget_Data *wd = elm_widget_data_get(obj);
4474 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
4475 EINA_SAFETY_ON_NULL_RETURN_VAL(wd->src_route, NULL);
4476
4477 char *type_name;
4478 char *url;
4479 char fname[PATH_MAX];
4480
4481 if (!ecore_file_exists(CACHE_ROUTE_ROOT))
4482 ecore_file_mkpath(CACHE_ROUTE_ROOT);
4483
4484 if (type == ELM_MAP_ROUTE_TYPE_MOTOCAR)
4485 type_name = strdup(ROUTE_TYPE_MOTORCAR);
4486 else if (type == ELM_MAP_ROUTE_TYPE_BICYCLE)
4487 type_name = strdup(ROUTE_TYPE_BICYCLE);
4488 else if (type == ELM_MAP_ROUTE_TYPE_FOOT)
4489 type_name = strdup(ROUTE_TYPE_FOOT);
4490 else type_name = NULL;
4491
4492 url = wd->src_route->url_cb(obj, type_name, method, flon, flat, tlon, tlat);
4493 if (!url)
4494 {
4495 ERR("Route URL is NULL");
4496 if (type_name) free(type_name);
4497 return NULL;
4498 }
4499 if (type_name) free(type_name);
4500
4501 Elm_Map_Route *route = ELM_NEW(Elm_Map_Route);
4502 route->wd = wd;
4503 snprintf(fname, sizeof(fname), CACHE_ROUTE_ROOT"/%d", rand());
4504 route->fname = strdup(fname);
4505 route->type = type;
4506 route->method = method;
4507 route->flon = flon;
4508 route->flat = flat;
4509 route->tlon = tlon;
4510 route->tlat = tlat;
4511 route->cb = route_cb;
4512 route->data = data;
4513
4514 if (!ecore_file_download_full(url, route->fname, _route_cb, NULL, route,
4515 &(route->job), wd->ua) || !(route->job))
4516 {
4517 ERR("Can't request Route from %s to %s", url, route->fname);
4518 free(route->fname);
4519 free(route);
4520 return NULL;
4521 }
4522 INF("Route requested from %s to %s", url, route->fname);
4523 free(url);
4524
4525 wd->routes = eina_list_append(wd->routes, route);
4526 evas_object_smart_callback_call(wd->obj, SIG_ROUTE_LOAD, route);
4527 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
4528 "elm,state,busy,start", "elm");
4529 return route;
4530#else
4531 (void) obj;
4532 (void) type;
4533 (void) method;
4534 (void) flon;
4535 (void) flat;
4536 (void) tlon;
4537 (void) tlat;
4538 (void) route_cb;
4539 (void) data;
4540 return NULL;
4541#endif
4542}
4543
4544
4545EAPI void
4546elm_map_route_del(Elm_Map_Route *route)
4547{
4548#ifdef HAVE_ELEMENTARY_ECORE_CON
4549 EINA_SAFETY_ON_NULL_RETURN(route);
4550 EINA_SAFETY_ON_NULL_RETURN(route->wd);
4551 ELM_CHECK_WIDTYPE(route->wd->obj, widtype);
4552
4553 Path_Waypoint *w;
4554 Path_Node *n;
4555
4556 if (route->job) ecore_file_download_abort(route->job);
4557
4558 EINA_LIST_FREE(route->waypoint, w)
4559 {
4560 if (w->point) eina_stringshare_del(w->point);
4561 free(w);
4562 }
4563
4564 EINA_LIST_FREE(route->nodes, n)
4565 {
4566 if (n->pos.address) eina_stringshare_del(n->pos.address);
4567 free(n);
4568 }
4569
4570 if (route->fname)
4571 {
4572 ecore_file_remove(route->fname);
4573 free(route->fname);
4574 }
4575
4576 route->wd->routes = eina_list_remove(route->wd->routes, route);
4577 free(route);
4578#else
4579 (void) route;
4580#endif
4581}
4582
4583EAPI double
4584elm_map_route_distance_get(const Elm_Map_Route *route)
4585{
4586#ifdef HAVE_ELEMENTARY_ECORE_CON
4587 EINA_SAFETY_ON_NULL_RETURN_VAL(route, 0.0);
4588 return route->info.distance;
4589#else
4590 (void) route;
4591 return 0.0;
4592#endif
4593}
4594
4595EAPI const char*
4596elm_map_route_node_get(const Elm_Map_Route *route)
4597{
4598#ifdef HAVE_ELEMENTARY_ECORE_CON
4599 EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
4600 return route->info.nodes;
4601#else
4602 (void) route;
4603 return NULL;
4604#endif
4605}
4606
4607EAPI const char*
4608elm_map_route_waypoint_get(const Elm_Map_Route *route)
4609{
4610#ifdef HAVE_ELEMENTARY_ECORE_CON
4611 EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
4612 return route->info.waypoints;
4613#else
4614 (void) route;
4615 return NULL;
4616#endif
4617}
4618
4619EAPI Elm_Map_Name *
4620elm_map_name_add(const Evas_Object *obj, const char *address, double lon, double lat, Elm_Map_Name_Cb name_cb, void *data)
4621{
4622#ifdef HAVE_ELEMENTARY_ECORE_CON
4623 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4624
4625 if (address)
4626 return _name_request(obj, ELM_MAP_NAME_METHOD_SEARCH, address, 0, 0,
4627 name_cb, data);
4628 else
4629 return _name_request(obj, ELM_MAP_NAME_METHOD_REVERSE, NULL, lon, lat,
4630 name_cb, data);
4631#else
4632 (void) obj;
4633 (void) address;
4634 (void) lon;
4635 (void) lat;
4636 (void) name_cb;
4637 (void) data;
4638 return NULL;
4639#endif
4640}
4641
4642EAPI void
4643elm_map_name_del(Elm_Map_Name *name)
4644{
4645#ifdef HAVE_ELEMENTARY_ECORE_CON
4646 EINA_SAFETY_ON_NULL_RETURN(name);
4647 EINA_SAFETY_ON_NULL_RETURN(name->wd);
4648 ELM_CHECK_WIDTYPE(name->wd->obj, widtype);
4649
4650 if (name->job) ecore_file_download_abort(name->job);
4651 if (name->address) free(name->address);
4652 if (name->fname)
4653 {
4654 ecore_file_remove(name->fname);
4655 free(name->fname);
4656 }
4657
4658 name->wd->names = eina_list_remove(name->wd->names, name);
4659 free(name);
4660#else
4661 (void) name;
4662#endif
4663}
4664
4665EAPI const char *
4666elm_map_name_address_get(const Elm_Map_Name *name)
4667{
4668#ifdef HAVE_ELEMENTARY_ECORE_CON
4669 EINA_SAFETY_ON_NULL_RETURN_VAL(name, NULL);
4670 EINA_SAFETY_ON_NULL_RETURN_VAL(name->wd, NULL);
4671 ELM_CHECK_WIDTYPE(name->wd->obj, widtype) NULL;
4672
4673 return name->address;
4674#else
4675 (void) name;
4676 return NULL;
4677#endif
4678}
4679
4680EAPI void
4681elm_map_name_region_get(const Elm_Map_Name *name, double *lon, double *lat)
4682{
4683#ifdef HAVE_ELEMENTARY_ECORE_CON
4684 EINA_SAFETY_ON_NULL_RETURN(name);
4685 EINA_SAFETY_ON_NULL_RETURN(name->wd);
4686 ELM_CHECK_WIDTYPE(name->wd->obj, widtype);
4687
4688 if (lon) *lon = name->lon;
4689 if (lat) *lat = name->lat;
4690#else
4691 (void) name;
4692 (void) lon;
4693 (void) lat;
4694#endif
4695}
4696
4697EAPI Elm_Map_Overlay *
4698elm_map_overlay_add(Evas_Object *obj, double lon, double lat)
4699{
4700#ifdef HAVE_ELEMENTARY_ECORE_CON
4701 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
4702 Widget_Data *wd = elm_widget_data_get(obj);
4703 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
4704
4705 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
4706 overlay->wd = wd;
4707 overlay->type = ELM_MAP_OVERLAY_TYPE_DEFAULT;
4708 overlay->c.r = 0x87;
4709 overlay->c.g = 0xce;
4710 overlay->c.b = 0xeb;
4711 overlay->c.a = 255;
4712 overlay->ovl = _overlay_default_new(overlay, lon, lat, overlay->c, 1);
4713 overlay->grp = _overlay_group_new(wd);
4714 wd->overlays = eina_list_append(wd->overlays, overlay);
4715
4716 evas_object_smart_changed(wd->pan_smart);
4717 return overlay;
4718#else
4719 (void) obj;
4720 (void) lon;
4721 (void) lat;
4722 return NULL;
4723#endif
4724}
4725
4726EAPI void
4727elm_map_overlay_del(Elm_Map_Overlay *overlay)
4728{
4729#ifdef HAVE_ELEMENTARY_ECORE_CON
4730 EINA_SAFETY_ON_NULL_RETURN(overlay);
4731 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4732 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4733
4734 if (overlay->grp)
4735 {
4736 if (overlay->grp->clas)
4737 elm_map_overlay_class_remove(overlay->grp->clas, overlay);
4738 _overlay_group_free(overlay->grp);
4739 }
4740
4741 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
4742 _overlay_default_free(overlay->ovl);
4743 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
4744 _overlay_bubble_free(overlay->ovl);
4745 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
4746 _overlay_class_free(overlay->ovl);
4747 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
4748 _overlay_route_free(overlay->ovl);
4749 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_LINE)
4750 _overlay_line_free(overlay->ovl);
4751 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_POLYGON)
4752 _overlay_polygon_free(overlay->ovl);
4753 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CIRCLE)
4754 _overlay_circle_free(overlay->ovl);
4755 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_SCALE)
4756 _overlay_scale_free(overlay->ovl);
4757 else ERR("Invalid overlay type: %d", overlay->type);
4758
4759 overlay->wd->overlays = eina_list_remove(overlay->wd->overlays, overlay);
4760 evas_object_smart_changed(overlay->wd->pan_smart);
4761
4762 free(overlay);
4763#else
4764 (void) overlay;
4765#endif
4766}
4767
4768EAPI Elm_Map_Overlay_Type
4769elm_map_overlay_type_get(const Elm_Map_Overlay *overlay)
4770{
4771#ifdef HAVE_ELEMENTARY_ECORE_CON
4772 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, ELM_MAP_OVERLAY_TYPE_NONE);
4773 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, ELM_MAP_OVERLAY_TYPE_NONE);
4774 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) ELM_MAP_OVERLAY_TYPE_NONE;
4775
4776 return overlay->type;
4777#else
4778 (void) overlay;
4779 return ELM_MAP_OVERLAY_TYPE_NONE;
4780#endif
4781}
4782
4783EAPI void
4784elm_map_overlay_data_set(Elm_Map_Overlay *overlay, void *data)
4785{
4786#ifdef HAVE_ELEMENTARY_ECORE_CON
4787 EINA_SAFETY_ON_NULL_RETURN(overlay);
4788 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4789 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4790
4791 overlay->data = data;
4792#else
4793 (void) overlay;
4794 (void) data;
4795#endif
4796}
4797
4798EAPI void *
4799elm_map_overlay_data_get(const Elm_Map_Overlay *overlay)
4800{
4801#ifdef HAVE_ELEMENTARY_ECORE_CON
4802 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
4803 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, NULL);
4804 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) NULL;
4805
4806 return overlay->data;
4807#else
4808 (void) overlay;
4809 return NULL;
4810#endif
4811}
4812
4813EAPI void
4814elm_map_overlay_hide_set(Elm_Map_Overlay *overlay, Eina_Bool hide)
4815{
4816#ifdef HAVE_ELEMENTARY_ECORE_CON
4817 EINA_SAFETY_ON_NULL_RETURN(overlay);
4818 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4819 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4820
4821 if (overlay->hide == !!hide) return;
4822 overlay->hide = hide;
4823
4824 evas_object_smart_changed(overlay->wd->pan_smart);
4825#else
4826 (void) overlay;
4827 (void) hide;
4828#endif
4829}
4830
4831EAPI Eina_Bool
4832elm_map_overlay_hide_get(const Elm_Map_Overlay *overlay)
4833{
4834#ifdef HAVE_ELEMENTARY_ECORE_CON
4835 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, EINA_FALSE);
4836 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, EINA_FALSE);
4837 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) EINA_FALSE;
4838
4839 return overlay->hide;
4840#else
4841 (void) overlay;
4842 return EINA_FALSE;
4843#endif
4844}
4845
4846EAPI void
4847elm_map_overlay_displayed_zoom_min_set(Elm_Map_Overlay *overlay, int zoom)
4848{
4849#ifdef HAVE_ELEMENTARY_ECORE_CON
4850 EINA_SAFETY_ON_NULL_RETURN(overlay);
4851 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4852 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4853
4854 overlay->zoom_min = zoom;
4855 evas_object_smart_changed(overlay->wd->pan_smart);
4856#else
4857 (void) overlay;
4858 (void) zoom;
4859#endif
4860}
4861
4862EAPI int
4863elm_map_overlay_displayed_zoom_min_get(const Elm_Map_Overlay *overlay)
4864{
4865#ifdef HAVE_ELEMENTARY_ECORE_CON
4866 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, 0);
4867 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, 0);
4868 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) 0;
4869
4870 return overlay->zoom_min;
4871#else
4872 (void) overlay;
4873 return 0;
4874#endif
4875}
4876
4877EAPI void
4878elm_map_overlay_paused_set(Elm_Map_Overlay *overlay, Eina_Bool paused)
4879{
4880#ifdef HAVE_ELEMENTARY_ECORE_CON
4881 EINA_SAFETY_ON_NULL_RETURN(overlay);
4882 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4883 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4884
4885 if (overlay->paused == !!paused) return;
4886 overlay->paused = paused;
4887
4888 evas_object_smart_changed(overlay->wd->pan_smart);
4889#else
4890 (void) overlay;
4891 (void) paused;
4892#endif
4893}
4894
4895EAPI Eina_Bool
4896elm_map_overlay_paused_get(const Elm_Map_Overlay *overlay)
4897{
4898#ifdef HAVE_ELEMENTARY_ECORE_CON
4899 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, EINA_FALSE);
4900 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, EINA_FALSE);
4901 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) EINA_FALSE;
4902
4903 return overlay->paused;
4904#else
4905 (void) overlay;
4906 return EINA_FALSE;
4907#endif
4908}
4909
4910EAPI void
4911elm_map_overlay_show(Elm_Map_Overlay *overlay)
4912{
4913#ifdef HAVE_ELEMENTARY_ECORE_CON
4914 EINA_SAFETY_ON_NULL_RETURN(overlay);
4915 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4916 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4917
4918 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
4919 {
4920 Overlay_Default *ovl = overlay->ovl;
4921 elm_map_region_show(overlay->wd->obj, ovl->lon, ovl->lat);
4922 }
4923 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
4924 {
4925 Overlay_Bubble *ovl = overlay->ovl;
4926 elm_map_region_show(overlay->wd->obj, ovl->lon, ovl->lat);
4927 }
4928 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
4929 {
4930 Overlay_Class *ovl = overlay->ovl;
4931 double lon, lat, max_lo, min_lo, max_la, min_la;
4932 _region_max_min_get(ovl->members, &max_lo, &min_lo, &max_la, &min_la);
4933 lon = (max_lo + min_lo) / 2;
4934 lat = (max_la + min_la) / 2;
4935 elm_map_region_show(overlay->wd->obj, lon, lat);
4936 }
4937 else ERR("Not supported overlay type: %d", overlay->type);
4938
4939 evas_object_smart_changed(overlay->wd->pan_smart);
4940#else
4941 (void) overlay;
4942#endif
4943}
4944
4945EAPI void
4946elm_map_overlays_show(Eina_List *overlays)
4947{
4948#ifdef HAVE_ELEMENTARY_ECORE_CON
4949 EINA_SAFETY_ON_NULL_RETURN(overlays);
4950 EINA_SAFETY_ON_FALSE_RETURN(eina_list_count(overlays));
4951
4952 Elm_Map_Overlay *overlay;
4953 overlay = eina_list_data_get(overlays);
4954
4955 Delayed_Data *data = ELM_NEW(Delayed_Data);
4956 data->func = _overlays_show;
4957 data->wd = overlay->wd;
4958 data->overlays = eina_list_clone(overlays);
4959 data->wd->delayed_jobs = eina_list_append(data->wd->delayed_jobs, data);
4960 evas_object_smart_changed(data->wd->pan_smart);
4961#else
4962 (void) overlays;
4963#endif
4964}
4965
4966EAPI void
4967elm_map_overlay_region_set(Elm_Map_Overlay *overlay, double lon, double lat)
4968{
4969#ifdef HAVE_ELEMENTARY_ECORE_CON
4970 EINA_SAFETY_ON_NULL_RETURN(overlay);
4971 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
4972 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
4973
4974 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
4975 {
4976 Overlay_Default *ovl = overlay->ovl;
4977 ovl->lon = lon;
4978 ovl->lat = lat;
4979 }
4980 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
4981 {
4982 Overlay_Bubble *ovl = overlay->ovl;
4983 ovl->lon = lon;
4984 ovl->lat = lat;
4985 }
4986 else ERR("Not supported overlay type: %d", overlay->type);
4987
4988 evas_object_smart_changed(overlay->wd->pan_smart);
4989#else
4990 (void) overlay;
4991 (void) lon;
4992 (void) lat;
4993#endif
4994}
4995
4996EAPI void
4997elm_map_overlay_region_get(const Elm_Map_Overlay *overlay, double *lon, double *lat)
4998{
4999#ifdef HAVE_ELEMENTARY_ECORE_CON
5000 EINA_SAFETY_ON_NULL_RETURN(overlay);
5001 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
5002 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5003
5004 if (overlay->type == ELM_MAP_OVERLAY_TYPE_GROUP)
5005 {
5006 Overlay_Group *ovl = overlay->ovl;
5007 _overlay_group_region_get(ovl, lon, lat);
5008 }
5009 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5010 {
5011 const Overlay_Default *ovl = overlay->ovl;
5012 if (lon) *lon = ovl->lon;
5013 if (lat) *lat = ovl->lat;
5014 }
5015 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_BUBBLE)
5016 {
5017 const Overlay_Bubble *ovl = overlay->ovl;
5018 if (lon) *lon = ovl->lon;
5019 if (lat) *lat = ovl->lat;
5020 }
5021 else ERR("Not supported overlay type: %d", overlay->type);
5022#else
5023 (void) overlay;
5024 (void) lon;
5025 (void) lat;
5026#endif
5027}
5028
5029EAPI void
5030elm_map_overlay_icon_set(Elm_Map_Overlay *overlay, Evas_Object *icon)
5031{
5032#ifdef HAVE_ELEMENTARY_ECORE_CON
5033 EINA_SAFETY_ON_NULL_RETURN(overlay);
5034 EINA_SAFETY_ON_NULL_RETURN(icon);
5035 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
5036 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5037
5038 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5039 _overlay_default_icon_update(overlay->ovl, icon);
5040 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5041 _overlay_class_icon_update(overlay->ovl, icon);
5042 else ERR("Not supported overlay type: %d", overlay->type);
5043
5044 evas_object_smart_changed(overlay->wd->pan_smart);
5045#else
5046 (void) overlay;
5047 (void) icon;
5048#endif
5049}
5050
5051EAPI const Evas_Object *
5052elm_map_overlay_icon_get(const Elm_Map_Overlay *overlay)
5053{
5054#ifdef HAVE_ELEMENTARY_ECORE_CON
5055 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
5056 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, NULL);
5057 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) NULL;
5058
5059 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5060 {
5061 const Overlay_Default *ovl = overlay->ovl;
5062 return ovl->icon;
5063 }
5064 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5065 {
5066 const Overlay_Class *ovl = overlay->ovl;
5067 return ovl->icon;
5068 }
5069 else
5070 {
5071 ERR("Not supported overlay type: %d", overlay->type);
5072 return NULL;
5073 }
5074#else
5075 (void) overlay;
5076 return NULL;
5077#endif
5078}
5079
5080EAPI void
5081elm_map_overlay_content_set(Elm_Map_Overlay *overlay, Evas_Object *content)
5082{
5083#ifdef HAVE_ELEMENTARY_ECORE_CON
5084 EINA_SAFETY_ON_NULL_RETURN(overlay);
5085 EINA_SAFETY_ON_NULL_RETURN(content);
5086 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
5087 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5088
5089 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5090 _overlay_default_content_update(overlay->ovl, content, overlay);
5091 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5092 _overlay_class_content_update(overlay->ovl, content);
5093 else ERR("Not supported overlay type: %d", overlay->type);
5094
5095 evas_object_smart_changed(overlay->wd->pan_smart);
5096#else
5097 (void) overlay;
5098 (void) obj;
5099#endif
5100}
5101
5102EAPI const Evas_Object *
5103elm_map_overlay_content_get(const Elm_Map_Overlay *overlay)
5104{
5105#ifdef HAVE_ELEMENTARY_ECORE_CON
5106 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay, NULL);
5107 EINA_SAFETY_ON_NULL_RETURN_VAL(overlay->wd, NULL);
5108 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype) NULL;
5109
5110 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5111 {
5112 const Overlay_Default *ovl = overlay->ovl;
5113 return ovl->content;
5114 }
5115 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5116 {
5117 const Overlay_Class *ovl = overlay->ovl;
5118 return ovl->content;
5119 }
5120 else
5121 {
5122 ERR("Not supported overlay type: %d", overlay->type);
5123 return NULL;
5124 }
5125#else
5126 (void) overlay;
5127 return NULL;
5128#endif
5129}
5130
5131EAPI void
5132elm_map_overlay_color_set(Elm_Map_Overlay *overlay, int r, int g , int b, int a)
5133{
5134#ifdef HAVE_ELEMENTARY_ECORE_CON
5135 EINA_SAFETY_ON_NULL_RETURN(overlay);
5136 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
5137 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5138
5139 overlay->c.r = r;
5140 overlay->c.g = g;
5141 overlay->c.b = b;
5142 overlay->c.a = a;
5143
5144 if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5145 _overlay_class_color_update(overlay->ovl, overlay->c);
5146 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5147 _overlay_default_color_update(overlay->ovl, overlay->c);
5148 else if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
5149 _overlay_route_color_update(overlay->ovl, overlay->c);
5150 else
5151 {
5152 ERR("Not supported overlay type: %d", overlay->type);
5153 }
5154
5155#else
5156 (void) overlay;
5157 (void) r;
5158 (void) g;
5159 (void) b;
5160 (void) a;
5161#endif
5162}
5163
5164EAPI void
5165elm_map_overlay_color_get(const Elm_Map_Overlay *overlay, int *r, int *g , int *b, int *a)
5166{
5167#ifdef HAVE_ELEMENTARY_ECORE_CON
5168 EINA_SAFETY_ON_NULL_RETURN(overlay);
5169 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
5170 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5171
5172 if (overlay->type == ELM_MAP_OVERLAY_TYPE_ROUTE)
5173 {
5174 if (r) *r = overlay->c.r;
5175 if (g) *g = overlay->c.g;
5176 if (b) *b = overlay->c.b;
5177 if (a) *a = overlay->c.a;
5178 }
5179 else ERR("Not supported overlay type: %d", overlay->type);
5180#else
5181 (void) overlay;
5182 (void) r;
5183 (void) g;
5184 (void) b;
5185 (void) a;
5186#endif
5187}
5188
5189EAPI void
5190elm_map_overlay_get_cb_set(Elm_Map_Overlay *overlay, Elm_Map_Overlay_Get_Cb get_cb, void *data)
5191{
5192#ifdef HAVE_ELEMENTARY_ECORE_CON
5193 EINA_SAFETY_ON_NULL_RETURN(overlay);
5194 EINA_SAFETY_ON_NULL_RETURN(overlay->wd);
5195 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5196
5197 overlay->cb = get_cb;
5198 overlay->cb_data = data;
5199
5200 if (overlay->type == ELM_MAP_OVERLAY_TYPE_CLASS)
5201 _overlay_class_cb_set(overlay->ovl, get_cb, data);
5202#else
5203 (void) overlay;
5204 (void) get_cb;
5205 (void) data;
5206#endif
5207}
5208
5209EAPI Elm_Map_Overlay *
5210elm_map_overlay_class_add(Evas_Object *obj)
5211{
5212#ifdef HAVE_ELEMENTARY_ECORE_CON
5213 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5214 Widget_Data *wd = elm_widget_data_get(obj);
5215 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5216
5217 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5218 overlay->wd = wd;
5219 overlay->type = ELM_MAP_OVERLAY_TYPE_CLASS;
5220 overlay->ovl = _overlay_class_new(wd);
5221 overlay->c.r = 0x90;
5222 overlay->c.g = 0xee;
5223 overlay->c.b = 0x90;
5224 overlay->c.a = 0xff;
5225 wd->overlays = eina_list_append(wd->overlays, overlay);
5226
5227 evas_object_smart_changed(wd->pan_smart);
5228 return overlay;
5229#else
5230 (void) obj;
5231 return NULL;
5232#endif
5233}
5234
5235EAPI void
5236elm_map_overlay_class_append(Elm_Map_Overlay *clas, Elm_Map_Overlay *overlay)
5237{
5238#ifdef HAVE_ELEMENTARY_ECORE_CON
5239 EINA_SAFETY_ON_NULL_RETURN(clas);
5240 EINA_SAFETY_ON_NULL_RETURN(overlay);
5241 EINA_SAFETY_ON_NULL_RETURN(clas->wd);
5242 ELM_CHECK_WIDTYPE(clas->wd->obj, widtype);
5243 EINA_SAFETY_ON_FALSE_RETURN(clas->type == ELM_MAP_OVERLAY_TYPE_CLASS);
5244
5245 Overlay_Class *clas_ovl = clas->ovl;
5246 if (eina_list_data_find(clas_ovl->members, overlay))
5247 {
5248 ERR("Already added overlay into clas");
5249 return;
5250 }
5251 clas_ovl->members = eina_list_append(clas_ovl->members, overlay);
5252
5253 // Update group by class
5254 overlay->grp->clas = clas;
5255 _overlay_group_icon_update(overlay->grp, clas_ovl->icon);
5256 _overlay_group_content_update(overlay->grp, clas_ovl->content);
5257 _overlay_group_color_update(overlay->grp, clas->c);
5258 _overlay_group_cb_set(overlay->grp, clas->cb, clas->data);
5259 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5260 {
5261 _overlay_default_clas_icon_update(overlay->ovl, clas_ovl->icon);
5262 _overlay_default_clas_content_update(overlay->ovl, clas_ovl->content);
5263 }
5264
5265 evas_object_smart_changed(clas->wd->pan_smart);
5266#else
5267 (void) clas;
5268 (void) overlay;
5269#endif
5270}
5271
5272EAPI void
5273elm_map_overlay_class_remove(Elm_Map_Overlay *clas, Elm_Map_Overlay *overlay)
5274{
5275#ifdef HAVE_ELEMENTARY_ECORE_CON
5276 EINA_SAFETY_ON_NULL_RETURN(clas);
5277 EINA_SAFETY_ON_NULL_RETURN(overlay);
5278 EINA_SAFETY_ON_NULL_RETURN(clas->wd);
5279 ELM_CHECK_WIDTYPE(clas->wd->obj, widtype);
5280 EINA_SAFETY_ON_FALSE_RETURN(clas->type == ELM_MAP_OVERLAY_TYPE_CLASS);
5281
5282 Overlay_Class *ovl = clas->ovl;
5283 ovl->members = eina_list_remove(ovl->members, overlay);
5284
5285 overlay->grp->clas = NULL;
5286 _overlay_group_icon_update(overlay->grp, NULL);
5287 _overlay_group_content_update(overlay->grp, NULL);
5288 if (overlay->type == ELM_MAP_OVERLAY_TYPE_DEFAULT)
5289 {
5290 _overlay_default_clas_icon_update(overlay->ovl, NULL);
5291 _overlay_default_clas_content_update(overlay->ovl, NULL);
5292 }
5293
5294 evas_object_smart_changed(clas->wd->pan_smart);
5295#else
5296 (void) clas;
5297 (void) overlay;
5298#endif
5299}
5300
5301EAPI void
5302elm_map_overlay_class_zoom_max_set(Elm_Map_Overlay *clas, int zoom)
5303{
5304#ifdef HAVE_ELEMENTARY_ECORE_CON
5305 EINA_SAFETY_ON_NULL_RETURN(clas);
5306 EINA_SAFETY_ON_NULL_RETURN(clas->wd);
5307 ELM_CHECK_WIDTYPE(clas->wd->obj, widtype);
5308 EINA_SAFETY_ON_FALSE_RETURN(clas->type == ELM_MAP_OVERLAY_TYPE_CLASS);
5309
5310 Overlay_Class *ovl = clas->ovl;
5311 if (ovl->zoom_max == !!zoom) return;
5312 ovl->zoom_max = zoom;
5313
5314 evas_object_smart_changed(clas->wd->pan_smart);
5315#else
5316 (void) clas;
5317 (void) zoom;
5318#endif
5319}
5320
5321EAPI int
5322elm_map_overlay_class_zoom_max_get(const Elm_Map_Overlay *clas)
5323{
5324#ifdef HAVE_ELEMENTARY_ECORE_CON
5325 EINA_SAFETY_ON_NULL_RETURN_VAL(clas, OVERLAY_CLASS_ZOOM_MAX);
5326 EINA_SAFETY_ON_NULL_RETURN_VAL(clas->wd, OVERLAY_CLASS_ZOOM_MAX);
5327 ELM_CHECK_WIDTYPE(clas->wd->obj, widtype) OVERLAY_CLASS_ZOOM_MAX;
5328 EINA_SAFETY_ON_FALSE_RETURN_VAL(clas->type == ELM_MAP_OVERLAY_TYPE_CLASS, OVERLAY_CLASS_ZOOM_MAX);
5329
5330 const Overlay_Class *ovl = clas->ovl;
5331 return ovl->zoom_max;
5332#else
5333 (void) clas;
5334 return OVERLAY_CLASS_ZOOM_MAX;
5335#endif
5336}
5337
5338EAPI Eina_List *
5339elm_map_overlay_group_members_get(const Elm_Map_Overlay *grp)
5340{
5341#ifdef HAVE_ELEMENTARY_ECORE_CON
5342 EINA_SAFETY_ON_NULL_RETURN_VAL(grp, NULL);
5343 EINA_SAFETY_ON_NULL_RETURN_VAL(grp->wd, NULL);
5344 ELM_CHECK_WIDTYPE(grp->wd->obj, widtype) NULL;
5345 EINA_SAFETY_ON_FALSE_RETURN_VAL(grp->type == ELM_MAP_OVERLAY_TYPE_GROUP, NULL);
5346
5347 Overlay_Group *ovl = grp->ovl;
5348 return ovl->members;
5349#else
5350 (void) clas;
5351 return OVERLAY_CLASS_ZOOM_MAX;
5352#endif
5353}
5354
5355EAPI Elm_Map_Overlay *
5356elm_map_overlay_bubble_add(Evas_Object *obj)
5357{
5358#ifdef HAVE_ELEMENTARY_ECORE_CON
5359 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5360 Widget_Data *wd = elm_widget_data_get(obj);
5361 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5362
5363 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5364 overlay->wd = wd;
5365 overlay->type = ELM_MAP_OVERLAY_TYPE_BUBBLE;
5366 overlay->c.r = 255;
5367 overlay->c.g = 255;
5368 overlay->c.b = 255;
5369 overlay->c.a = 255;
5370 overlay->ovl = _overlay_bubble_new(overlay);
5371 overlay->grp = _overlay_group_new(wd);
5372 wd->overlays = eina_list_append(wd->overlays, overlay);
5373
5374 evas_object_smart_changed(wd->pan_smart);
5375 return overlay;
5376#else
5377 (void) obj;
5378 return NULL;
5379#endif
5380}
5381
5382EAPI void
5383elm_map_overlay_bubble_follow(Elm_Map_Overlay *bubble, const Elm_Map_Overlay *parent)
5384{
5385#ifdef HAVE_ELEMENTARY_ECORE_CON
5386 EINA_SAFETY_ON_NULL_RETURN(bubble);
5387 EINA_SAFETY_ON_NULL_RETURN(parent);
5388 ELM_CHECK_WIDTYPE(bubble->wd->obj, widtype);
5389 EINA_SAFETY_ON_FALSE_RETURN(bubble->type == ELM_MAP_OVERLAY_TYPE_BUBBLE);
5390
5391 Overlay_Bubble *ovl = bubble->ovl;
5392 Evas_Object *pobj = _overlay_obj_get(parent);
5393 if (!pobj) return;
5394
5395 if (ovl->pobj)
5396 {
5397 evas_object_event_callback_del_full(ovl->pobj, EVAS_CALLBACK_HIDE,
5398 _overlay_bubble_hide_cb, ovl);
5399 evas_object_event_callback_del_full(ovl->pobj, EVAS_CALLBACK_SHOW,
5400 _overlay_bubble_chase_cb, ovl);
5401 evas_object_event_callback_del_full(ovl->pobj, EVAS_CALLBACK_MOVE,
5402 _overlay_bubble_chase_cb, ovl);
5403 }
5404
5405 ovl->pobj = pobj;
5406 evas_object_event_callback_add(ovl->pobj, EVAS_CALLBACK_HIDE,
5407 _overlay_bubble_hide_cb, ovl);
5408 evas_object_event_callback_add(ovl->pobj, EVAS_CALLBACK_SHOW,
5409 _overlay_bubble_chase_cb, ovl);
5410 evas_object_event_callback_add(ovl->pobj, EVAS_CALLBACK_MOVE,
5411 _overlay_bubble_chase_cb, ovl);
5412
5413 _overlay_bubble_chase(ovl);
5414 evas_object_smart_changed(bubble->wd->pan_smart);
5415#else
5416 (void) bubble;
5417 (void) parent;
5418#endif
5419}
5420
5421EAPI void
5422elm_map_overlay_bubble_content_append(Elm_Map_Overlay *bubble, Evas_Object *content)
5423{
5424#ifdef HAVE_ELEMENTARY_ECORE_CON
5425 EINA_SAFETY_ON_NULL_RETURN(bubble);
5426 EINA_SAFETY_ON_NULL_RETURN(content);
5427 ELM_CHECK_WIDTYPE(bubble->wd->obj, widtype);
5428 EINA_SAFETY_ON_FALSE_RETURN(bubble->type == ELM_MAP_OVERLAY_TYPE_BUBBLE);
5429
5430 Overlay_Bubble *bb = bubble->ovl;
5431 elm_box_pack_end(bb->bx, content);
5432
5433 evas_object_smart_changed(bubble->wd->pan_smart);
5434#else
5435 (void) bubble;
5436 (void) content;
5437#endif
5438}
5439
5440EAPI void
5441elm_map_overlay_bubble_content_clear(Elm_Map_Overlay *bubble)
5442{
5443#ifdef HAVE_ELEMENTARY_ECORE_CON
5444 EINA_SAFETY_ON_NULL_RETURN(bubble);
5445 ELM_CHECK_WIDTYPE(bubble->wd->obj, widtype);
5446 EINA_SAFETY_ON_FALSE_RETURN(bubble->type == ELM_MAP_OVERLAY_TYPE_BUBBLE);
5447
5448 Overlay_Bubble *bb = bubble->ovl;
5449 elm_box_clear(bb->bx);
5450
5451 evas_object_smart_changed(bubble->wd->pan_smart);
5452#else
5453 (void) bubble;
5454#endif
5455}
5456
5457EAPI Elm_Map_Overlay *
5458elm_map_overlay_route_add(Evas_Object *obj, const Elm_Map_Route *route)
5459{
5460#ifdef HAVE_ELEMENTARY_ECORE_CON
5461 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5462 Widget_Data *wd = elm_widget_data_get(obj);
5463 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5464 EINA_SAFETY_ON_NULL_RETURN_VAL(route, NULL);
5465 EINA_SAFETY_ON_NULL_RETURN_VAL(route->wd, NULL);
5466 EINA_SAFETY_ON_FALSE_RETURN_VAL(obj == route->wd->obj, NULL);
5467
5468 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5469 overlay->wd = wd;
5470 overlay->type = ELM_MAP_OVERLAY_TYPE_ROUTE;
5471 overlay->c.r = 0xff;
5472 overlay->c.g = 0x00;
5473 overlay->c.b = 0x00;
5474 overlay->c.a = 0xff;
5475 overlay->ovl = _overlay_route_new(wd, route, overlay->c);
5476 overlay->grp = _overlay_group_new(wd);
5477 wd->overlays = eina_list_append(wd->overlays, overlay);
5478
5479 evas_object_smart_changed(wd->pan_smart);
5480 return overlay;
5481#else
5482 (void) obj;
5483 (void) route;
5484 return NULL;
5485#endif
5486}
5487
5488EAPI Elm_Map_Overlay *
5489elm_map_overlay_line_add(Evas_Object *obj, double flon, double flat, double tlon, double tlat)
5490{
5491#ifdef HAVE_ELEMENTARY_ECORE_CON
5492 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5493 Widget_Data *wd = elm_widget_data_get(obj);
5494 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5495
5496 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5497 overlay->wd = wd;
5498 overlay->type = ELM_MAP_OVERLAY_TYPE_LINE;
5499 overlay->c.r = 0xff;
5500 overlay->c.g = 0x00;
5501 overlay->c.b = 0x00;
5502 overlay->c.a = 0xff;
5503 overlay->ovl = _overlay_line_new(wd, flon, flat, tlon, tlat, overlay->c);
5504 overlay->grp = _overlay_group_new(wd);
5505 wd->overlays = eina_list_append(wd->overlays, overlay);
5506
5507 evas_object_smart_changed(wd->pan_smart);
5508 return overlay;
5509#else
5510 (void) obj;
5511 (void) flon;
5512 (void) flat
5513 (void) tlon;
5514 (void) tlat;
5515 return NULL;
5516#endif
5517}
5518
5519EAPI Elm_Map_Overlay *
5520elm_map_overlay_polygon_add(Evas_Object *obj)
5521{
5522#ifdef HAVE_ELEMENTARY_ECORE_CON
5523 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5524 Widget_Data *wd = elm_widget_data_get(obj);
5525 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5526
5527 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5528 overlay->wd = wd;
5529 overlay->type = ELM_MAP_OVERLAY_TYPE_POLYGON;
5530 overlay->c.r = 0xdc;
5531 overlay->c.g = 0x14;
5532 overlay->c.b = 0x3c;
5533 overlay->c.a = 200;
5534 overlay->ovl = _overlay_polygon_new(wd, overlay->c);
5535 overlay->grp = _overlay_group_new(wd);
5536 wd->overlays = eina_list_append(wd->overlays, overlay);
5537 evas_object_smart_changed(wd->pan_smart);
5538 return overlay;
5539#else
5540 (void) obj;
5541 return NULL;
5542#endif
5543}
5544
5545EAPI void
5546elm_map_overlay_polygon_region_add(Elm_Map_Overlay *overlay, double lon, double lat)
5547{
5548#ifdef HAVE_ELEMENTARY_ECORE_CON
5549 EINA_SAFETY_ON_NULL_RETURN(overlay);
5550 ELM_CHECK_WIDTYPE(overlay->wd->obj, widtype);
5551 EINA_SAFETY_ON_FALSE_RETURN(overlay->type == ELM_MAP_OVERLAY_TYPE_POLYGON);
5552
5553 Overlay_Polygon *ovl = overlay->ovl;
5554 Region *r = ELM_NEW(Region);
5555 r->lon = lon;
5556 r->lat = lat;
5557 ovl->regions = eina_list_append(ovl->regions, r);
5558
5559 evas_object_smart_changed(ovl->wd->pan_smart);
5560#else
5561 (void) overlay;
5562 (void) lon;
5563 (void) lat
5564 #endif
5565}
5566
5567EAPI Elm_Map_Overlay *
5568elm_map_overlay_circle_add(Evas_Object *obj, double lon, double lat, double radius)
5569{
5570#ifdef HAVE_ELEMENTARY_ECORE_CON
5571 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5572 Widget_Data *wd = elm_widget_data_get(obj);
5573 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5574
5575 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5576 overlay->wd = wd;
5577 overlay->type = ELM_MAP_OVERLAY_TYPE_CIRCLE;
5578 overlay->c.r = 0xdc;
5579 overlay->c.g = 0x14;
5580 overlay->c.b = 0x3c;
5581 overlay->c.a = 200;
5582 overlay->ovl = _overlay_circle_new(wd, lon, lat, radius, overlay->c);
5583 overlay->grp = _overlay_group_new(wd);
5584 wd->overlays = eina_list_append(wd->overlays, overlay);
5585
5586 evas_object_smart_changed(wd->pan_smart);
5587 return overlay;
5588#else
5589 (void) obj;
5590 return NULL;
5591#endif
5592}
5593
5594EAPI Elm_Map_Overlay *
5595elm_map_overlay_scale_add(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
5596{
5597#ifdef HAVE_ELEMENTARY_ECORE_CON
5598 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5599 Widget_Data *wd = elm_widget_data_get(obj);
5600 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, NULL);
5601
5602 Elm_Map_Overlay *overlay = ELM_NEW(Elm_Map_Overlay);
5603 overlay->wd = wd;
5604 overlay->type = ELM_MAP_OVERLAY_TYPE_SCALE;
5605 overlay->c.r = 0;
5606 overlay->c.g = 0;
5607 overlay->c.b = 0;
5608 overlay->c.a = 255;
5609 overlay->ovl = _overlay_scale_new(wd, x, y, overlay->c);
5610 overlay->grp = _overlay_group_new(wd);
5611 wd->overlays = eina_list_append(wd->overlays, overlay);
5612
5613 evas_object_smart_changed(wd->pan_smart);
5614 return overlay;
5615#else
5616 (void) obj;
5617 return NULL;
5618#endif
5619}
5620
5621#ifdef ELM_EMAP
5622EAPI Evas_Object *
5623elm_map_track_add(Evas_Object *obj, void *emap)
5624{
5625#ifdef HAVE_ELEMENTARY_ECORE_CON
5626 EMap_Route *emapr = emap;
5627 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
5628 Widget_Data *wd = elm_widget_data_get(obj);
5629 EINA_SAFETY_ON_NULL_RETURN_VAL(wd, EINA_FALSE);
5630
5631 Evas_Object *route = elm_route_add(obj);
5632 elm_route_emap_set(route, emapr);
5633 wd->track = eina_list_append(wd->track, route);
5634
5635 return route;
5636#else
5637 (void) obj;
5638 (void) emap;
5639 return NULL;
5640#endif
5641}
5642
5643EAPI void
5644elm_map_track_remove(Evas_Object *obj, Evas_Object *route)
5645{
5646#ifdef HAVE_ELEMENTARY_ECORE_CON
5647 ELM_CHECK_WIDTYPE(obj, widtype) ;
5648 Widget_Data *wd = elm_widget_data_get(obj);
5649 EINA_SAFETY_ON_NULL_RETURN(wd);
5650
5651 wd->track = eina_list_remove(wd->track, route);
5652 evas_object_del(route);
5653#else
5654 (void) obj;
5655 (void) route;
5656#endif
5657}
5658#else
5659EAPI Evas_Object *
5660elm_map_track_add(Evas_Object *obj __UNUSED__, void *emap __UNUSED__)
5661{
5662 return NULL;
5663}
5664
5665EAPI void
5666elm_map_track_remove(Evas_Object *obj __UNUSED__, Evas_Object *route __UNUSED__)
5667{
5668}
5669#endif
diff --git a/libraries/elementary/src/lib/elm_map.h b/libraries/elementary/src/lib/elm_map.h
new file mode 100644
index 0000000..c7b58df
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_map.h
@@ -0,0 +1,1503 @@
1/**
2 * @defgroup Map Map
3 * @ingroup Elementary
4 *
5 * @image html img/widget/map/preview-00.png
6 * @image latex img/widget/map/preview-00.eps
7 *
8 * This is a widget specifically for displaying a map. It uses basically
9 * OpenStreetMap provider http://www.openstreetmap.org/,
10 * but custom providers can be added.
11 *
12 * It supports some basic but yet nice features:
13 * @li zoom and scroll
14 * @li markers with content to be displayed when user clicks over it
15 * @li group of markers
16 * @li routes
17 *
18 * Smart callbacks one can listen to:
19 *
20 * - "clicked" - This is called when a user has clicked the map without
21 * dragging around.
22 * - "clicked,double" - This is called when a user has double-clicked
23 * the map.
24 * - "press" - This is called when a user has pressed down on the map.
25 * - "longpressed" - This is called when a user has pressed down on the map
26 * for a long time without dragging around.
27 * - "scroll" - the content has been scrolled (moved).
28 * - "scroll,drag,start" - dragging the contents around has started.
29 * - "scroll,drag,stop" - dragging the contents around has stopped.
30 * - "scroll,anim,start" - scrolling animation has started.
31 * - "scroll,anim,stop" - scrolling animation has stopped.
32 * - "zoom,start" - Zoom animation started.
33 * - "zoom,stop" - Zoom animation stopped.
34 * - "zoom,change" - Zoom changed when using an auto zoom mode.
35 * - "tile,load" - A map tile image load begins.
36 * - "tile,loaded" - A map tile image load ends.
37 * - "tile,loaded,fail" - A map tile image load fails.
38 * - "route,load" - Route request begins.
39 * - "route,loaded" - Route request ends.
40 * - "route,loaded,fail" - Route request fails.
41 * - "name,load" - Name request begins.
42 * - "name,loaded" - Name request ends.
43 * - "name,loaded,fail" - Name request fails.
44 * - "overlay,clicked" - A overlay is clicked.
45 *
46 * Available style for map widget:
47 * - @c "default"
48 *
49 * Available style for markers:
50 * - @c "radio"
51 * - @c "radio2"
52 * - @c "empty"
53 *
54 * Available style for marker bubble:
55 * - @c "default"
56 *
57 * List of examples:
58 * @li @ref map_example_01
59 * @li @ref map_example_02
60 * @li @ref map_example_03
61 */
62
63/**
64 * @addtogroup Map
65 * @{
66 */
67
68/**
69 * Set map's zoom behavior. It can be set to manual or automatic.
70 *
71 * Default value is #ELM_MAP_ZOOM_MODE_MANUAL.
72 *
73 * Values <b> don't </b> work as bitmask, only one can be chosen.
74 *
75 * @note Valid sizes are 2^zoom, consequently the map may be smaller
76 * than the scroller view.
77 *
78 * @see elm_map_zoom_mode_set()
79 * @see elm_map_zoom_mode_get()
80 *
81 * @ingroup Map
82 */
83typedef enum
84{
85 ELM_MAP_ZOOM_MODE_MANUAL, /**< Zoom controlled manually by elm_map_zoom_set(). It's set by default. */
86 ELM_MAP_ZOOM_MODE_AUTO_FIT, /**< Zoom until map fits inside the scroll frame with no pixels outside this area. */
87 ELM_MAP_ZOOM_MODE_AUTO_FILL, /**< Zoom until map fills scroll, ensuring no pixels are left unfilled. */
88 ELM_MAP_ZOOM_MODE_LAST
89} Elm_Map_Zoom_Mode;
90
91/**
92 * Set type of a external source (provider).
93 *
94 * @see elm_map_sources_get()
95 * @see elm_map_source_get()
96 * @see elm_map_source_set()
97 *
98 * @ingroup Map
99 */
100typedef enum
101{
102 ELM_MAP_SOURCE_TYPE_TILE, /**< Map tile provider. */
103 ELM_MAP_SOURCE_TYPE_ROUTE, /**< Route service provider. */
104 ELM_MAP_SOURCE_TYPE_NAME, /**< Name service provider. */
105 ELM_MAP_SOURCE_TYPE_LAST
106} Elm_Map_Source_Type;
107
108/**
109 * Set type of transport used on route.
110 *
111 * @see elm_map_route_add()
112 *
113 * @ingroup Map
114 */
115typedef enum
116{
117 ELM_MAP_ROUTE_TYPE_MOTOCAR, /**< Route should consider an automobile will be used. */
118 ELM_MAP_ROUTE_TYPE_BICYCLE, /**< Route should consider a bicycle will be used by the user. */
119 ELM_MAP_ROUTE_TYPE_FOOT, /**< Route should consider user will be walking. */
120 ELM_MAP_ROUTE_TYPE_LAST
121} Elm_Map_Route_Type;
122
123/**
124 * Set the routing method, what should be prioritized, time or distance.
125 *
126 * @see elm_map_route_add()
127 *
128 * @ingroup Map
129 */
130typedef enum
131{
132 ELM_MAP_ROUTE_METHOD_FASTEST, /**< Route should prioritize time. */
133 ELM_MAP_ROUTE_METHOD_SHORTEST, /**< Route should prioritized distance. */
134 ELM_MAP_ROUTE_METHOD_LAST
135} Elm_Map_Route_Method;
136
137/**
138 * Set the name search method.
139 *
140 * This is for name module interface.
141 *
142 * @ingroup Map
143 */
144typedef enum
145{
146 ELM_MAP_NAME_METHOD_SEARCH,
147 ELM_MAP_NAME_METHOD_REVERSE,
148 ELM_MAP_NAME_METHOD_LAST
149} Elm_Map_Name_Method;
150
151/**
152 * Set overlay type to be used. This type is resolved
153 * when the overlay is created.
154 * You can get this value by elm_map_overlay_type_get().
155 *
156 * @see elm_map_overlay_type_get()
157 * @see elm_map_overlay_add()
158 * @see elm_map_overlay_class_add()
159 * @see elm_map_overlay_bubble_add()
160 *
161 * @ingroup Map
162 */
163typedef enum _Elm_Map_Overlay_Type
164{
165 ELM_MAP_OVERLAY_TYPE_NONE = 0,
166 ELM_MAP_OVERLAY_TYPE_DEFAULT,
167 ELM_MAP_OVERLAY_TYPE_CLASS,
168 ELM_MAP_OVERLAY_TYPE_GROUP,
169 ELM_MAP_OVERLAY_TYPE_BUBBLE,
170 ELM_MAP_OVERLAY_TYPE_ROUTE,
171 ELM_MAP_OVERLAY_TYPE_LINE,
172 ELM_MAP_OVERLAY_TYPE_POLYGON,
173 ELM_MAP_OVERLAY_TYPE_CIRCLE,
174 ELM_MAP_OVERLAY_TYPE_SCALE
175
176} Elm_Map_Overlay_Type;
177
178typedef struct _Elm_Map_Marker Elm_Map_Marker; /**< A marker to be shown in a specific point of the map. Can be created with elm_map_marker_add() and deleted with elm_map_marker_remove(). */
179typedef struct _Elm_Map_Marker_Class Elm_Map_Marker_Class; /**< Each marker must be associated to a class. It's required to add a mark. The class defines the style of the marker when a marker is displayed alone (not grouped). A new class can be created with elm_map_marker_class_new(). */
180typedef struct _Elm_Map_Group_Class Elm_Map_Group_Class; /**< Each marker must be associated to a group class. It's required to add a mark. The group class defines the style of the marker when a marker is grouped to other markers. Markers with the same group are grouped if they are close. A new group class can be created with elm_map_marker_group_class_new(). */
181typedef struct _Elm_Map_Route Elm_Map_Route; /**< A route to be shown in the map. Can be created with elm_map_route_add() and deleted with elm_map_route_remove(). */
182typedef struct _Elm_Map_Name Elm_Map_Name; /**< A handle for specific coordinates. */
183typedef struct _Elm_Map_Overlay Elm_Map_Overlay; /**< A overlay to be shown in a specific point of the map. This can be created by elm_map_overlay_add() and similar functions and deleted by elm_map_overlay_del(). */
184
185typedef Evas_Object *(*Elm_Map_Marker_Get_Func)(Evas_Object *obj, Elm_Map_Marker *marker, void *data); /**< Bubble content fetching class function for marker classes. When the user click on a marker, a bubble is displayed with a content. */
186typedef void (*Elm_Map_Marker_Del_Func)(Evas_Object *obj, Elm_Map_Marker *marker, void *data, Evas_Object *o); /**< Function to delete bubble content for marker classes. */
187typedef Evas_Object *(*Elm_Map_Marker_Icon_Get_Func)(Evas_Object *obj, Elm_Map_Marker *marker, void *data); /**< Icon fetching class function for marker classes. */
188typedef Evas_Object *(*Elm_Map_Group_Icon_Get_Func)(Evas_Object *obj, void *data); /**< Icon fetching class function for markers group classes. */
189
190typedef void (*Elm_Map_Overlay_Get_Cb)(void *data, Evas_Object *map, Elm_Map_Overlay *overlay); /**< Get callback function for the overlay. */
191typedef void (*Elm_Map_Name_Cb)(void *data, Evas_Object *map, Elm_Map_Name *name); /**< Async-callback function for the name request. */
192typedef void (*Elm_Map_Route_Cb)(void *data, Evas_Object *map, Elm_Map_Route *route); /**< Async-callback function for the route request. */
193
194/**
195 * Add a new map widget to the given parent Elementary (container) object.
196 *
197 * @param parent The parent object.
198 * @return a new map widget handle or @c NULL, on errors.
199 *
200 * This function inserts a new map widget on the canvas.
201 *
202 * @ingroup Map
203 */
204EAPI Evas_Object *elm_map_add(Evas_Object *parent);
205
206/**
207 * Set the zoom level of the map.
208 *
209 * @param obj The map object.
210 * @param zoom The zoom level to set.
211 *
212 * This sets the zoom level.
213 *
214 * It will respect limits defined by elm_map_zoom_min_set() and
215 * elm_map_zoom_max_set().
216 *
217 * By default these values are 0 (world map) and 18 (maximum zoom).
218 *
219 * This function should be used when zoom mode is set to
220 * #ELM_MAP_ZOOM_MODE_MANUAL. This is the default mode, and can be set
221 * with elm_map_zoom_mode_set().
222 *
223 * @see elm_map_zoom_mode_set()
224 * @see elm_map_zoom_get()
225 *
226 * @ingroup Map
227 */
228EAPI void elm_map_zoom_set(Evas_Object *obj, int zoom);
229
230/**
231 * Get the zoom level of the map.
232 *
233 * @param obj The map object.
234 * @return The current zoom level.
235 *
236 * This returns the current zoom level of the map object.
237 *
238 * Note that if you set the fill mode to other than #ELM_MAP_ZOOM_MODE_MANUAL
239 * (which is the default), the zoom level may be changed at any time by the
240 * map object itself to account for map size and map viewport size.
241 *
242 * @see elm_map_zoom_set() for details.
243 *
244 * @ingroup Map
245 */
246EAPI int elm_map_zoom_get(const Evas_Object *obj);
247
248/**
249 * Set the zoom mode used by the map object.
250 *
251 * @param obj The map object.
252 * @param mode The zoom mode of the map, being it one of
253 * #ELM_MAP_ZOOM_MODE_MANUAL (default), #ELM_MAP_ZOOM_MODE_AUTO_FIT,
254 * or #ELM_MAP_ZOOM_MODE_AUTO_FILL.
255 *
256 * This sets the zoom mode to manual or one of the automatic levels.
257 * Manual (#ELM_MAP_ZOOM_MODE_MANUAL) means that zoom is set manually by
258 * elm_map_zoom_set() and will stay at that level until changed by code
259 * or until zoom mode is changed. This is the default mode.
260 *
261 * The Automatic modes will allow the map object to automatically
262 * adjust zoom mode based on properties. #ELM_MAP_ZOOM_MODE_AUTO_FIT will
263 * adjust zoom so the map fits inside the scroll frame with no pixels
264 * outside this area. #ELM_MAP_ZOOM_MODE_AUTO_FILL will be similar but
265 * ensure no pixels within the frame are left unfilled. Do not forget that
266 * the valid sizes are 2^zoom, consequently the map may be smaller than
267 * the scroller view.
268 *
269 * @see elm_map_zoom_set()
270 *
271 * @ingroup Map
272 */
273EAPI void elm_map_zoom_mode_set(Evas_Object *obj, Elm_Map_Zoom_Mode mode);
274
275/**
276 * Get the zoom mode used by the map object.
277 *
278 * @param obj The map object.
279 * @return The zoom mode of the map, being it one of
280 * #ELM_MAP_ZOOM_MODE_MANUAL (default), #ELM_MAP_ZOOM_MODE_AUTO_FIT,
281 * or #ELM_MAP_ZOOM_MODE_AUTO_FILL.
282 *
283 * This function returns the current zoom mode used by the map object.
284 *
285 * @see elm_map_zoom_mode_set() for more details.
286 *
287 * @ingroup Map
288 */
289EAPI Elm_Map_Zoom_Mode elm_map_zoom_mode_get(const Evas_Object *obj);
290
291/**
292 * Set the minimum zoom of the source.
293 *
294 * @param obj The map object.
295 * @param zoom New minimum zoom value to be used.
296 *
297 * @see elm_map_zoom_min_get() for details.
298 *
299 * @ingroup Map
300 */
301EAPI void elm_map_zoom_min_set(Evas_Object *obj, int zoom);
302
303/**
304 * Get the minimum zoom of the source.
305 *
306 * @param obj The map object.
307 * @return Returns the minimum zoom of the source.
308 *
309 * @see elm_map_zoom_min_set() for details.
310 *
311 * @ingroup Map
312 */
313EAPI int elm_map_zoom_min_get(const Evas_Object *obj);
314
315/**
316 * Set the maximum zoom of the source.
317 *
318 * @param obj The map object.
319 * @param zoom New maximum zoom value to be used.
320 *
321 * @see elm_map_zoom_max_get() for details.
322 *
323 * @ingroup Map
324 */
325EAPI void elm_map_zoom_max_set(Evas_Object *obj, int zoom);
326
327/**
328 * Get the maximum zoom of the source.
329 *
330 * @param obj The map object.
331 * @return Returns the maximum zoom of the source.
332 *
333 * @see elm_map_zoom_max_set() for details.
334 *
335 * @ingroup Map
336 */
337EAPI int elm_map_zoom_max_get(const Evas_Object *obj);
338
339/**
340 * Get the current geographic coordinates of the map.
341 *
342 * @param obj The map object.
343 * @param lon Pointer to store longitude.
344 * @param lat Pointer to store latitude.
345 *
346 * This gets the current center coordinates of the map object. It can be
347 * set by elm_map_region_bring_in() and elm_map_region_show().
348 *
349 * @see elm_map_region_bring_in()
350 * @see elm_map_region_show()
351 *
352 * @ingroup Map
353 */
354EAPI void elm_map_region_get(const Evas_Object *obj, double *lon, double *lat);
355
356/**
357 * Animatedly bring in given coordinates to the center of the map.
358 *
359 * @param obj The map object.
360 * @param lon Longitude to center at.
361 * @param lat Latitude to center at.
362 *
363 * This causes map to jump to the given @p lat and @p lon coordinates
364 * and show it (by scrolling) in the center of the viewport, if it is not
365 * already centered. This will use animation to do so and take a period
366 * of time to complete.
367 *
368 * @see elm_map_region_show() for a function to avoid animation.
369 * @see elm_map_region_get()
370 *
371 * @ingroup Map
372 */
373EAPI void elm_map_region_bring_in(Evas_Object *obj, double lon, double lat);
374
375/**
376 * Show the given coordinates at the center of the map, @b immediately.
377 *
378 * @param obj The map object.
379 * @param lon Longitude to center at.
380 * @param lat Latitude to center at.
381 *
382 * This causes map to @b redraw its viewport's contents to the
383 * region containing the given @p lat and @p lon, that will be moved to the
384 * center of the map.
385 *
386 * @see elm_map_region_bring_in() for a function to move with animation.
387 * @see elm_map_region_get()
388 *
389 * @ingroup Map
390 */
391EAPI void elm_map_region_show(Evas_Object *obj, double lon, double lat);
392
393/**
394 * Convert canvas coordinates into geographic coordinates
395 * (longitude, latitude).
396 *
397 * @param obj The map object.
398 * @param x horizontal coordinate of the point to convert.
399 * @param y vertical coordinate of the point to convert.
400 * @param lon A pointer to the longitude.
401 * @param lat A pointer to the latitude.
402 *
403 * This gets longitude and latitude from canvas x, y coordinates. The canvas
404 * coordinates mean x, y coordinate from current viewport.
405 *
406 * see elm_map_region_to_canvas_convert()
407 *
408 * @ingroup Map
409 */
410EAPI void elm_map_canvas_to_region_convert(const Evas_Object *obj, const Evas_Coord x, const Evas_Coord y, double *lon, double *lat);
411
412/**
413 * Convert geographic coordinates (longitude, latitude)
414 * into canvas coordinates.
415 *
416 * @param obj The map object.
417 * @param lon The longitude to convert.
418 * @param lat The latitude to convert.
419 * @param x A pointer to horizontal coordinate.
420 * @param y A pointer to vertical coordinate.
421 *
422 * This gets canvas x, y coordinates from longitude and latitude. The canvas
423 * coordinates mean x, y coordinate from current viewport.
424 *
425 * see elm_map_canvas_to_region_convert()
426 *
427 * @ingroup Map
428 */
429EAPI void elm_map_region_to_canvas_convert(const Evas_Object *obj, double lon, double lat, Evas_Coord *x, Evas_Coord *y);
430
431/**
432 * Pause or unpause the map.
433 *
434 * @param obj The map object.
435 * @param paused Use @c EINA_TRUE to pause the map @p obj or @c EINA_FALSE
436 * to unpause it.
437 *
438 * This sets the paused state to on (@c EINA_TRUE) or off (@c EINA_FALSE)
439 * for map.
440 *
441 * The default is off.
442 *
443 * This will stop zooming using animation, changing zoom levels will
444 * change instantly. This will stop any existing animations that are running.
445 *
446 * @see elm_map_paused_get()
447 *
448 * @ingroup Map
449 */
450EAPI void elm_map_paused_set(Evas_Object *obj, Eina_Bool paused);
451
452/**
453 * Get a value whether map is paused or not.
454 *
455 * @param obj The map object.
456 * @return @c EINA_TRUE means map is pause. @c EINA_FALSE indicates
457 * it is not.
458 *
459 * This gets the current paused state for the map object.
460 *
461 * @see elm_map_paused_set() for details.
462 *
463 * @ingroup Map
464 */
465EAPI Eina_Bool elm_map_paused_get(const Evas_Object *obj);
466
467/**
468 * Rotate the map.
469 *
470 * @param obj The map object.
471 * @param degree Angle from 0.0 to 360.0 to rotate around Z axis.
472 * @param cx Rotation's center horizontal position.
473 * @param cy Rotation's center vertical position.
474 *
475 * @see elm_map_rotate_get()
476 *
477 * @ingroup Map
478 */
479EAPI void elm_map_rotate_set(Evas_Object *obj, double degree, Evas_Coord cx, Evas_Coord cy);
480
481/**
482 * Get the rotate degree of the map
483 *
484 * @param obj The map object
485 * @param degree Pointer to store degrees from 0.0 to 360.0
486 * to rotate around Z axis.
487 * @param cx Pointer to store rotation's center horizontal position.
488 * @param cy Pointer to store rotation's center vertical position.
489 *
490 * @see elm_map_rotate_set() to set map rotation.
491 *
492 * @ingroup Map
493 */
494EAPI void elm_map_rotate_get(const Evas_Object *obj, double *degree, Evas_Coord *cx, Evas_Coord *cy);
495
496/**
497 * Enable or disable mouse wheel to be used to zoom in / out the map.
498 *
499 * @param obj The map object.
500 * @param disabled Use @c EINA_TRUE to disable mouse wheel or @c EINA_FALSE
501 * to enable it.
502 *
503 * Mouse wheel can be used for the user to zoom in or zoom out the map.
504 *
505 * It's disabled by default.
506 *
507 * @see elm_map_wheel_disabled_get()
508 *
509 * @ingroup Map
510 */
511EAPI void elm_map_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled);
512
513/**
514 * Get a value whether mouse wheel is enabled or not.
515 *
516 * @param obj The map object.
517 * @return @c EINA_TRUE means map is disabled. @c EINA_FALSE indicates
518 * it is enabled.
519 *
520 * Mouse wheel can be used for the user to zoom in or zoom out the map.
521 *
522 * @see elm_map_wheel_disabled_set() for details.
523 *
524 * @ingroup Map
525 */
526EAPI Eina_Bool elm_map_wheel_disabled_get(const Evas_Object *obj);
527
528/**
529 * Set the user agent used by the map object to access routing services.
530 *
531 * @param obj The map object.
532 * @param user_agent The user agent to be used by the map.
533 *
534 * User agent is a client application implementing a network protocol used
535 * in communications within a client–server distributed computing system
536 *
537 * The @p user_agent identification string will transmitted in a header
538 * field @c User-Agent.
539 *
540 * @see elm_map_user_agent_get()
541 *
542 * @ingroup Map
543 */
544EAPI void elm_map_user_agent_set(Evas_Object *obj, const char *user_agent);
545
546/**
547 * Get the user agent used by the map object.
548 *
549 * @param obj The map object.
550 * @return The user agent identification string used by the map.
551 *
552 * @see elm_map_user_agent_set() for details.
553 *
554 * @ingroup Map
555 */
556EAPI const char *elm_map_user_agent_get(const Evas_Object *obj);
557
558
559/**
560 * Add a new overlay to the map object. This overlay has a default type.
561 *
562 * @param obj The map object to add a new overlay.
563 * @param lon The longitude of the overlay.
564 * @param lat The latitude of the overlay.
565 * @return The created overlay or @c NULL upon failure.
566 *
567 * A overlay will be created and shown in a specific point of the map, defined
568 * by @p lon and @p lat.
569 *
570 * The created overlay has a default style layout before content or
571 * icon is set.
572 * If content or icon is set, those are displayed instead of default style
573 * layout.
574 * You can set by using elm_map_overlay_content_set() or
575 * elm_map_overlay_icon_set(). If NULL is set, default style
576 * is shown again.
577 *
578 * Overlay created with this method can be deleted by elm_map_overlay_del().
579 *
580 * @see elm_map_overlay_del()
581 * @see elm_map_overlay_class_add()
582 * @see elm_map_overlay_bubble_add()
583 * @see elm_map_overlay_content_set()
584 * @see elm_map_overlay_icon_set()
585 *
586 * @ingroup Map
587 */
588EAPI Elm_Map_Overlay * elm_map_overlay_add(Evas_Object *obj, double lon, double lat);
589
590/**
591 * Delete a overlay from the map. This function can delete all types
592 * of overlays.
593 *
594 * @param overlay The overlay to be deleted.
595 *
596 * @see elm_map_overlay_add()
597 * @see elm_map_overlay_class_add()
598 * @see elm_map_overlay_bubble_add()
599 *
600 * @ingroup Map
601 */
602EAPI void elm_map_overlay_del(Elm_Map_Overlay *overlay);
603
604/**
605 * Get the overlay type.
606 *
607 * @param overlay The overlay to return type.
608 * @return Return the overlay type.
609 *
610 * This type is resolved when the overlay is created.
611 *
612 * @see elm_map_overlay_add()
613 * @see elm_map_overlay_class_add()
614 * @see elm_map_overlay_bubble_add()
615 *
616 * @ingroup Map
617 */
618EAPI Elm_Map_Overlay_Type elm_map_overlay_type_get(const Elm_Map_Overlay *overlay);
619
620 /**
621 * Set a pointer of user data for a overlay.
622 *
623 * @param overlay The overlay to own the user data.
624 * @param data A pointer of user data
625 *
626 * @see elm_map_overlay_data_get()
627 *
628 * @ingroup Map
629 */
630EAPI void elm_map_overlay_data_set(Elm_Map_Overlay *overlay, void *data);
631
632/**
633 * Get the user data stored on a overlay.
634 *
635 * @param overlay The overlay to return the user data.
636 * @return A pointer to data stored using elm_map_overlay_data_set(),
637 * or @c NULL, if none has been set.
638 *
639 * @see elm_map_overlay_data_set()
640 *
641 * @ingroup Map
642 */
643EAPI void * elm_map_overlay_data_get(const Elm_Map_Overlay *overlay);
644
645/**
646 * Set if the overlay is hidden or not.
647 *
648 * @param overlay The overlay to be hidden.
649 * @param hide Use @c EINA_TRUE to hide the overlay or @c EINA_FALSE to show.
650 *
651 * @see elm_map_overlay_hide_get()
652 *
653 * @ingroup Map
654 */
655EAPI void elm_map_overlay_hide_set(Elm_Map_Overlay *overlay, Eina_Bool hide);
656
657/**
658 * Get a value whether the overlay is hidden or not.
659 *
660 * @param overlay The overlay to return the hidden state.
661 * @return @c EINA_TRUE means the overlay is hidden. @c EINA_FALSE indicates
662 * it is not.
663 *
664 * This gets the current hidden state for the overlay.
665 *
666 * @see elm_map_overlay_hide_set()
667 *
668 * @ingroup Map
669 */
670EAPI Eina_Bool elm_map_overlay_hide_get(const Elm_Map_Overlay *overlay);
671
672/**
673 * Set the minimum zoom from where the overlay is displayed.
674 *
675 * @param overlay The overlay to be set the minimum zoom.
676 * @param zoom The minimum zoom.
677 *
678 * The overlay only will be displayed when the map is displayed at @p zoom
679 * or bigger.
680 *
681 * @see elm_map_overlay_displayed_zoom_min_get()
682 *
683 * @ingroup Map
684 */
685EAPI void elm_map_overlay_displayed_zoom_min_set(Elm_Map_Overlay *overlay, int zoom);
686
687/**
688 * Get the minimum zoom from where the overlay is displayed.
689 *
690 * @param overlay The overlay to return the minimum zoom.
691 * @return zoom The minimum zoom.
692 *
693 * @see elm_map_overlay_displayed_zoom_min_set()
694 *
695 * @ingroup Map
696 */
697EAPI int elm_map_overlay_displayed_zoom_min_get(const Elm_Map_Overlay *overlay);
698
699/**
700 * Pause or unpause the overlay.
701 *
702 * @param overlay The overlay to be paused.
703 * @param paused Use @c EINA_TRUE to pause the @p overlay or @c EINA_FALSE
704 * to unpause it.
705 *
706 * This sets the paused state to on (@c EINA_TRUE) or off (@c EINA_FALSE)
707 * for the overlay.
708 *
709 * The default is off.
710 *
711 * This will stop moving the overlay coordinates instantly.
712 * even if map being scrolled or zoomed.
713 *
714 * @see elm_map_overlay_paused_get()
715 *
716 * @ingroup Map
717 */
718EAPI void elm_map_overlay_paused_set(Elm_Map_Overlay *overlay, Eina_Bool paused);
719
720/**
721 * Get a value whether the overlay is paused or not.
722 *
723 * @param overlay The overlay to return paused state.
724 * @return @c EINA_TRUE means overlay is paused. @c EINA_FALSE indicates
725 * it is not.
726 *
727 * This gets the current paused state for the overlay.
728 *
729 * @see elm_map_overlay_paused_set()
730 *
731 * @ingroup Map
732 */
733EAPI Eina_Bool elm_map_overlay_paused_get(const Elm_Map_Overlay *overlay);
734
735/**
736 * Set the content object of the overlay.
737 *
738 * @param overlay The overlay to be set the content.
739 * @param obj The evas object will be used to display the overlay.
740 *
741 * Only default and class type overlay support this function.
742 *
743 * The content should be resized or set size hints before set to the overlay.
744 * <b> Do not modify this object</b> (move, show, hide, del, etc.),
745 * after set.
746 * You can only resize this.
747 *
748 * This content is what will be inside the overlay that will be displayed.
749 * If a content is set, icon and default style layout are no more used before
750 * the content is deleted.
751 *
752 * If @p obj is @c NULL, content inside the overlay is deleted.
753 *
754 * @see elm_map_overlay_content_get()
755 *
756 * @ingroup Map
757 */
758EAPI void elm_map_overlay_content_set(Elm_Map_Overlay *overlay, Evas_Object *obj);
759
760/**
761 * Get the content object.
762 *
763 * @param overlay The overlay to return the content.
764 * @return Return the evas object if it exists, else @c NULL.
765 *
766 * Only default and class type overlay support this function.
767 *
768 * Returned content is what being inside the overlay that being displayed.
769 *
770 * <b> Do not modify this object</b> (move, show, hide, del, etc.).
771 * You can only resize this.
772 *
773 * The content can be set by elm_map_overlay_content_set().
774 *
775 * @see elm_map_overlay_content_set()
776 *
777 * @ingroup Map
778 */
779EAPI const Evas_Object * elm_map_overlay_content_get(const Elm_Map_Overlay *overlay);
780
781/**
782 * Set a icon of the overlay.
783 *
784 * @param overlay The overlay to be set the icon.
785 * @param icon The icon will be used to display the overlay.
786 *
787 * Only default and class type overlay support this function.
788 *
789 * <b> Do not modify this object</b> (move, show, hide, resize, del, etc.),
790 * after set.
791 *
792 * If icon is set, default style layout will not be used.
793 *
794 * If @p icon is @c NULL, icon inside the overlay will be deleted.
795 *
796 * @see elm_map_overlay_icon_get()
797 *
798 * @ingroup Map
799 */
800EAPI void elm_map_overlay_icon_set(Elm_Map_Overlay *overlay, Evas_Object *icon);
801
802/**
803 * Get the icon object.
804 *
805 * @param overlay The overlay to return the icon.
806 * @return Return the icon object if it exists, else @c NULL.
807 *
808 * Only default and class type overlay support this function.
809 *
810 * Returned icon is what being inside the overlay that being displayed.
811 *
812 * <b> Do not modify this icon </b> (move, show, hide, resize, del, etc.).
813 *
814 * The icon can be set by elm_map_overlay_icon_set().
815 *
816 * @see elm_map_overlay_icon_set()
817 *
818 * @ingroup Map
819 */
820EAPI const Evas_Object * elm_map_overlay_icon_get(const Elm_Map_Overlay *overlay);
821
822/**
823 * Set the geographic coordinates of the overlay.
824 *
825 * @param overlay The overlay to be set geographic coordinates.
826 * @param lon Longitude to be set.
827 * @param lat Latitude to be set.
828 *
829 * Only default and bubble type overlay support this function.
830 *
831 * This sets the center coordinates of the overlay. It can be
832 * get by elm_map_overlay_region_get().
833 *
834 * @see elm_map_overlay_region_get()
835 *
836 * @ingroup Map
837 */
838EAPI void elm_map_overlay_region_set(Elm_Map_Overlay *overlay, double lon, double lat);
839
840/**
841 * Get the geographic coordinates of the overlay.
842 *
843 * @param overlay The overlay to return geographic coordinates.
844 * @param lon Pointer to store longitude.
845 * @param lat Pointer to store latitude.
846 *
847 * Only default and bubble type overlay support this function.
848 *
849 * This returns the center coordinates of the overlay. It can be
850 * set by elm_map_overlay_region_set().
851 *
852 * @see elm_map_overlay_region_set()
853 *
854 * @ingroup Map
855 */
856EAPI void elm_map_overlay_region_get(const Elm_Map_Overlay *overlay, double *lon, double *lat);
857
858
859/**
860 * Set the object color of the overlay.
861 *
862 * @param overlay The overlay to be set color.
863 * @param r Red channel value, from 0 to 255.
864 * @param g Green channel value, from 0 to 255.
865 * @param b Blue channel value, from 0 to 255.
866 * @param a Alpha channel value, from 0 to 255.
867 *
868 * It uses an additive color model, so each color channel represents
869 * how much of each primary colors must to be used. 0 represents
870 * absence of this color, so if all of the three are set to 0,
871 * the color will be black.
872 *
873 * These component values should be integers in the range 0 to 255,
874 * (single 8-bit byte).
875 *
876 * This sets the color used for the overlay. By default, it is set to
877 * solid red (r = 255, g = 0, b = 0, a = 255).
878 *
879 * For alpha channel, 0 represents completely transparent, and 255, opaque.
880 *
881 * @see elm_map_overlay_color_get()
882 *
883 * @ingroup Map
884 */
885EAPI void elm_map_overlay_color_set(Elm_Map_Overlay *overlay, int r, int g, int b, int a);
886
887/**
888 * Get the object color of the overlay.
889 *
890 * @param overlay The overlay to return color.
891 * @param r Pointer to store the red channel value.
892 * @param g Pointer to store the green channel value.
893 * @param b Pointer to store the blue channel value.
894 * @param a Pointer to store the alpha channel value.
895 *
896 * @see elm_map_overlay_color_set()
897 *
898 * @ingroup Map
899 */
900EAPI void elm_map_overlay_color_get(const Elm_Map_Overlay *overlay, int *r, int *g, int *b, int *a);
901
902/**
903 * Show the given overlay at the center of the map, immediately.
904 *
905 * @param overlay The overlay to be center at.
906 *
907 * This causes map to @b redraw its viewport's contents to the
908 * region containing the given @p overlay's coordinates, that will be
909 * moved to the center of the map.
910 *
911 * @see elm_map_overlays_show() if more than one overlay need to be displayed.
912 *
913 * @ingroup Map
914 */
915EAPI void elm_map_overlay_show(Elm_Map_Overlay *overlay);
916
917/**
918 * Move and zoom the map to display a list of overlays.
919 *
920 * @param overlays A list of #Elm_Map_Overlay handles.
921 *
922 * The map will be centered on the center point of the overlays in the list.
923 * Then the map will be zoomed in order to fit the overlays using the maximum
924 * zoom which allows display of all the overlays.
925 *
926 * @warning All the overlays should belong to the same map object.
927 *
928 * @see elm_map_overlay_show() to show a single overlay.
929 *
930 * @ingroup Map
931 */
932EAPI void elm_map_overlays_show(Eina_List *overlays);
933
934/**
935 * Set the get callback function of the overlay.
936 *
937 * @param overlay The overlay to own the get callback function.
938 * @param get_cb The callback function.
939 * @param data The user callback data.
940 *
941 * If the overlay is clicked, the callback wll be called.
942 * The clicked overlay is returned by callback.
943 *
944 * You can add callback to the class overlay. If one of the group overlays in this class
945 * is clicked, callback will be called and return a virtual group overlays.
946 *
947 * You can delete this callback function by setting @c NULL.
948 *
949 * @ingroup Map
950 */
951EAPI void elm_map_overlay_get_cb_set(Elm_Map_Overlay *overlay, Elm_Map_Overlay_Get_Cb get_cb, void *data);
952
953
954/**
955 * Add a new class overlay to the map object.
956 * This overlay has a class type.
957 *
958 * @param obj The map object to add a new overlay.
959 * @return The created overlay or @c NULL upon failure.
960 *
961 * This overlay is not shown before overlay members are appended.
962 * if overlay members in the same class are close, group overlays
963 * are created. If they are far away, group overlays are hidden.
964 * When group overlays are shown, they have default style layouts at first.
965 *
966 * You can change the state (hidden, paused, etc.) or set the content
967 * or icon of the group overlays by chaning the state of the class overlay.
968 * Do not modifty the group overlay itself.
969 *
970 * Also these changes have a influence on the overlays in the same class
971 * even if each overlay is alone and is not grouped.
972 *
973 * @see elm_map_overlay_del()
974 * @see elm_map_overlay_add()
975 * @see elm_map_overlay_bubble_add()
976 *
977 * @ingroup Map
978 */
979EAPI Elm_Map_Overlay * elm_map_overlay_class_add(Evas_Object *obj);
980
981/**
982 * Add a new overlay member to the class overlay.
983 *
984 * @param clas The class overlay to add a new overlay.
985 * @param overlay The overlay to be added to the class overlay.
986 *
987 * @see elm_map_overlay_class_remove()
988 *
989 * @ingroup Map
990 */
991EAPI void elm_map_overlay_class_append(Elm_Map_Overlay *clas, Elm_Map_Overlay *overlay);
992
993/**
994 * Remove a overlay from the class.
995 *
996 * @param clas The class overlay to delete the overlay.
997 * @param overlay The overlay to be deleted from the class overlay.
998 *
999 * @see elm_map_overlay_class_append()
1000 *
1001 * @ingroup Map
1002 */
1003EAPI void elm_map_overlay_class_remove(Elm_Map_Overlay *clas, Elm_Map_Overlay *overlay);
1004
1005/**
1006 * Set the maximum zoom from where the overlay members in the class can be
1007 * grouped.
1008 *
1009 * @param clas The overlay class has overlay members.
1010 * @param zoom The maximum zoom.
1011 *
1012 * Overlay members in the class only will be grouped when the map
1013 * is displayed at less than @p zoom.
1014 *
1015 * @see elm_map_overlay_class_zoom_max_get()
1016 *
1017 * @ingroup Map
1018 */
1019EAPI void elm_map_overlay_class_zoom_max_set(Elm_Map_Overlay *clas, int zoom);
1020
1021/**
1022 * Get the maximum zoom from where the overlay members in the class can be
1023 * grouped.
1024 *
1025 * @param clas The overlay class has overlay members.
1026 *
1027 * @return The maximum zoom.
1028 *
1029 * @see elm_map_overlay_class_zoom_max_set()
1030 *
1031 * @ingroup Map
1032 */
1033EAPI int elm_map_overlay_class_zoom_max_get(const Elm_Map_Overlay *clas);
1034
1035/**
1036 * Get the overlay members of the group overlay.
1037 *
1038 * @param grp The group overlay has overlay members.
1039 *
1040 * @return The list of group overlay members.
1041 *
1042 * The group overlays are virtualy overlays. Those are shown and hidden dynamically.
1043 * You can add callback to the class overlay. If one of the group overlays in this class
1044 * is clicked, callback will be called and return a virtual group overlays.
1045 *
1046 * You can change the state (hidden, paused, etc.) or set the content
1047 * or icon of the group overlays by chaning the state of the class overlay.
1048 * Do not modifty the group overlay itself.
1049 *
1050 * @see elm_map_overlay_class_add()
1051 *
1052 * @ingroup Map
1053 */
1054EAPI Eina_List * elm_map_overlay_group_members_get(const Elm_Map_Overlay *grp);
1055
1056/**
1057 * Add a new bubble overlay to the map object.
1058 * This overlay has a bubble type.
1059 *
1060 * @param obj The map object to add a new overlay.
1061 * @return The created overlay or @c NULL upon failure.
1062 *
1063 * A bubble will not be displayed before geographic coordinates are set or
1064 * any other overlays are followed.
1065 *
1066 * This overlay has a bubble style layout and icon or content can not
1067 * be set.
1068 *
1069 * Overlay created with this method can be deleted with elm_map_overlay_del().
1070 *
1071 * @see elm_map_overlay_del()
1072 * @see elm_map_overlay_add()
1073 * @see elm_map_overlay_class_add()
1074 * @see elm_map_overlay_region_set()
1075 * @see elm_map_overlay_bubble_follow()
1076 *
1077 * @ingroup Map
1078 */
1079EAPI Elm_Map_Overlay * elm_map_overlay_bubble_add(Evas_Object *obj);
1080
1081/**
1082 * Follow a other overlay.
1083 *
1084 * @param bubble The bubble overlay to follow a parent overlay.
1085 * @param parent The parent overlay to be followed by the bubble overlay.
1086 *
1087 * Bubble overlay will follow the parent overlay's movement (hide, show, move).
1088 *
1089 * @see elm_map_overlay_bubble_add()
1090 *
1091 * @ingroup Map
1092 */
1093EAPI void elm_map_overlay_bubble_follow(Elm_Map_Overlay *bubble, const Elm_Map_Overlay *parent);
1094
1095/**
1096 * Add a content object to the bubble overlay.
1097 *
1098 * @param bubble The bubble overlay to add a content.
1099 * @param content The content to be added to the bubble overlay.
1100 *
1101 * Added contents will be displayed inside the bubble overlay.
1102 *
1103 * @see elm_map_overlay_bubble_content_clear()
1104 *
1105 * @ingroup Map
1106 */
1107EAPI void elm_map_overlay_bubble_content_append(Elm_Map_Overlay *bubble, Evas_Object *content);
1108
1109/**
1110 * Clear all contents inside the bubble overlay.
1111 *
1112 * @param bubble The bubble overlay to clear the contents.
1113 *
1114 * This will delete all contents inside the bubble overlay.
1115 *
1116 * @see elm_map_overlay_bubble_content_append()
1117 *
1118 * @ingroup Map
1119 */
1120EAPI void elm_map_overlay_bubble_content_clear(Elm_Map_Overlay *bubble);
1121
1122/**
1123 * Add a new route overlay to the map object.
1124 * This overlay has a route type.
1125 *
1126 * @param obj The map object to add a new overlay.
1127 * @param route The route object to make a overlay.
1128 * @return The created overlay or @c NULL upon failure.
1129 *
1130 * This overlay has a route style layout and icon or content can not
1131 * be set.
1132 *
1133 * The color scheme can be changed by elm_map_overlay_content_set().
1134 *
1135 * Overlay created with this method can be deleted with elm_map_overlay_del().
1136 *
1137 * @see elm_map_overlay_del()
1138 * @see elm_map_overlay_class_add()
1139 * @see elm_map_overlay_content_set()
1140 * @see elm_map_overlay_content_get()
1141 *
1142 * @ingroup Map
1143 */
1144EAPI Elm_Map_Overlay * elm_map_overlay_route_add(Evas_Object *obj, const Elm_Map_Route *route);
1145
1146/**
1147 * Add a new line overlay to the map object.
1148 * This overlay has a line type.
1149 *
1150 * @param obj The map object to add a new overlay.
1151 * @param flon The start longitude.
1152 * @param flat The start latitude.
1153 * @param tlon The destination longitude.
1154 * @param tlat The destination latitude.
1155 * @return The created overlay or @c NULL upon failure.
1156 *
1157 * Overlay created with this method can be deleted with elm_map_overlay_del().
1158 *
1159 * @see elm_map_overlay_del()
1160 *
1161 * @ingroup Map
1162 */
1163EAPI Elm_Map_Overlay * elm_map_overlay_line_add(Evas_Object *obj, double flon, double flat, double tlon, double tlat);
1164
1165/**
1166 * Add a new polygon overlay to the map object.
1167 * This overlay has a polygon type.
1168 *
1169 * @param obj The map object to add a new overlay.
1170 * @return The created overlay or @c NULL upon failure.
1171 *
1172 * At least 3 regions should be added to show the polygon overlay.
1173 *
1174 * Overlay created with this method can be deleted with elm_map_overlay_del().
1175 *
1176 * @see elm_map_overlay_polygon_region_add()
1177 * @see elm_map_overlay_del()
1178 *
1179 * @ingroup Map
1180 */
1181EAPI Elm_Map_Overlay * elm_map_overlay_polygon_add(Evas_Object *obj);
1182
1183/**
1184 * Add a geographic coordinates to the polygon overlay.
1185 *
1186 * @param overlay The polygon overlay to get a region.
1187 * @param lon The longitude.
1188 * @param lat The latitude.
1189 *
1190 * At least 3 regions should be added to show the polygon overlay.
1191 *
1192 * Overlay created with this method can be deleted with elm_map_overlay_del().
1193 *
1194 * @see elm_map_overlay_polygon_add()
1195 * @see elm_map_overlay_del()
1196 *
1197 * @ingroup Map
1198 */
1199EAPI void elm_map_overlay_polygon_region_add(Elm_Map_Overlay *overlay, double lon, double lat);
1200
1201/**
1202 * Add a new circle overlay to the map object.
1203 * This overlay has a circle type.
1204 *
1205 * @param obj The map object to add a new overlay.
1206 * @param lon The center longitude.
1207 * @param lat The center latitude.
1208 * @param radius The pixel length of radius.
1209 * @return The created overlay or @c NULL upon failure.
1210 *
1211 * Overlay created with this method can be deleted with elm_map_overlay_del().
1212 *
1213 * @see elm_map_overlay_del()
1214 *
1215 * @ingroup Map
1216 */
1217EAPI Elm_Map_Overlay * elm_map_overlay_circle_add(Evas_Object *obj, double lon, double lat, double radius);
1218
1219/**
1220 * Add a new scale overlay to the map object.
1221 * This overlay has a scale type.
1222 *
1223 * @param obj The map object to add a new overlay.
1224 * @param x horizontal pixel coordinate.
1225 * @param y vertical pixel coordinate
1226 * @return The created overlay or @c NULL upon failure.
1227 *
1228 * The scale overlay shows the ratio of a distance on the map to the corresponding distance.
1229 *
1230 * Overlay created with this method can be deleted with elm_map_overlay_del().
1231 *
1232 * @see elm_map_overlay_del()
1233 *
1234 * @ingroup Map
1235 */
1236EAPI Elm_Map_Overlay * elm_map_overlay_scale_add(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
1237
1238/**
1239 * Get the information of tile load status.
1240 *
1241 * @param obj The map object.
1242 * @param try_num Pointer to store number of tiles download requested.
1243 * @param finish_num Pointer to store number of tiles successfully downloaded.
1244 *
1245 * This gets the current tile loaded status for the map object.
1246 *
1247 * @ingroup Map
1248 */
1249EAPI void elm_map_tile_load_status_get(const Evas_Object *obj, int *try_num, int *finish_num);
1250
1251/**
1252 * Get the names of available sources for a specific type.
1253 *
1254 * @param obj The map object.
1255 * @param type source type.
1256 * @return The char pointer array of source names.
1257 *
1258 * It will provide a list with all available sources.
1259 * Current source can be set by elm_map_source_set(), or get with
1260 * elm_map_source_get().
1261 *
1262 * At least available sources of tile type:
1263 * @li "Mapnik"
1264 * @li "Osmarender"
1265 * @li "CycleMap"
1266 * @li "Maplint"
1267 *
1268 * At least available sources of route type:
1269 * @li "Yours"
1270 *
1271 * At least available sources of name type:
1272 * @li "Nominatim"
1273 *
1274 * @see elm_map_source_set()
1275 * @see elm_map_source_get()
1276 *
1277 * @ingroup Map
1278 */
1279EAPI const char **elm_map_sources_get(const Evas_Object *obj, Elm_Map_Source_Type type);
1280
1281/**
1282 * Set the current source of the map for a specific type.
1283 *
1284 * @param obj The map object.
1285 * @param type source type.
1286 * @param source_name The source to be used.
1287 *
1288 * Map widget retrieves tile images that composes the map from a web service.
1289 * This web service can be set with this method
1290 * for ELM_MAP_SOURCE_TYPE_TILE type.
1291 * A different service can return a different maps with different
1292 * information and it can use different zoom values.
1293 *
1294 * Map widget provides route data based on a external web service.
1295 * This web service can be set with this method
1296 * for ELM_MAP_SOURCE_TYPE_ROUTE type.
1297 *
1298 * Map widget also provide geoname data based on a external web service.
1299 * This web service can be set with this method
1300 * for ELM_MAP_SOURCE_TYPE_NAME type.
1301 *
1302 * The @p source_name need to match one of the names provided by
1303 * elm_map_sources_get().
1304 *
1305 * The current source can be get using elm_map_source_get().
1306 *
1307 * @see elm_map_sources_get()
1308 * @see elm_map_source_get()
1309 *
1310 * @ingroup Map
1311 */
1312EAPI void elm_map_source_set(Evas_Object *obj, Elm_Map_Source_Type type, const char *source_name);
1313
1314/**
1315 * Get the name of currently used source for a specific type.
1316 *
1317 * @param obj The map object.
1318 * @param type source type.
1319 * @return Returns the name of the source in use.
1320 *
1321 * @see elm_map_sources_get()
1322 * @see elm_map_source_set()
1323 *
1324 * @ingroup Map
1325 */
1326EAPI const char *elm_map_source_get(const Evas_Object *obj, Elm_Map_Source_Type type);
1327
1328/**
1329 * Add a new route to the map object.
1330 *
1331 * @param obj The map object.
1332 * @param type The type of transport to be considered when tracing a route.
1333 * @param method The routing method, what should be prioritized.
1334 * @param flon The start longitude.
1335 * @param flat The start latitude.
1336 * @param tlon The destination longitude.
1337 * @param tlat The destination latitude.
1338 *
1339 * @return The created route or @c NULL upon failure.
1340 *
1341 * A route will be traced by point on coordinates (@p flat, @p flon)
1342 * to point on coordinates (@p tlat, @p tlon), using the route service
1343 * set with elm_map_source_set().
1344 *
1345 * It will take @p type on consideration to define the route,
1346 * depending if the user will be walking or driving, the route may vary.
1347 * One of #ELM_MAP_ROUTE_TYPE_MOTOCAR, #ELM_MAP_ROUTE_TYPE_BICYCLE, or
1348 * #ELM_MAP_ROUTE_TYPE_FOOT need to be used.
1349 *
1350 * Another parameter is what the route should prioritize, the minor distance
1351 * or the less time to be spend on the route. So @p method should be one
1352 * of #ELM_MAP_ROUTE_METHOD_SHORTEST or #ELM_MAP_ROUTE_METHOD_FASTEST.
1353 *
1354 * Routes created with this method can be deleted with
1355 * elm_map_route_remove(),
1356 * and distance can be get with elm_map_route_distance_get().
1357 *
1358 * @see elm_map_route_remove()
1359 * @see elm_map_route_distance_get()
1360 * @see elm_map_source_set()
1361 *
1362 * @ingroup Map
1363 */
1364EAPI Elm_Map_Route *elm_map_route_add(Evas_Object *obj, Elm_Map_Route_Type type, Elm_Map_Route_Method method, double flon, double flat, double tlon, double tlat, Elm_Map_Route_Cb route_cb, void *data);
1365
1366/**
1367 * Remove a route from the map.
1368 *
1369 * @param route The route to remove.
1370 *
1371 * @see elm_map_route_add()
1372 *
1373 * @ingroup Map
1374 */
1375EAPI void elm_map_route_del(Elm_Map_Route *route);
1376
1377/**
1378 * Get the route distance in kilometers.
1379 *
1380 * @param route The route object.
1381 * @return The distance of route (unit : km).
1382 *
1383 * @ingroup Map
1384 */
1385EAPI double elm_map_route_distance_get(const Elm_Map_Route *route);
1386
1387/**
1388 * Get the information of route nodes.
1389 *
1390 * @param route The route object.
1391 * @return Returns a string with the nodes of route.
1392 *
1393 * @ingroup Map
1394 */
1395EAPI const char *elm_map_route_node_get(const Elm_Map_Route *route);
1396
1397/**
1398 * Get the information of route waypoint.
1399 *
1400 * @param route the route object.
1401 * @return Returns a string with information about waypoint of route.
1402 *
1403 * @ingroup Map
1404 */
1405EAPI const char *elm_map_route_waypoint_get(const Elm_Map_Route *route);
1406
1407/**
1408 * Request a address or geographic coordinates(longitude, latitude)
1409 * from a given address or geographic coordinate(longitude, latitude).
1410 *
1411 * @param obj The map object.
1412 * @param address The address.
1413 * @param lon The longitude.
1414 * @param lat The latitude.
1415 * @param name_cb The callback function.
1416 * @param data The user callback data.
1417 * @return name A #Elm_Map_Name handle for this coordinate.
1418 *
1419 * If you want to get address from geographic coordinates, set input @p address
1420 * as NULL and set @p lon, @p lat as you want to convert.
1421 * If address is set except NULL, @p lon and @p lat are checked.
1422 *
1423 * To get the string for this address, elm_map_name_address_get()
1424 * should be used after callback or "name,loaded" signal is called.
1425 *
1426 * To get the longitude and latitude, elm_map_name_region_get()
1427 * should be used.
1428 *
1429 * @ingroup Map
1430 */
1431EAPI Elm_Map_Name *elm_map_name_add(const Evas_Object *obj, const char *address, double lon, double lat, Elm_Map_Name_Cb name_cb, void *data);
1432
1433/**
1434 * Get the address of the name.
1435 *
1436 * @param name The name handle.
1437 * @return Returns the address string of @p name.
1438 *
1439 * This gets the coordinates of the @p name, created with one of the
1440 * conversion functions.
1441 *
1442 * @see elm_map_name_add()
1443 *
1444 * @ingroup Map
1445 */
1446EAPI const char *elm_map_name_address_get(const Elm_Map_Name *name);
1447
1448/**
1449 * Get the current coordinates of the name.
1450 *
1451 * @param name The name handle.
1452 * @param lat Pointer to store the latitude.
1453 * @param lon Pointer to store The longitude.
1454 *
1455 * This gets the coordinates of the @p name, created with one of the
1456 * conversion functions.
1457 *
1458 * @see elm_map_name_add()
1459 *
1460 * @ingroup Map
1461 */
1462EAPI void elm_map_name_region_get(const Elm_Map_Name *name, double *lon, double *lat);
1463
1464/**
1465 * Remove a name from the map.
1466 *
1467 * @param name The name to remove.
1468 *
1469 * Basically the struct handled by @p name will be freed, so conversions
1470 * between address and coordinates will be lost.
1471 *
1472 * @see elm_map_name_add()
1473 *
1474 * @ingroup Map
1475 */
1476EAPI void elm_map_name_del(Elm_Map_Name *name);
1477
1478/**
1479 * Add a track on the map
1480 *
1481 * @param obj The map object.
1482 * @param emap The emap route object.
1483 * @return The route object. This is an elm object of type Route.
1484 *
1485 * @see elm_route_add() for details.
1486 *
1487 * @ingroup Map
1488 */
1489EAPI Evas_Object *elm_map_track_add(Evas_Object *obj, void *emap);
1490
1491/**
1492 * Remove a track from the map
1493 *
1494 * @param obj The map object.
1495 * @param route The track to remove.
1496 *
1497 * @ingroup Map
1498 */
1499EAPI void elm_map_track_remove(Evas_Object *obj, Evas_Object *route);
1500
1501/**
1502 * @}
1503 */
diff --git a/libraries/elementary/src/lib/elm_mapbuf.c b/libraries/elementary/src/lib/elm_mapbuf.c
new file mode 100644
index 0000000..4608872
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_mapbuf.c
@@ -0,0 +1,305 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *content, *clip;
9 Eina_Bool enabled : 1;
10 Eina_Bool alpha : 1;
11 Eina_Bool smooth : 1;
12};
13
14static const char *widtype = NULL;
15static void _del_hook(Evas_Object *obj);
16static void _theme_hook(Evas_Object *obj);
17static void _sizing_eval(Evas_Object *obj);
18static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
19static void _sub_del(void *data, Evas_Object *obj, void *event_info);
20
21static void
22_del_hook(Evas_Object *obj)
23{
24 Widget_Data *wd = elm_widget_data_get(obj);
25 if (!wd) return;
26 free(wd);
27}
28
29static void
30_theme_hook(Evas_Object *obj)
31{
32 Widget_Data *wd = elm_widget_data_get(obj);
33 if (!wd) return;
34 _sizing_eval(obj);
35}
36
37static void
38_sizing_eval(Evas_Object *obj)
39{
40 Widget_Data *wd = elm_widget_data_get(obj);
41 Evas_Coord minw = -1, minh = -1;
42 Evas_Coord maxw = -1, maxh = -1;
43 if (!wd) return;
44 if (wd->content)
45 {
46 evas_object_size_hint_min_get(wd->content, &minw, &minh);
47 evas_object_size_hint_max_get(wd->content, &maxw, &maxh);
48 }
49 evas_object_size_hint_min_set(obj, minw, minh);
50 evas_object_size_hint_max_set(obj, maxw, maxh);
51}
52
53static void
54_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
55{
56 Widget_Data *wd = elm_widget_data_get(data);
57 if (!wd) return;
58 _sizing_eval(data);
59}
60
61static void
62_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
63{
64 Widget_Data *wd = elm_widget_data_get(obj);
65 Evas_Object *sub = event_info;
66 if (!wd) return;
67 if (sub == wd->content)
68 {
69 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
70 _changed_size_hints, obj);
71 wd->content = NULL;
72 _sizing_eval(obj);
73 }
74}
75
76static void
77_mapbuf(Evas_Object *obj)
78{
79 Widget_Data *wd = elm_widget_data_get(obj);
80 Evas_Coord x, y, w, h;
81 if (!wd) return;
82 evas_object_geometry_get(wd->clip, &x, &y, &w, &h);
83 if (wd->enabled)
84 {
85 Evas_Map *m;
86
87 m = evas_map_new(4);
88 evas_map_util_points_populate_from_geometry(m, x, y, w, h, 0);
89 evas_map_smooth_set(m, wd->smooth);
90 evas_map_alpha_set(m, wd->alpha);
91 evas_object_map_set(wd->content, m);
92 evas_object_map_enable_set(wd->content, EINA_TRUE);
93 evas_map_free(m);
94 }
95 else
96 {
97 evas_object_map_set(wd->content, NULL);
98 evas_object_map_enable_set(wd->content, EINA_FALSE);
99 evas_object_move(wd->content, x, y);
100 evas_object_resize(wd->content, w, h);
101 }
102}
103
104static void
105_configure(Evas_Object *obj)
106{
107 Widget_Data *wd = elm_widget_data_get(obj);
108 if (!wd) return;
109 if (wd->content)
110 {
111 Evas_Coord x, y, w, h, x2, y2;
112
113 evas_object_geometry_get(wd->clip, &x, &y, &w, &h);
114 evas_object_geometry_get(wd->content, &x2, &y2, NULL, NULL);
115 if ((x != x2) || (y != y2))
116 {
117 if (!wd->enabled)
118 evas_object_move(wd->content, x, y);
119 else
120 {
121
122 Evas *e = evas_object_evas_get(obj);
123 evas_smart_objects_calculate(e);
124 evas_nochange_push(e);
125 evas_object_move(wd->content, x, y);
126 evas_smart_objects_calculate(e);
127 evas_nochange_pop(e);
128 }
129 }
130 evas_object_resize(wd->content, w, h);
131 _mapbuf(obj);
132 }
133}
134
135static void
136_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
137{
138 _configure(data);
139}
140
141static void
142_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
143{
144 _configure(data);
145}
146
147static void
148_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
149{
150 ELM_CHECK_WIDTYPE(obj, widtype);
151 Widget_Data *wd;
152
153 if (part && strcmp(part, "default")) return;
154 wd = elm_widget_data_get(obj);
155 if (!wd) return;
156 if (wd->content == content) return;
157 if (wd->content) evas_object_del(wd->content);
158 wd->content = content;
159 if (content)
160 {
161 evas_object_data_set(content, "_elm_leaveme", (void *)1);
162 elm_widget_sub_object_add(obj, content);
163 evas_object_smart_member_add(content, obj);
164 evas_object_clip_set(content, wd->clip);
165 evas_object_color_set(wd->clip, 255, 255, 255, 255);
166 evas_object_event_callback_add(content,
167 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
168 _changed_size_hints, obj);
169 }
170 else
171 evas_object_color_set(wd->clip, 0, 0, 0, 0);
172 _sizing_eval(obj);
173 _configure(obj);
174}
175
176static Evas_Object *
177_content_get_hook(const Evas_Object *obj, const char *part)
178{
179 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
180 Widget_Data *wd;
181
182 if (part && strcmp(part, "default")) return NULL;
183 wd = elm_widget_data_get(obj);
184 if (!wd) return NULL;
185 return wd->content;
186}
187
188static Evas_Object *
189_content_unset_hook(Evas_Object *obj, const char *part)
190{
191 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
192 Widget_Data *wd;
193 Evas_Object *content;
194
195 if (part && strcmp(part, "default")) return NULL;
196 wd = elm_widget_data_get(obj);
197 if (!wd) return NULL;
198 if (!wd->content) return NULL;
199 content = wd->content;
200 elm_widget_sub_object_del(obj, content);
201 evas_object_smart_member_del(content);
202 evas_object_color_set(wd->clip, 0, 0, 0, 0);
203 evas_object_data_del(content, "_elm_leaveme");
204 return content;
205}
206
207EAPI Evas_Object *
208elm_mapbuf_add(Evas_Object *parent)
209{
210 Evas_Object *obj;
211 Evas *e;
212 Widget_Data *wd;
213
214 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
215
216 ELM_SET_WIDTYPE(widtype, "mapbuf");
217 elm_widget_type_set(obj, "mapbuf");
218 elm_widget_sub_object_add(parent, obj);
219 elm_widget_data_set(obj, wd);
220 elm_widget_del_hook_set(obj, _del_hook);
221 elm_widget_theme_hook_set(obj, _theme_hook);
222 elm_widget_content_set_hook_set(obj, _content_set_hook);
223 elm_widget_content_get_hook_set(obj, _content_get_hook);
224 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
225 elm_widget_can_focus_set(obj, EINA_FALSE);
226
227 wd->clip = evas_object_rectangle_add(e);
228 evas_object_static_clip_set(wd->clip, EINA_TRUE);
229 evas_object_pass_events_set(wd->clip, EINA_TRUE);
230 evas_object_color_set(wd->clip, 0, 0, 0, 0);
231
232 evas_object_event_callback_add(wd->clip, EVAS_CALLBACK_MOVE, _move, obj);
233 evas_object_event_callback_add(wd->clip, EVAS_CALLBACK_RESIZE, _resize, obj);
234 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
235
236 elm_widget_resize_object_set(obj, wd->clip);
237
238 wd->enabled = 0;
239 wd->alpha = 1;
240 wd->smooth = 1;
241
242 _sizing_eval(obj);
243 return obj;
244}
245
246EAPI void
247elm_mapbuf_enabled_set(Evas_Object *obj, Eina_Bool enabled)
248{
249 ELM_CHECK_WIDTYPE(obj, widtype);
250 Widget_Data *wd = elm_widget_data_get(obj);
251 if (!wd) return;
252 if (wd->enabled == enabled) return;
253 wd->enabled = enabled;
254 if (wd->content) evas_object_static_clip_set(wd->content, wd->enabled);
255 _configure(obj);
256}
257
258EAPI Eina_Bool
259elm_mapbuf_enabled_get(const Evas_Object *obj)
260{
261 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
262 Widget_Data *wd = elm_widget_data_get(obj);
263 if (!wd) return EINA_FALSE;
264 return wd->enabled;
265}
266
267EAPI void
268elm_mapbuf_smooth_set(Evas_Object *obj, Eina_Bool smooth)
269{
270 ELM_CHECK_WIDTYPE(obj, widtype);
271 Widget_Data *wd = elm_widget_data_get(obj);
272 if (!wd) return;
273 if (wd->smooth == smooth) return;
274 wd->smooth = smooth;
275 _configure(obj);
276}
277
278EAPI Eina_Bool
279elm_mapbuf_smooth_get(const Evas_Object *obj)
280{
281 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
282 Widget_Data *wd = elm_widget_data_get(obj);
283 if (!wd) return EINA_FALSE;
284 return wd->smooth;
285}
286
287EAPI void
288elm_mapbuf_alpha_set(Evas_Object *obj, Eina_Bool alpha)
289{
290 ELM_CHECK_WIDTYPE(obj, widtype);
291 Widget_Data *wd = elm_widget_data_get(obj);
292 if (!wd) return;
293 if (wd->alpha == alpha) return;
294 wd->alpha = alpha;
295 _configure(obj);
296}
297
298EAPI Eina_Bool
299elm_mapbuf_alpha_get(const Evas_Object *obj)
300{
301 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
302 Widget_Data *wd = elm_widget_data_get(obj);
303 if (!wd) return EINA_FALSE;
304 return wd->alpha;
305}
diff --git a/libraries/elementary/src/lib/elm_mapbuf.h b/libraries/elementary/src/lib/elm_mapbuf.h
new file mode 100644
index 0000000..462d758
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_mapbuf.h
@@ -0,0 +1,149 @@
1/**
2 * @defgroup Mapbuf Mapbuf
3 * @ingroup Elementary
4 *
5 * @image html img/widget/mapbuf/preview-00.png
6 * @image latex img/widget/mapbuf/preview-00.eps width=\textwidth
7 *
8 * This holds one content object and uses an Evas Map of transformation
9 * points to be later used with this content. So the content will be
10 * moved, resized, etc as a single image. So it will improve performance
11 * when you have a complex interface, with a lot of elements, and will
12 * need to resize or move it frequently (the content object and its
13 * children).
14 *
15 * Default content parts of the mapbuf widget that you can use for are:
16 * @li "default" - A content of the mapbuf
17 *
18 * Supported elm_object common APIs.
19 * @li @ref elm_object_part_content_set
20 * @li @ref elm_object_part_content_get
21 * @li @ref elm_object_part_content_unset
22 *
23 * To enable map, elm_mapbuf_enabled_set() should be used.
24 *
25 * See how to use this widget in this example:
26 * @ref mapbuf_example
27 */
28
29/**
30 * @addtogroup Mapbuf
31 * @{
32 */
33
34/**
35 * Add a new mapbuf widget to the given parent Elementary
36 * (container) object.
37 *
38 * @param parent The parent object.
39 * @return A new mapbuf widget handle or @c NULL, on errors.
40 *
41 * This function inserts a new mapbuf widget on the canvas.
42 *
43 * @ingroup Mapbuf
44 */
45EAPI Evas_Object *elm_mapbuf_add(Evas_Object *parent);
46
47/**
48 * Enable or disable the map.
49 *
50 * @param obj The mapbuf object.
51 * @param enabled @c EINA_TRUE to enable map or @c EINA_FALSE to disable it.
52 *
53 * This enables the map that is set or disables it. On enable, the object
54 * geometry will be saved, and the new geometry will change (position and
55 * size) to reflect the map geometry set.
56 *
57 * Also, when enabled, alpha and smooth states will be used, so if the
58 * content isn't solid, alpha should be enabled, for example, otherwise
59 * a black rectangle will fill the content.
60 *
61 * When disabled, the stored map will be freed and geometry prior to
62 * enabling the map will be restored.
63 *
64 * It's disabled by default.
65 *
66 * @see elm_mapbuf_alpha_set()
67 * @see elm_mapbuf_smooth_set()
68 *
69 * @ingroup Mapbuf
70 */
71EAPI void elm_mapbuf_enabled_set(Evas_Object *obj, Eina_Bool enabled);
72
73/**
74 * Get a value whether map is enabled or not.
75 *
76 * @param obj The mapbuf object.
77 * @return @c EINA_TRUE means map is enabled. @c EINA_FALSE indicates
78 * it's disabled. If @p obj is @c NULL, @c EINA_FALSE is returned.
79 *
80 * @see elm_mapbuf_enabled_set() for details.
81 *
82 * @ingroup Mapbuf
83 */
84EAPI Eina_Bool elm_mapbuf_enabled_get(const Evas_Object *obj);
85
86/**
87 * Enable or disable smooth map rendering.
88 *
89 * @param obj The mapbuf object.
90 * @param smooth @c EINA_TRUE to enable smooth map rendering or @c EINA_FALSE
91 * to disable it.
92 *
93 * This sets smoothing for map rendering. If the object is a type that has
94 * its own smoothing settings, then both the smooth settings for this object
95 * and the map must be turned off.
96 *
97 * By default smooth maps are enabled.
98 *
99 * @ingroup Mapbuf
100 */
101EAPI void elm_mapbuf_smooth_set(Evas_Object *obj, Eina_Bool smooth);
102
103/**
104 * Get a value whether smooth map rendering is enabled or not.
105 *
106 * @param obj The mapbuf object.
107 * @return @c EINA_TRUE means smooth map rendering is enabled. @c EINA_FALSE
108 * indicates it's disabled. If @p obj is @c NULL, @c EINA_FALSE is returned.
109 *
110 * @see elm_mapbuf_smooth_set() for details.
111 *
112 * @ingroup Mapbuf
113 */
114EAPI Eina_Bool elm_mapbuf_smooth_get(const Evas_Object *obj);
115
116/**
117 * Set or unset alpha flag for map rendering.
118 *
119 * @param obj The mapbuf object.
120 * @param alpha @c EINA_TRUE to enable alpha blending or @c EINA_FALSE
121 * to disable it.
122 *
123 * This sets alpha flag for map rendering. If the object is a type that has
124 * its own alpha settings, then this will take precedence. Only image objects
125 * have this currently. It stops alpha blending of the map area, and is
126 * useful if you know the object and/or all sub-objects is 100% solid.
127 *
128 * Alpha is enabled by default.
129 *
130 * @ingroup Mapbuf
131 */
132EAPI void elm_mapbuf_alpha_set(Evas_Object *obj, Eina_Bool alpha);
133
134/**
135 * Get a value whether alpha blending is enabled or not.
136 *
137 * @param obj The mapbuf object.
138 * @return @c EINA_TRUE means alpha blending is enabled. @c EINA_FALSE
139 * indicates it's disabled. If @p obj is @c NULL, @c EINA_FALSE is returned.
140 *
141 * @see elm_mapbuf_alpha_set() for details.
142 *
143 * @ingroup Mapbuf
144 */
145EAPI Eina_Bool elm_mapbuf_alpha_get(const Evas_Object *obj);
146
147/**
148 * @}
149 */
diff --git a/libraries/elementary/src/lib/elm_menu.c b/libraries/elementary/src/lib/elm_menu.c
new file mode 100644
index 0000000..0cb0da0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_menu.c
@@ -0,0 +1,968 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Menu_Item Elm_Menu_Item;
6
7struct _Elm_Menu_Item
8{
9 ELM_WIDGET_ITEM;
10 Elm_Menu_Item *parent;
11 Evas_Object *content;
12 const char *icon_str;
13 const char *label;
14 Evas_Smart_Cb func;
15 unsigned int idx;
16
17 struct
18 {
19 Evas_Object *hv, *bx, *location;
20 Eina_List *items;
21 Eina_Bool open : 1;
22 } submenu;
23
24 Eina_Bool separator : 1;
25 Eina_Bool selected : 1;
26 Eina_Bool object_item : 1;
27};
28
29struct _Widget_Data
30{
31 Evas_Object *hv, *bx, *location, *parent, *obj;
32 Eina_List *items;
33 Evas_Coord xloc, yloc;
34};
35
36static const char *widtype = NULL;
37static void _del_hook(Evas_Object *obj);
38static void _theme_hook(Evas_Object *obj);
39static void _item_disable_hook(Elm_Object_Item *it);
40static void _sizing_eval(Evas_Object *obj);
41static void _submenu_sizing_eval(Elm_Menu_Item *parent);
42static void _item_sizing_eval(Elm_Menu_Item *item);
43static void _submenu_hide(Elm_Menu_Item *item);
44static void _submenu_open(void *data, Evas_Object *obj, const char *emission, const char *source);
45static void _parent_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
46static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
47static void _menu_hide(void *data, Evas_Object *obj, void *event_info);
48
49static const char SIG_CLICKED[] = "clicked";
50
51static const Evas_Smart_Cb_Description _signals[] = {
52 {SIG_CLICKED, ""},
53 {NULL, NULL}
54};
55
56
57static void
58_del_item(Elm_Menu_Item *item)
59{
60 Elm_Menu_Item *child;
61
62 EINA_LIST_FREE(item->submenu.items, child)
63 _del_item(child);
64
65 if (item->label) eina_stringshare_del(item->label);
66 if (item->submenu.hv) evas_object_del(item->submenu.hv);
67 if (item->submenu.location) evas_object_del(item->submenu.location);
68 if (item->icon_str) eina_stringshare_del(item->icon_str);
69 elm_widget_item_free(item);
70}
71
72static void
73_del_pre_hook(Evas_Object *obj)
74{
75 Elm_Menu_Item *item;
76 Widget_Data *wd = elm_widget_data_get(obj);
77 if (!wd) return;
78
79 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, obj);
80 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
81
82 EINA_LIST_FREE(wd->items, item)
83 _del_item(item);
84
85 if (wd->hv) evas_object_del(wd->hv);
86 if (wd->location) evas_object_del(wd->location);
87}
88
89static void
90_del_hook(Evas_Object *obj)
91{
92 Widget_Data *wd = elm_widget_data_get(obj);
93 free(wd);
94}
95
96static void
97_theme_hook(Evas_Object *obj)
98{
99 Eina_List *l, *_l, *_ll, *ll = NULL;
100 Elm_Menu_Item *item;
101 Widget_Data *wd = elm_widget_data_get(obj);
102 if (!wd) return;
103 _elm_widget_mirrored_reload(obj);
104 ll = eina_list_append(ll, wd->items);
105 EINA_LIST_FOREACH(ll, _ll, l)
106 {
107 EINA_LIST_FOREACH(l, _l, item)
108 {
109 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(obj));
110 ll = eina_list_append(ll, item->submenu.items);
111 if (item->separator)
112 _elm_theme_object_set(obj, VIEW(item), "menu", "separator",
113 elm_widget_style_get(obj));
114 else if (item->submenu.bx)
115 {
116 _elm_theme_object_set
117 (obj, VIEW(item), "menu", "item_with_submenu",
118 elm_widget_style_get(obj));
119 elm_object_item_text_set((Elm_Object_Item *)item,
120 item->label);
121 elm_menu_item_icon_name_set((Elm_Object_Item *)item,
122 item->icon_str);
123 }
124 else
125 {
126 _elm_theme_object_set(obj, VIEW(item), "menu", "item",
127 elm_widget_style_get(obj));
128 elm_object_item_text_set((Elm_Object_Item *)item,
129 item->label);
130 elm_menu_item_icon_name_set((Elm_Object_Item *)item,
131 item->icon_str);
132 }
133 _item_disable_hook((Elm_Object_Item *)item);
134 edje_object_scale_set(VIEW(item), elm_widget_scale_get(obj) *
135 _elm_config->scale);
136 }
137 }
138 _sizing_eval(obj);
139}
140
141static void
142_item_text_set_hook(Elm_Object_Item *it,
143 const char *part,
144 const char *label)
145{
146 Elm_Menu_Item *item;
147
148 if (part && strcmp(part, "default")) return;
149
150 item = (Elm_Menu_Item *)it;
151
152 eina_stringshare_replace(&item->label, label);
153
154 if (label)
155 edje_object_signal_emit(VIEW(item), "elm,state,text,visible", "elm");
156 else
157 edje_object_signal_emit(VIEW(item), "elm,state,text,hidden", "elm");
158
159 edje_object_message_signal_process(VIEW(item));
160 edje_object_part_text_set(VIEW(item), "elm.text", label);
161 _sizing_eval(WIDGET(item));
162}
163
164static const char *
165_item_text_get_hook(const Elm_Object_Item *it, const char *part)
166{
167 if (part && strcmp(part, "default")) return NULL;
168 return ((Elm_Menu_Item *)it)->label;
169}
170
171static void
172_item_content_set_hook(Elm_Object_Item *it,
173 const char *part,
174 Evas_Object *content)
175{
176 Elm_Menu_Item *item;
177 if (part && strcmp(part, "default")) return;
178
179 item = (Elm_Menu_Item *)it;
180 if (content == item->content) return;
181
182 if (item->content) evas_object_del(item->content);
183
184 item->content = content;
185 elm_widget_sub_object_add(WIDGET(item), item->content);
186 if (item->content)
187 edje_object_part_swallow(VIEW(item), "elm.swallow.content", item->content);
188 _sizing_eval(WIDGET(item));
189}
190
191static Evas_Object *
192_item_content_get_hook(const Elm_Object_Item *it, const char *part)
193{
194 if (part && strcmp(part, "default")) return NULL;
195 return ((Elm_Menu_Item *)it)->content;
196}
197
198static void
199_item_disable_hook(Elm_Object_Item *it)
200{
201 Elm_Menu_Item *item = (Elm_Menu_Item *)it;
202
203 if (elm_widget_item_disabled_get(item))
204 {
205 edje_object_signal_emit(VIEW(item), "elm,state,disabled", "elm");
206 if (item->submenu.open) _submenu_hide(item);
207 }
208 else
209 edje_object_signal_emit(VIEW(item), "elm,state,enabled", "elm");
210
211 edje_object_message_signal_process(VIEW(item));
212}
213
214static void
215_sizing_eval(Evas_Object *obj)
216{
217 Eina_List *l;
218 Elm_Menu_Item *item;
219 Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh;
220 Widget_Data *wd = elm_widget_data_get(obj);
221 if ((!wd) || (!wd->parent)) return;
222 EINA_LIST_FOREACH(wd->items,l,item) _item_sizing_eval(item);
223 evas_object_geometry_get(wd->location, &x_p, &y_p, &w_p, &h_p);
224 evas_object_geometry_get(wd->parent, &x2, &y2, &w2, &h2);
225 evas_object_geometry_get(wd->bx, &bx, &by, &bw, &bh);
226
227 x_p = wd->xloc;
228 y_p = wd->yloc;
229
230 if (elm_widget_mirrored_get(obj))
231 x_p -= w_p;
232
233 if (x_p+bw > x2+w2) x_p -= x_p+bw - (x2+w2);
234 if (x_p < x2) x_p += x2 - x_p;
235
236 if (y_p+h_p+bh > y2+h2) y_p -= y_p+h_p+bh - (y2+h2);
237 if (y_p < y2) y_p += y2 - y_p;
238
239
240 evas_object_move(wd->location, x_p, y_p);
241 evas_object_resize(wd->location, bw, h_p);
242 evas_object_size_hint_min_set(wd->location, bw, h_p);
243 evas_object_size_hint_max_set(wd->location, bw, h_p);
244 elm_hover_target_set(wd->hv, wd->location);
245
246 EINA_LIST_FOREACH(wd->items,l,item)
247 {
248 if (item->submenu.open) _submenu_sizing_eval(item);
249 }
250}
251
252static void
253_submenu_sizing_eval(Elm_Menu_Item *parent)
254{
255 Eina_List *l;
256 Elm_Menu_Item *item;
257 Evas_Coord x_p, y_p, w_p, h_p, x2, y2, w2, h2, bx, by, bw, bh, px, py, pw, ph;
258 Widget_Data *wd = elm_widget_data_get(WIDGET(parent));
259 if (!wd) return;
260 EINA_LIST_FOREACH(parent->submenu.items, l, item) _item_sizing_eval(item);
261 evas_object_geometry_get(parent->submenu.location, &x_p, &y_p, &w_p, &h_p);
262 evas_object_geometry_get(VIEW(parent), &x2, &y2, &w2, &h2);
263 evas_object_geometry_get(parent->submenu.bx, &bx, &by, &bw, &bh);
264 evas_object_geometry_get(wd->parent, &px, &py, &pw, &ph);
265
266 x_p = x2+w2;
267 y_p = y2;
268
269 /* If it overflows on the right, adjust the x */
270 if ((x_p + bw > px + pw) || elm_widget_mirrored_get(WIDGET(parent)))
271 x_p = x2-bw;
272
273 /* If it overflows on the left, adjust the x - usually only happens
274 * with an RTL interface */
275 if (x_p < px)
276 x_p = x2 + w2;
277
278 /* If after all the adjustments it still overflows, fix it */
279 if (x_p + bw > px + pw)
280 x_p = x2-bw;
281
282 if (y_p+bh > py+ph)
283 y_p -= y_p+bh - (py+ph);
284 if (y_p < py)
285 y_p += y_p - y_p;
286
287 evas_object_move(parent->submenu.location, x_p, y_p);
288 evas_object_resize(parent->submenu.location, bw, h_p);
289 evas_object_size_hint_min_set(parent->submenu.location, bw, h_p);
290 evas_object_size_hint_max_set(parent->submenu.location, bw, h_p);
291 elm_hover_target_set(parent->submenu.hv, parent->submenu.location);
292
293 EINA_LIST_FOREACH(parent->submenu.items, l, item)
294 {
295 if (item->submenu.open)
296 _submenu_sizing_eval(item);
297 }
298}
299
300static void
301_item_sizing_eval(Elm_Menu_Item *item)
302{
303 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
304 if (!item->separator)
305 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
306 edje_object_size_min_restricted_calc(VIEW(item), &minw, &minh, minw, minh);
307 if (!item->separator)
308 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
309 evas_object_size_hint_min_set(VIEW(item), minw, minh);
310 evas_object_size_hint_max_set(VIEW(item), maxw, maxh);
311}
312
313static void
314_menu_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
315{
316 _sizing_eval(data);
317}
318
319static void
320_parent_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
321{
322 _sizing_eval(data);
323}
324
325static void
326_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
327{
328 Widget_Data *wd = data;
329 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
330 wd->parent = NULL;
331}
332
333static void
334_item_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
335{
336 Elm_Menu_Item *item = data;
337 if (item->submenu.open) _submenu_sizing_eval(item);
338}
339
340static void
341_hover_clicked_cb(void *data, Evas_Object *obj, void *event_info)
342{
343 _menu_hide(data, obj, event_info);
344 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
345}
346
347static void
348_menu_hide(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
349{
350 Eina_List *l;
351 Elm_Menu_Item *item2;
352 Widget_Data *wd = elm_widget_data_get(data);
353 if (!wd) return;
354 evas_object_hide(wd->hv);
355 evas_object_hide(data);
356
357 EINA_LIST_FOREACH(wd->items, l, item2)
358 {
359 if (item2->submenu.open) _submenu_hide(item2);
360 }
361}
362
363static void
364_submenu_hide(Elm_Menu_Item *item)
365{
366 Eina_List *l;
367 Elm_Menu_Item *item2;
368 evas_object_hide(item->submenu.hv);
369 item->submenu.open = EINA_FALSE;
370 EINA_LIST_FOREACH(item->submenu.items, l, item2)
371 {
372 if (item2->submenu.open) _submenu_hide(item2);
373 }
374}
375
376static void
377_menu_item_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
378{
379 Elm_Menu_Item *item = data;
380 if (item->submenu.items)
381 {
382 if (!item->submenu.open) _submenu_open(item, NULL, NULL, NULL);
383 else _submenu_hide(item);
384 }
385 else
386 _menu_hide(WIDGET(item), NULL, NULL);
387
388 if (item->func) item->func((void *)(item->base.data), WIDGET(item), item);
389}
390
391static void
392_menu_item_activate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
393{
394 Eina_List *l;
395 Elm_Menu_Item *item2;
396 Elm_Menu_Item *item = data;
397 item->selected = 1;
398 if (item->parent)
399 {
400 EINA_LIST_FOREACH(item->parent->submenu.items, l, item2)
401 {
402 if (item2 != item)
403 elm_menu_item_selected_set((Elm_Object_Item *)item2, 0);
404 }
405 }
406 else
407 {
408 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
409 EINA_LIST_FOREACH(wd->items, l, item2)
410 {
411 if (item2 != item)
412 elm_menu_item_selected_set((Elm_Object_Item *)item2, 0);
413 }
414 }
415}
416
417static void
418_menu_item_inactivate(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
419{
420 Elm_Menu_Item *item = data;
421 item->selected = 0;
422 if (item->submenu.open) _submenu_hide(item);
423}
424
425static void
426_submenu_open(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
427{
428 Elm_Menu_Item *item = data;
429 item->submenu.open = EINA_TRUE;
430 evas_object_show(item->submenu.hv);
431 _submenu_sizing_eval(item);
432}
433
434static void
435_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
436{
437 Widget_Data *wd = elm_widget_data_get(data);
438 if (!wd) return;
439 evas_object_show(wd->hv);
440}
441
442static void
443_item_obj_create(Elm_Menu_Item *item)
444{
445 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
446 if (!wd) return;
447 VIEW(item) = edje_object_add(evas_object_evas_get(wd->bx));
448 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
449 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
450 evas_object_size_hint_fill_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
451 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "item", elm_widget_style_get(WIDGET(item)));
452 edje_object_signal_callback_add(VIEW(item), "elm,action,click", "",
453 _menu_item_select, item);
454 edje_object_signal_callback_add(VIEW(item), "elm,action,activate", "",
455 _menu_item_activate, item);
456 edje_object_signal_callback_add(VIEW(item), "elm,action,inactivate", "",
457 _menu_item_inactivate, item);
458 evas_object_show(VIEW(item));
459}
460
461static void
462_item_separator_obj_create(Elm_Menu_Item *item)
463{
464 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
465 if (!wd) return;
466 VIEW(item) = edje_object_add(evas_object_evas_get(wd->bx));
467 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
468 evas_object_size_hint_fill_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
469 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "separator", elm_widget_style_get(WIDGET(item)));
470 edje_object_signal_callback_add(VIEW(item), "elm,action,activate", "",
471 _menu_item_activate, item);
472 evas_object_show(VIEW(item));
473}
474
475static void
476_item_submenu_obj_create(Elm_Menu_Item *item)
477{
478 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
479 if (!wd) return;
480 item->submenu.location = elm_icon_add(wd->bx);
481 item->submenu.hv = elm_hover_add(wd->bx);
482 elm_widget_mirrored_set(item->submenu.hv, EINA_FALSE);
483 elm_hover_target_set(item->submenu.hv, item->submenu.location);
484 elm_hover_parent_set(item->submenu.hv, wd->parent);
485 elm_object_style_set(item->submenu.hv, "submenu");
486
487 item->submenu.bx = elm_box_add(wd->bx);
488 elm_widget_mirrored_set(item->submenu.bx, EINA_FALSE);
489 evas_object_size_hint_weight_set(item->submenu.bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
490 evas_object_show(item->submenu.bx);
491 elm_object_part_content_set(item->submenu.hv, elm_hover_best_content_location_get(item->submenu.hv, ELM_HOVER_AXIS_VERTICAL), item->submenu.bx);
492
493 edje_object_mirrored_set(VIEW(item), elm_widget_mirrored_get(WIDGET(item)));
494 _elm_theme_object_set(WIDGET(item), VIEW(item), "menu", "item_with_submenu", elm_widget_style_get(WIDGET(item)));
495 elm_object_item_text_set((Elm_Object_Item *)item,
496 item->label);
497 if (item->icon_str)
498 elm_menu_item_icon_name_set((Elm_Object_Item *)item,
499 item->icon_str);
500 edje_object_signal_callback_add(VIEW(item), "elm,action,open", "",
501 _submenu_open, item);
502 evas_object_event_callback_add(VIEW(item), EVAS_CALLBACK_MOVE, _item_move_resize, item);
503 evas_object_event_callback_add(VIEW(item), EVAS_CALLBACK_RESIZE, _item_move_resize, item);
504
505 evas_object_event_callback_add(item->submenu.bx, EVAS_CALLBACK_RESIZE, _menu_resize, WIDGET(item));
506}
507
508EAPI Evas_Object *
509elm_menu_add(Evas_Object *parent)
510{
511 Evas_Object *obj;
512 Evas *e;
513 Widget_Data *wd;
514
515 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
516
517 ELM_SET_WIDTYPE(widtype, "menu");
518 elm_widget_type_set(obj, "menu");
519 elm_widget_sub_object_add(parent, obj);
520 elm_widget_data_set(obj, wd);
521 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
522 elm_widget_del_hook_set(obj, _del_hook);
523 elm_widget_theme_hook_set(obj, _theme_hook);
524 elm_widget_can_focus_set(obj, EINA_FALSE);
525
526 wd->location = elm_icon_add(obj);
527 wd->parent = parent;
528 wd->obj = obj;
529
530 wd->hv = elm_hover_add(obj);
531 elm_widget_mirrored_set(wd->hv, EINA_FALSE);
532 elm_hover_parent_set(wd->hv, parent);
533 elm_hover_target_set(wd->hv, wd->location);
534 elm_object_style_set(wd->hv, "menu");
535 evas_object_smart_callback_add(wd->hv, "clicked", _hover_clicked_cb, obj);
536
537 wd->bx = elm_box_add(obj);
538 elm_widget_mirrored_set(wd->bx, EINA_FALSE);
539 evas_object_size_hint_weight_set(wd->bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
540 evas_object_show(wd->bx);
541 elm_object_part_content_set(wd->hv, elm_hover_best_content_location_get(wd->hv, ELM_HOVER_AXIS_VERTICAL), wd->bx);
542
543 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
544 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
545
546 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
547
548 evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _menu_resize, obj);
549
550 evas_object_smart_callbacks_descriptions_set(obj, _signals);
551
552 _sizing_eval(obj);
553 return obj;
554}
555
556EAPI void
557elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
558{
559 Eina_List *l, *_l, *_ll, *ll = NULL;
560 Elm_Menu_Item *item;
561 ELM_CHECK_WIDTYPE(obj, widtype);
562 Widget_Data *wd = elm_widget_data_get(obj);
563 if (!wd) return;
564
565 if (wd->parent == parent) return;
566 if (wd->parent)
567 {
568 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
569 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
570 }
571 wd->parent = parent;
572 if (wd->parent)
573 {
574 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_RESIZE, _parent_resize, wd->obj);
575 evas_object_event_callback_add(wd->parent, EVAS_CALLBACK_DEL, _parent_del, wd);
576 }
577 elm_hover_parent_set(wd->hv, parent);
578
579 ll = eina_list_append(ll, wd->items);
580 EINA_LIST_FOREACH(ll, _ll, l)
581 {
582 EINA_LIST_FOREACH(l, _l, item)
583 {
584 if (item->submenu.hv)
585 {
586 elm_hover_parent_set(item->submenu.hv, parent);
587 ll = eina_list_append(ll, item->submenu.items);
588 }
589 }
590 }
591 _sizing_eval(obj);
592}
593
594EAPI Evas_Object *
595elm_menu_parent_get(const Evas_Object *obj)
596{
597 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
598 Widget_Data *wd = elm_widget_data_get(obj);
599 if (!wd) return NULL;
600 return wd->parent;
601}
602
603EAPI void
604elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
605{
606 ELM_CHECK_WIDTYPE(obj, widtype);
607 Widget_Data *wd = elm_widget_data_get(obj);
608 if (!wd) return;
609 wd->xloc = x;
610 wd->yloc = y;
611 _sizing_eval(obj);
612}
613
614EAPI void
615elm_menu_close(Evas_Object *obj)
616{
617 ELM_CHECK_WIDTYPE(obj, widtype);
618 Widget_Data *wd = elm_widget_data_get(obj);
619 _menu_hide(obj, wd->hv, NULL);
620}
621
622EAPI Evas_Object *
623elm_menu_item_object_get(const Elm_Object_Item *it)
624{
625 return VIEW(((Elm_Menu_Item *)it));
626}
627
628static void
629_item_clone(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *item)
630{
631 Elm_Object_Item *new_item;
632 Elm_Menu_Item *subitem;
633 Eina_List *iter;
634
635 if (item->separator)
636 new_item = elm_menu_item_separator_add(obj, (Elm_Object_Item *) parent);
637 else
638 new_item = elm_menu_item_add(obj,
639 (Elm_Object_Item *) parent,
640 item->icon_str,
641 item->label,
642 item->func,
643 item->base.data);
644 elm_object_item_disabled_set(new_item,
645 elm_widget_item_disabled_get(item));
646
647 EINA_LIST_FOREACH(item->submenu.items, iter, subitem)
648 _item_clone(obj, (Elm_Menu_Item *) new_item, subitem);
649}
650
651void
652elm_menu_clone(Evas_Object *from_menu, Evas_Object *to_menu, Elm_Object_Item *parent)
653{
654 ELM_CHECK_WIDTYPE(from_menu, widtype);
655 ELM_CHECK_WIDTYPE(to_menu, widtype);
656 Widget_Data *from_wd = elm_widget_data_get(from_menu);
657 Eina_List *iter;
658 Elm_Menu_Item *item;
659
660 if (!from_wd) return;
661 EINA_LIST_FOREACH(from_wd->items, iter, item)
662 _item_clone(to_menu, (Elm_Menu_Item *) parent, item);
663}
664
665static void
666_elm_menu_item_add_helper(Evas_Object *obj, Elm_Menu_Item *parent, Elm_Menu_Item *subitem, Widget_Data *wd)
667{
668 if (parent)
669 {
670 if (!parent->submenu.bx) _item_submenu_obj_create(parent);
671 elm_box_pack_end(parent->submenu.bx, VIEW(subitem));
672 parent->submenu.items = eina_list_append(parent->submenu.items, subitem);
673 subitem->idx = eina_list_count(parent->submenu.items) - 1;
674 }
675 else
676 {
677 elm_box_pack_end(wd->bx, VIEW(subitem));
678 wd->items = eina_list_append(wd->items, subitem);
679 subitem->idx = eina_list_count(wd->items) - 1;
680 }
681
682 _sizing_eval(obj);
683}
684
685static Eina_Bool
686_item_del_pre_hook(Elm_Object_Item *it)
687{
688 Elm_Menu_Item *item = (Elm_Menu_Item *)it;
689 Elm_Object_Item *_item;
690
691 EINA_LIST_FREE(item->submenu.items, _item) elm_object_item_del(_item);
692 if (item->label) eina_stringshare_del(item->label);
693 if (item->content) evas_object_del(item->content);
694 if (item->submenu.hv) evas_object_del(item->submenu.hv);
695 if (item->submenu.location) evas_object_del(item->submenu.location);
696
697 if (item->parent)
698 item->parent->submenu.items = eina_list_remove(item->parent->submenu.items, item);
699 else
700 {
701 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
702 wd->items = eina_list_remove(wd->items, item);
703 }
704
705 return EINA_TRUE;
706}
707
708EAPI Elm_Object_Item *
709elm_menu_item_add(Evas_Object *obj, Elm_Object_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
710{
711 Elm_Menu_Item *subitem;
712 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
713 Widget_Data *wd = elm_widget_data_get(obj);
714 Evas_Object *icon_obj;
715
716 if (!wd) return NULL;
717 icon_obj = elm_icon_add(obj);
718 if (!icon_obj) return NULL;
719 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
720 if (!subitem)
721 {
722 evas_object_del(icon_obj);
723 return NULL;
724 }
725
726 elm_widget_item_del_pre_hook_set(subitem, _item_del_pre_hook);
727 elm_widget_item_disable_hook_set(subitem, _item_disable_hook);
728 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
729 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
730 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
731 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
732
733 subitem->base.data = data;
734 subitem->func = func;
735 subitem->parent = (Elm_Menu_Item *) parent;
736 subitem->content = icon_obj;
737
738 _item_obj_create(subitem);
739 elm_object_item_text_set((Elm_Object_Item *) subitem, label);
740
741 elm_widget_sub_object_add(WIDGET(subitem), subitem->content);
742 edje_object_part_swallow(VIEW(subitem), "elm.swallow.content", subitem->content);
743 if (icon)
744 elm_menu_item_icon_name_set((Elm_Object_Item *) subitem, icon);
745
746 _elm_menu_item_add_helper(obj, (Elm_Menu_Item *) parent, subitem, wd);
747
748 return (Elm_Object_Item *) subitem;
749}
750
751EAPI unsigned int
752elm_menu_item_index_get(const Elm_Object_Item *it)
753{
754 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
755 return ((Elm_Menu_Item *)it)->idx;
756}
757
758EAPI void
759elm_menu_item_icon_name_set(Elm_Object_Item *it, const char *icon)
760{
761 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
762 EINA_SAFETY_ON_NULL_RETURN(icon);
763 char icon_tmp[512];
764 Elm_Menu_Item *item = (Elm_Menu_Item *)it;
765
766 if (!*icon) return;
767 if ((item->icon_str) && (!strcmp(item->icon_str, icon))) return;
768 if ((snprintf(icon_tmp, sizeof(icon_tmp), "menu/%s", icon) > 0) &&
769 (elm_icon_standard_set(item->content, icon_tmp) ||
770 elm_icon_standard_set(item->content, icon)))
771 {
772 eina_stringshare_replace(&item->icon_str, icon);
773 edje_object_signal_emit(VIEW(item), "elm,state,icon,visible", "elm");
774 }
775 else
776 edje_object_signal_emit(VIEW(item), "elm,state,icon,hidden", "elm");
777 edje_object_message_signal_process(VIEW(item));
778 _sizing_eval(WIDGET(item));
779}
780
781EAPI Elm_Object_Item *
782elm_menu_item_separator_add(Evas_Object *obj, Elm_Object_Item *parent)
783{
784 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
785 Elm_Menu_Item *subitem;
786 Widget_Data *wd = elm_widget_data_get(obj);
787 Elm_Menu_Item *p_item = (Elm_Menu_Item *) parent;
788 if (!wd) return NULL;
789 /* don't add a separator as the first item */
790 if (!wd->items) return NULL;
791 /* don't allow adding more than one separator in a row */
792 if (p_item) subitem = eina_list_last(p_item->submenu.items)->data;
793 else subitem = eina_list_last(wd->items)->data;
794 if (subitem->separator) return NULL;
795
796 subitem = elm_widget_item_new(obj, Elm_Menu_Item);
797 if (!subitem) return NULL;
798
799 elm_widget_item_del_pre_hook_set(subitem, _item_del_pre_hook);
800 elm_widget_item_disable_hook_set(subitem, _item_disable_hook);
801 elm_widget_item_text_set_hook_set(subitem, _item_text_set_hook);
802 elm_widget_item_text_get_hook_set(subitem, _item_text_get_hook);
803 elm_widget_item_content_set_hook_set(subitem, _item_content_set_hook);
804 elm_widget_item_content_get_hook_set(subitem, _item_content_get_hook);
805
806 subitem->separator = EINA_TRUE;
807 _item_separator_obj_create(subitem);
808 if (!p_item)
809 {
810 elm_box_pack_end(wd->bx, VIEW(subitem));
811 wd->items = eina_list_append(wd->items, subitem);
812 }
813 else
814 {
815 if (!p_item->submenu.bx) _item_submenu_obj_create(p_item);
816 elm_box_pack_end(p_item->submenu.bx, VIEW(subitem));
817 p_item->submenu.items = eina_list_append(p_item->submenu.items,
818 subitem);
819 }
820 _sizing_eval(obj);
821 return (Elm_Object_Item *) subitem;
822}
823
824EAPI const char *
825elm_menu_item_icon_name_get(const Elm_Object_Item *it)
826{
827 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
828 return ((Elm_Menu_Item *)it)->icon_str;
829}
830
831EAPI Eina_Bool
832elm_menu_item_is_separator(Elm_Object_Item *it)
833{
834 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
835 return ((Elm_Menu_Item *)it)->separator;
836}
837
838EAPI const Eina_List *
839elm_menu_item_subitems_get(const Elm_Object_Item *it)
840{
841 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
842 return ((Elm_Menu_Item *)it)->submenu.items;
843}
844
845EAPI const Eina_List *
846elm_menu_items_get(const Evas_Object * obj)
847{
848 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
849 Widget_Data *wd = elm_widget_data_get(obj);
850 return wd->items;
851}
852
853EAPI void
854elm_menu_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
855{
856 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
857 Elm_Menu_Item *item = (Elm_Menu_Item *)it;
858
859 if (selected == item->selected) return;
860 item->selected = selected;
861 if (selected)
862 {
863 edje_object_signal_emit(VIEW(item), "elm,state,selected", "elm");
864 _menu_item_activate(item, NULL, NULL, NULL);
865 }
866 else
867 {
868 edje_object_signal_emit(VIEW(item), "elm,state,unselected", "elm");
869 _menu_item_inactivate(item, NULL, NULL, NULL);
870 }
871 edje_object_message_signal_process(VIEW(item));
872}
873
874EAPI Eina_Bool
875elm_menu_item_selected_get(const Elm_Object_Item *it)
876{
877 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
878 return ((Elm_Menu_Item *)it)->selected;
879}
880
881EAPI Elm_Object_Item *
882elm_menu_item_prev_get(const Elm_Object_Item *it)
883{
884 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
885 Elm_Menu_Item *item = (Elm_Menu_Item *)it;
886
887 if (item->parent)
888 {
889 Eina_List *l = eina_list_data_find_list(item->parent->submenu.items,
890 item);
891 l = eina_list_prev(l);
892 if (!l) return NULL;
893 return l->data;
894 }
895 else
896 {
897 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
898 if (!wd || !wd->items) return NULL;
899 Eina_List *l = eina_list_data_find_list(wd->items, item);
900 l = eina_list_prev(l);
901 if (!l) return NULL;
902 return l->data;
903 }
904 return NULL;
905}
906
907EAPI Elm_Object_Item *
908elm_menu_item_next_get(const Elm_Object_Item *it)
909{
910 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
911 Elm_Menu_Item *item = (Elm_Menu_Item *)it;
912
913 if (item->parent)
914 {
915 Eina_List *l = eina_list_data_find_list(item->parent->submenu.items,
916 item);
917 l = eina_list_next(l);
918 if (!l) return NULL;
919 return l->data;
920 }
921 else
922 {
923 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
924 if (!wd || !wd->items) return NULL;
925 Eina_List *l = eina_list_data_find_list(wd->items, item);
926 l = eina_list_next(l);
927 if (!l) return NULL;
928 return l->data;
929 }
930 return NULL;
931}
932
933EAPI Elm_Object_Item *
934elm_menu_first_item_get(const Evas_Object * obj)
935{
936 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
937 Widget_Data *wd = elm_widget_data_get(obj);
938 if (!wd) return NULL;
939 if (wd->items) return wd->items->data;
940 return NULL;
941}
942
943EAPI Elm_Object_Item *
944elm_menu_last_item_get(const Evas_Object * obj)
945{
946 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
947 Widget_Data *wd = elm_widget_data_get(obj);
948 if (!wd) return NULL;
949 Eina_List *l = eina_list_last(wd->items);
950 if (l) return l->data;
951 return NULL;
952}
953
954EAPI Elm_Object_Item *
955elm_menu_selected_item_get(const Evas_Object * obj)
956{
957 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
958 Widget_Data *wd = elm_widget_data_get(obj);
959 if (!wd) return NULL;
960 Eina_List *l;
961 Elm_Menu_Item *item;
962 EINA_LIST_FOREACH(wd->items, l, item)
963 {
964 if (item->selected) return ((Elm_Object_Item *)item);
965 }
966 return NULL;
967}
968
diff --git a/libraries/elementary/src/lib/elm_menu.h b/libraries/elementary/src/lib/elm_menu.h
new file mode 100644
index 0000000..fcb40e1
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_menu.h
@@ -0,0 +1,283 @@
1/**
2 * @defgroup Menu Menu
3 * @ingroup Elementary
4 *
5 * @image html img/widget/menu/preview-00.png
6 * @image latex img/widget/menu/preview-00.eps
7 *
8 * A menu is a list of items displayed above its parent. When the menu is
9 * showing its parent is darkened. Each item can have a sub-menu. The menu
10 * object can be used to display a menu on a right click event, in a toolbar,
11 * anywhere.
12 *
13 * Signals that you can add callbacks for are:
14 * @li "clicked" - the user clicked the empty space in the menu to dismiss.
15 *
16 * Default content parts of the menu items that you can use for are:
17 * @li "default" - A main content of the menu item
18 *
19 * Default text parts of the menu items that you can use for are:
20 * @li "default" - label in the menu item
21 *
22 * Supported elm_object_item common APIs.
23 * @li @ref elm_object_item_part_text_set
24 * @li @ref elm_object_item_part_text_get
25 * @li @ref elm_object_item_part_content_set
26 * @li @ref elm_object_item_part_content_get
27 * @li @ref elm_object_item_disabled_set
28 * @li @ref elm_object_item_disabled_get
29 *
30 * @see @ref tutorial_menu
31 * @{
32 */
33
34/**
35 * @brief Add a new menu to the parent
36 *
37 * @param parent The parent object.
38 * @return The new object or NULL if it cannot be created.
39 *
40 * @ingroup Menu
41 */
42EAPI Evas_Object *elm_menu_add(Evas_Object *parent);
43
44/**
45 * @brief Set the parent for the given menu widget
46 *
47 * @param obj The menu object.
48 * @param parent The new parent.
49 *
50 * @ingroup Menu
51 */
52EAPI void elm_menu_parent_set(Evas_Object *obj, Evas_Object *parent);
53
54/**
55 * @brief Get the parent for the given menu widget
56 *
57 * @param obj The menu object.
58 * @return The parent.
59 *
60 * @see elm_menu_parent_set()
61 *
62 * @ingroup Menu
63 */
64EAPI Evas_Object *elm_menu_parent_get(const Evas_Object *obj);
65
66/**
67 * @brief Move the menu to a new position
68 *
69 * @param obj The menu object.
70 * @param x The new position.
71 * @param y The new position.
72 *
73 * Sets the top-left position of the menu to (@p x,@p y).
74 *
75 * @note @p x and @p y coordinates are relative to parent.
76 *
77 * @ingroup Menu
78 */
79EAPI void elm_menu_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
80
81/**
82 * @brief Close a opened menu
83 *
84 * @param obj the menu object
85 * @return void
86 *
87 * Hides the menu and all it's sub-menus.
88 *
89 * @ingroup Menu
90 */
91EAPI void elm_menu_close(Evas_Object *obj);
92
93/**
94 * @brief Returns a list of @p item's items.
95 *
96 * @param obj The menu object
97 * @return An Eina_List* of @p item's items
98 *
99 * @ingroup Menu
100 */
101EAPI const Eina_List *elm_menu_items_get(const Evas_Object *obj);
102
103/**
104 * @brief Get the Evas_Object of an Elm_Object_Item
105 *
106 * @param it The menu item object.
107 * @return The edje object containing the swallowed content
108 *
109 * @warning Don't manipulate this object!
110 *
111 * @ingroup Menu
112 */
113EAPI Evas_Object *elm_menu_item_object_get(const Elm_Object_Item *it);
114
115/**
116 * @brief Add an item at the end of the given menu widget
117 *
118 * @param obj The menu object.
119 * @param parent The parent menu item (optional)
120 * @param icon An icon display on the item. The icon will be destroyed by the menu.
121 * @param label The label of the item.
122 * @param func Function called when the user select the item.
123 * @param data Data sent by the callback.
124 * @return Returns the new item.
125 *
126 * @ingroup Menu
127 */
128EAPI Elm_Object_Item *elm_menu_item_add(Evas_Object *obj, Elm_Object_Item *parent, const char *icon, const char *label, Evas_Smart_Cb func, const void *data);
129
130/**
131 * @brief Set the icon of a menu item to the standard icon with name @p icon
132 *
133 * @param it The menu item object.
134 * @param icon The name of icon object to set for the content of @p item
135 *
136 * Once this icon is set, any previously set icon will be deleted.
137 *
138 * @ingroup Menu
139 */
140EAPI void elm_menu_item_icon_name_set(Elm_Object_Item *it, const char *icon);
141
142/**
143 * @brief Get the string representation from the icon of a menu item
144 *
145 * @param it The menu item object.
146 * @return The string representation of @p item's icon or NULL
147 *
148 * @see elm_menu_item_icon_name_set()
149 *
150 * @ingroup Menu
151 */
152EAPI const char *elm_menu_item_icon_name_get(const Elm_Object_Item *it);
153
154/**
155 * @brief Set the selected state of @p item.
156 *
157 * @param it The menu item object.
158 * @param selected The selected/unselected state of the item
159 *
160 * @ingroup Menu
161 */
162EAPI void elm_menu_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
163
164/**
165 * @brief Get the selected state of @p item.
166 *
167 * @param it The menu item object.
168 * @return The selected/unselected state of the item
169 *
170 * @see elm_menu_item_selected_set()
171 *
172 * @ingroup Menu
173 */
174EAPI Eina_Bool elm_menu_item_selected_get(const Elm_Object_Item *it);
175
176/**
177 * @brief Add a separator item to menu @p obj under @p parent.
178 *
179 * @param obj The menu object
180 * @param parent The item to add the separator under
181 * @return The created item or NULL on failure
182 *
183 * This is item is a @ref Separator.
184 *
185 * @ingroup Menu
186 */
187EAPI Elm_Object_Item *elm_menu_item_separator_add(Evas_Object *obj, Elm_Object_Item *parent);
188
189/**
190 * @brief Returns whether @p item is a separator.
191 *
192 * @param it The item to check
193 * @return If true, @p item is a separator
194 *
195 * @see elm_menu_item_separator_add()
196 *
197 * @ingroup Menu
198 */
199EAPI Eina_Bool elm_menu_item_is_separator(Elm_Object_Item *it);
200
201/**
202 * @brief Returns a list of @p item's subitems.
203 *
204 * @param it The item
205 * @return An Eina_List* of @p item's subitems
206 *
207 * @see elm_menu_add()
208 *
209 * @ingroup Menu
210 */
211EAPI const Eina_List *elm_menu_item_subitems_get(const Elm_Object_Item *it);
212
213/**
214 * @brief Get the position of a menu item
215 *
216 * @param it The menu item
217 * @return The item's index
218 *
219 * This function returns the index position of a menu item in a menu.
220 * For a sub-menu, this number is relative to the first item in the sub-menu.
221 *
222 * @note Index values begin with 0
223 *
224 * @ingroup Menu
225 */
226EAPI unsigned int elm_menu_item_index_get(const Elm_Object_Item *it);
227
228/**
229 * @brief Get the selected item in the menu
230 *
231 * @param obj The menu object
232 * @return The selected item, or NULL if none
233 *
234 * @see elm_menu_item_selected_get()
235 * @see elm_menu_item_selected_set()
236 *
237 * @ingroup Menu
238 */
239EAPI Elm_Object_Item *elm_menu_selected_item_get(const Evas_Object *obj);
240
241/**
242 * @brief Get the last item in the menu
243 *
244 * @param obj The menu object
245 * @return The last item, or NULL if none
246 *
247 * @ingroup Menu
248 */
249EAPI Elm_Object_Item *elm_menu_last_item_get(const Evas_Object *obj);
250
251/**
252 * @brief Get the first item in the menu
253 *
254 * @param obj The menu object
255 * @return The first item, or NULL if none
256 *
257 * @ingroup Menu
258 */
259EAPI Elm_Object_Item *elm_menu_first_item_get(const Evas_Object *obj);
260
261/**
262 * @brief Get the next item in the menu.
263 *
264 * @param it The menu item object.
265 * @return The item after it, or NULL if none
266 *
267 * @ingroup Menu
268 */
269EAPI Elm_Object_Item *elm_menu_item_next_get(const Elm_Object_Item *it);
270
271/**
272 * @brief Get the previous item in the menu.
273 *
274 * @param it The menu item object.
275 * @return The item before it, or NULL if none
276 *
277 * @ingroup Menu
278 */
279EAPI Elm_Object_Item *elm_menu_item_prev_get(const Elm_Object_Item *it);
280
281/**
282 * @}
283 */
diff --git a/libraries/elementary/src/lib/elm_mirroring.h b/libraries/elementary/src/lib/elm_mirroring.h
new file mode 100644
index 0000000..24baa48
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_mirroring.h
@@ -0,0 +1,59 @@
1/**
2 * @defgroup Mirroring Mirroring
3 * @ingroup Elementary
4 *
5 * These functions allow you to set ui-mirroring on specific
6 * widgets or the whole interface. Widgets can be in one of two
7 * modes, automatic and manual. Automatic means they'll be changed
8 * according to the system mirroring mode and manual means only
9 * explicit changes will matter. You are not supposed to change
10 * mirroring state of a widget set to automatic, will mostly work,
11 * but the behavior is not really defined.
12 *
13 * @{
14 */
15
16/**
17 * Get the widget's mirrored mode.
18 *
19 * @param obj The widget.
20 * @return EINA_TRUE if mirrored is set, EINA_FALSE otherwise
21 *
22 * @ingroup Mirroring
23 */
24EAPI Eina_Bool elm_object_mirrored_get(const Evas_Object *obj);
25
26/**
27 * Set the widget's mirrored mode.
28 *
29 * @param obj The widget.
30 * @param mirrored EINA_TRUE to set mirrored mode, EINA_FALSE to unset it.
31 *
32 * @ingroup Mirroring
33 */
34EAPI void elm_object_mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
35
36/**
37 * Returns the widget's mirrored mode setting.
38 *
39 * @param obj The widget.
40 * @return mirrored mode setting of the object.
41 *
42 * @ingroup Mirroring
43 */
44EAPI Eina_Bool elm_object_mirrored_automatic_get(const Evas_Object *obj);
45
46/**
47 * Sets the widget's mirrored mode setting.
48 * When widget in automatic mode, it follows the system mirrored mode set by
49 * elm_mirrored_set().
50 * @param obj The widget.
51 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
52 *
53 * @ingroup Mirroring
54 */
55EAPI void elm_object_mirrored_automatic_set(Evas_Object *obj, Eina_Bool automatic);
56
57/**
58 * @}
59 */
diff --git a/libraries/elementary/src/lib/elm_module.c b/libraries/elementary/src/lib/elm_module.c
new file mode 100644
index 0000000..396e9de
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_module.c
@@ -0,0 +1,251 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4/* what are moodules in elementary for? for modularising behavior and features
5 * so they can be plugged in and out where you dont want the core source to
6 * always behave like that or do it that way. plug it at runtime!
7 *
8 * they have module names (in config) and "slots" to plug that module into
9 * to server a purpose. eg you plug plugin "xx" into the "entry-copy-paste"
10 * slot so it would provide replacement copy & paste ui functionality and
11 * specific symbols
12 *
13 * config is something like:
14 *
15 * export ELM_MODULES="xx>slot1:yy>slot2"
16 *
17 * where a module named xx is plugged into slot1 & yy is plugged into slot2
18 *
19 * real examples:
20 *
21 * export ELM_MODULES="my_module>entry/api"
22 *
23 * this loads the module called "my_module" into the slot "entry/api" which
24 * is an api slot for entry modules to modify behavior and hook to
25 * creation/deletion of the entry as well as replace the longpress behavior.
26 */
27
28#ifdef HAVE_CONFIG_H
29# include "elementary_config.h"
30#endif
31
32static Eina_Hash *modules = NULL;
33static Eina_Hash *modules_as = NULL;
34
35void
36_elm_module_init(void)
37{
38 modules = eina_hash_string_small_new(NULL);
39 modules_as = eina_hash_string_small_new(NULL);
40}
41
42void
43_elm_module_shutdown(void)
44{
45 // FIXME: unload all modules
46 if (modules) eina_hash_free(modules);
47 modules = NULL;
48 if (modules_as) eina_hash_free(modules_as);
49 modules_as = NULL;
50}
51
52void
53_elm_module_parse(const char *s)
54{
55 const char *p, *pe;
56
57 p = s;
58 pe = p;
59 for (;;)
60 {
61 if ((*pe == ':') || (!*pe))
62 { // p -> pe == 'name:'
63 if (pe > p)
64 {
65 char *n = malloc(pe - p + 1);
66 if (n)
67 {
68 char *nn;
69
70 strncpy(n, p, pe - p);
71 n[pe - p] = 0;
72 nn = strchr(n, '>');
73 if (nn)
74 {
75 *nn = 0;
76 nn++;
77 _elm_module_add(n, nn);
78 }
79 free(n);
80 }
81 }
82 if (!*pe) break;
83 p = pe + 1;
84 pe = p;
85 }
86 else
87 pe++;
88 }
89}
90
91Elm_Module *
92_elm_module_find_as(const char *as)
93{
94 Elm_Module *m;
95
96 m = eina_hash_find(modules_as, as);
97 if (!m) return NULL;
98
99 if (!_elm_module_load(m))
100 {
101 _elm_module_del(m);
102 return NULL;
103 }
104 return m;
105}
106
107Eina_Bool
108_elm_module_load(Elm_Module *m)
109{
110 const char *home;
111 char buf[PATH_MAX];
112
113 if (m->module) return EINA_TRUE;
114
115 home = getenv("HOME");
116 if (home)
117 {
118 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s/%s/module" EFL_SHARED_EXTENSION, home, m->name, MODULE_ARCH);
119 m->module = eina_module_new(buf);
120 if (m->module && eina_module_load (m->module) == EINA_TRUE)
121 {
122 m->init_func = eina_module_symbol_get(m->module, "elm_modapi_init");
123 if (m->init_func)
124 {
125 m->shutdown_func = eina_module_symbol_get(m->module, "elm_modapi_shutdown");
126 m->so_path = eina_stringshare_add(buf);
127 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s/%s", home, m->name, MODULE_ARCH);
128 m->bin_dir = eina_stringshare_add(buf);
129 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/modules/%s", home, m->name);
130 m->data_dir = eina_stringshare_add(buf);
131 }
132 else
133 {
134 if (m->module)
135 {
136 eina_module_unload(m->module);
137 eina_module_free(m->module);
138 m->module = NULL;
139 }
140 return EINA_FALSE;
141 }
142 }
143 else if (m->module)
144 {
145 eina_module_free(m->module);
146 m->module = NULL;
147 }
148 }
149
150 if (!m->module)
151 {
152 snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s/module" EFL_SHARED_EXTENSION, _elm_lib_dir, m->name, MODULE_ARCH);
153 m->module = eina_module_new(buf);
154 if (m->module && eina_module_load (m->module) == EINA_TRUE)
155 {
156 m->init_func = eina_module_symbol_get(m->module, "elm_modapi_init");
157 if (m->init_func)
158 {
159 m->shutdown_func = eina_module_symbol_get(m->module, "elm_modapi_shutdown");
160 m->so_path = eina_stringshare_add(buf);
161 snprintf(buf, sizeof(buf), "%s/elementary/modules/%s/%s", _elm_lib_dir, m->name, MODULE_ARCH);
162 m->bin_dir = eina_stringshare_add(buf);
163 snprintf(buf, sizeof(buf), "%s/elementary/modules/%s", _elm_lib_dir, m->name);
164 m->data_dir = eina_stringshare_add(buf);
165 }
166 else
167 {
168 if (m->module)
169 {
170 eina_module_unload(m->module);
171 eina_module_free(m->module);
172 m->module = NULL;
173 }
174 return EINA_FALSE;
175 }
176 }
177 }
178 else if (m->module)
179 {
180 eina_module_free(m->module);
181 m->module = NULL;
182 }
183
184 if (!m->module) return EINA_FALSE;
185 return EINA_TRUE;
186}
187
188void
189_elm_module_unload(Elm_Module *m)
190{
191 eina_stringshare_del(m->so_path);
192 eina_stringshare_del(m->data_dir);
193 eina_stringshare_del(m->bin_dir);
194 if (m->api)
195 {
196 free(m->api);
197 m->api = NULL;
198 }
199 if (m->module)
200 {
201 if (m->shutdown_func) m->shutdown_func(m);
202 eina_module_unload(m->module);
203 eina_module_free(m->module);
204 m->module = NULL;
205 }
206 m->shutdown_func = NULL;
207 m->init_func = NULL;
208}
209
210Elm_Module *
211_elm_module_add(const char *name, const char *as)
212{
213 Elm_Module *m;
214
215 if (name[0] == '/') return NULL;
216
217 m = eina_hash_find(modules, name);
218 if (m)
219 {
220 m->references++;
221 return m;
222 }
223 m = calloc(1, sizeof(Elm_Module));
224 if (!m) return NULL;
225 m->version = 1;
226 m->name = eina_stringshare_add(name);
227 m->references = 1;
228 eina_hash_direct_add(modules, m->name, m);
229 m->as = eina_stringshare_add(as);
230 eina_hash_direct_add(modules_as, m->as, m);
231 return m;
232}
233
234void
235_elm_module_del(Elm_Module *m)
236{
237 m->references--;
238 if (m->references > 0) return;
239 _elm_module_unload(m);
240 eina_hash_del(modules, m->name, m);
241 eina_hash_del(modules_as, m->as, m);
242 eina_stringshare_del(m->name);
243 eina_stringshare_del(m->as);
244 free(m);
245}
246
247const void *
248_elm_module_symbol_get(Elm_Module *m, const char *name)
249{
250 return eina_module_symbol_get(m->module, name);
251}
diff --git a/libraries/elementary/src/lib/elm_need.h b/libraries/elementary/src/lib/elm_need.h
new file mode 100644
index 0000000..1e43269
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_need.h
@@ -0,0 +1,49 @@
1/**
2 * Request that your elementary application needs Efreet
3 *
4 * This initializes the Efreet library when called and if support exists
5 * it returns EINA_TRUE, otherwise returns EINA_FALSE. This must be called
6 * before any efreet calls.
7 *
8 * @return EINA_TRUE if support exists and initialization succeeded.
9 *
10 * @ingroup Efreet
11 */
12EAPI Eina_Bool elm_need_efreet(void);
13
14/**
15 * Request that your elementary application needs e_dbus
16 *
17 * This initializes the E_dbus library when called and if support exists
18 * it returns EINA_TRUE, otherwise returns EINA_FALSE. This must be called
19 * before any e_dbus calls.
20 *
21 * @return EINA_TRUE if support exists and initialization succeeded.
22 *
23 * @ingroup E_dbus
24 */
25EAPI Eina_Bool elm_need_e_dbus(void);
26
27/**
28 * Request that your elementary application needs ethumb
29 *
30 * This initializes the Ethumb library when called and if support exists
31 * it returns EINA_TRUE, otherwise returns EINA_FALSE.
32 * This must be called before any other function that deals with
33 * elm_thumb objects or ethumb_client instances.
34 *
35 * @ingroup Thumb
36 */
37EAPI Eina_Bool elm_need_ethumb(void);
38
39/**
40 * Request that your elementary application needs web support
41 *
42 * This initializes the Ewebkit library when called and if support exists
43 * it returns EINA_TRUE, otherwise returns EINA_FALSE.
44 * This must be called before any other function that deals with
45 * elm_web objects or ewk_view instances.
46 *
47 * @ingroup Web
48 */
49EAPI Eina_Bool elm_need_web(void);
diff --git a/libraries/elementary/src/lib/elm_notify.c b/libraries/elementary/src/lib/elm_notify.c
new file mode 100644
index 0000000..1b68390
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_notify.c
@@ -0,0 +1,626 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *notify, *content, *parent;
9
10 Elm_Notify_Orient orient;
11 Eina_Bool allow_events;
12 Evas_Object *block_events;
13
14 double timeout;
15 Ecore_Timer *timer;
16};
17
18static const char *widtype = NULL;
19static void _del_hook(Evas_Object *obj);
20static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
21static void _theme_hook(Evas_Object *obj);
22static void _sizing_eval(Evas_Object *obj);
23static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
24static void _sub_del(void *data, Evas_Object *obj, void *event_info);
25static void _signal_block_clicked(void *data, Evas_Object *obj, const char *emission, const char *source);
26static void _calc(Evas_Object *obj);
27static void _content_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
28static void _show(void *data, Evas *e, Evas_Object *obj, void *event_info);
29static void _hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
30static void _parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
31static void _parent_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
32
33static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
34static void _restack(void *data, Evas *e, Evas_Object *obj, void *event_info);
35
36static const char SIG_BLOCK_CLICKED[] = "block,clicked";
37static const char SIG_TIMEOUT[] = "timeout";
38static const Evas_Smart_Cb_Description _signals[] = {
39 {SIG_BLOCK_CLICKED, ""},
40 {SIG_TIMEOUT, ""},
41 {NULL, NULL}
42};
43
44static void
45_del_pre_hook(Evas_Object *obj)
46{
47 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
48 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE, _resize, obj);
49 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_SHOW, _show, obj);
50 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_HIDE, _hide, obj);
51 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
52}
53
54static void
55_del_hook(Evas_Object *obj)
56{
57 Widget_Data *wd = elm_widget_data_get(obj);
58 if (!wd) return;
59 elm_notify_parent_set(obj, NULL);
60 elm_notify_allow_events_set(obj, EINA_TRUE);
61 if (wd->timer)
62 {
63 ecore_timer_del(wd->timer);
64 wd->timer = NULL;
65 }
66 free(wd);
67}
68
69/**
70 * Return Notification orientation with RTL
71 *
72 * This function switches-sides of notification area when in RTL mode.
73 *
74 * @param obj notification object.
75 *
76 * @param orient Original notification orientation.
77 *
78 * @return notification orientation with respect to the object RTL mode.
79 *
80 * @internal
81 **/
82static Elm_Notify_Orient
83_notify_orientation_with_rtl(Evas_Object *obj, Elm_Notify_Orient orient)
84{
85 if (elm_widget_mirrored_get(obj))
86 {
87 switch (orient)
88 {
89 case ELM_NOTIFY_ORIENT_LEFT:
90 orient = ELM_NOTIFY_ORIENT_RIGHT;
91 break;
92 case ELM_NOTIFY_ORIENT_RIGHT:
93 orient = ELM_NOTIFY_ORIENT_LEFT;
94 break;
95 case ELM_NOTIFY_ORIENT_TOP_LEFT:
96 orient = ELM_NOTIFY_ORIENT_TOP_RIGHT;
97 break;
98 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
99 orient = ELM_NOTIFY_ORIENT_TOP_LEFT;
100 break;
101 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
102 orient = ELM_NOTIFY_ORIENT_BOTTOM_RIGHT;
103 break;
104 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
105 orient = ELM_NOTIFY_ORIENT_BOTTOM_LEFT;
106 break;
107 default:
108 break;
109 }
110 }
111
112 return orient;
113}
114
115static void
116_notify_theme_apply(Evas_Object *obj)
117{
118 Widget_Data *wd = elm_widget_data_get(obj);
119 const char *style = elm_widget_style_get(obj);
120
121 switch (wd->orient)
122 {
123 case ELM_NOTIFY_ORIENT_TOP:
124 _elm_theme_object_set(obj, wd->notify, "notify", "top", style);
125 break;
126 case ELM_NOTIFY_ORIENT_CENTER:
127 _elm_theme_object_set(obj, wd->notify, "notify", "center", style);
128 break;
129 case ELM_NOTIFY_ORIENT_BOTTOM:
130 _elm_theme_object_set(obj, wd->notify, "notify", "bottom", style);
131 break;
132 case ELM_NOTIFY_ORIENT_LEFT:
133 _elm_theme_object_set(obj, wd->notify, "notify", "left", style);
134 break;
135 case ELM_NOTIFY_ORIENT_RIGHT:
136 _elm_theme_object_set(obj, wd->notify, "notify", "right", style);
137 break;
138 case ELM_NOTIFY_ORIENT_TOP_LEFT:
139 _elm_theme_object_set(obj, wd->notify, "notify", "top_left", style);
140 break;
141 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
142 _elm_theme_object_set(obj, wd->notify, "notify", "top_right", style);
143 break;
144 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
145 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_left", style);
146 break;
147 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
148 _elm_theme_object_set(obj, wd->notify, "notify", "bottom_right", style);
149 break;
150 case ELM_NOTIFY_ORIENT_LAST:
151 break;
152 }
153}
154
155/**
156 * Moves notification to orientation.
157 *
158 * This fucntion moves notification to orientation
159 * according to object RTL orientation.
160 *
161 * @param obj notification object.
162 *
163 * @param orient notification orientation.
164 *
165 * @internal
166 **/
167static void
168_notify_move_to_orientation(Evas_Object *obj)
169{
170 Widget_Data *wd = elm_widget_data_get(obj);
171 int offx;
172 int offy;
173 Evas_Coord minw = -1, minh = -1;
174 Evas_Coord x, y, w, h;
175
176 if (!wd) return;
177 evas_object_geometry_get(obj, &x, &y, &w, &h);
178 edje_object_size_min_get(wd->notify, &minw, &minh);
179 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
180 offx = (w - minw) / 2;
181 offy = (h - minh) / 2;
182
183 switch (_notify_orientation_with_rtl(obj, wd->orient))
184 {
185 case ELM_NOTIFY_ORIENT_TOP:
186 evas_object_move(wd->notify, x + offx, y);
187 break;
188 case ELM_NOTIFY_ORIENT_CENTER:
189 evas_object_move(wd->notify, x + offx, y + offy);
190 break;
191 case ELM_NOTIFY_ORIENT_BOTTOM:
192 evas_object_move(wd->notify, x + offx, y + h - minh);
193 break;
194 case ELM_NOTIFY_ORIENT_LEFT:
195 evas_object_move(wd->notify, x, y + offy);
196 break;
197 case ELM_NOTIFY_ORIENT_RIGHT:
198 evas_object_move(wd->notify, x + w - minw, y + offy);
199 break;
200 case ELM_NOTIFY_ORIENT_TOP_LEFT:
201 evas_object_move(wd->notify, x, y);
202 break;
203 case ELM_NOTIFY_ORIENT_TOP_RIGHT:
204 evas_object_move(wd->notify, x + w - minw, y);
205 break;
206 case ELM_NOTIFY_ORIENT_BOTTOM_LEFT:
207 evas_object_move(wd->notify, x, y + h - minh);
208 break;
209 case ELM_NOTIFY_ORIENT_BOTTOM_RIGHT:
210 evas_object_move(wd->notify, x + w - minw, y + h - minh);
211 break;
212 case ELM_NOTIFY_ORIENT_LAST:
213 break;
214 }
215}
216
217static void
218_block_events_theme_apply(Evas_Object *obj)
219{
220 Widget_Data *wd = elm_widget_data_get(obj);
221 const char *style = elm_widget_style_get(obj);
222 _elm_theme_object_set(obj, wd->block_events, "notify", "block_events", style);
223}
224
225static void
226_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
227{
228 Widget_Data *wd = elm_widget_data_get(obj);
229 if (!wd) return;
230 edje_object_mirrored_set(wd->notify, rtl);
231 _notify_move_to_orientation(obj);
232}
233
234static void
235_theme_hook(Evas_Object *obj)
236{
237 Widget_Data *wd = elm_widget_data_get(obj);
238 if (!wd) return;
239 _elm_widget_mirrored_reload(obj);
240 _mirrored_set(obj, elm_widget_mirrored_get(obj));
241 _notify_theme_apply(obj);
242 if (wd->block_events) _block_events_theme_apply(obj);
243 edje_object_scale_set(wd->notify, elm_widget_scale_get(obj) *
244 _elm_config->scale);
245 _sizing_eval(obj);
246}
247
248static void
249_sizing_eval(Evas_Object *obj)
250{
251 Widget_Data *wd = elm_widget_data_get(obj);
252 Evas_Coord x,y,w,h;
253 if (!wd) return;
254 if (!wd->parent) return;
255 evas_object_geometry_get(wd->parent, &x, &y, &w, &h);
256 evas_object_move(obj, x, y);
257 evas_object_resize(obj, w, h);
258}
259
260static void
261_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
262{
263 _calc(data);
264}
265
266static void
267_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
268{
269 Widget_Data *wd = elm_widget_data_get(obj);
270 Evas_Object *sub = event_info;
271 if (!wd) return;
272
273 if (sub == wd->content)
274 {
275 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
276 _changed_size_hints, obj);
277 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_RESIZE,
278 _content_resize, obj);
279 wd->content = NULL;
280 }
281}
282
283static void
284_signal_block_clicked(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
285{
286 Widget_Data *wd = elm_widget_data_get(data);
287 if (!wd) return;
288 evas_object_smart_callback_call(data, SIG_BLOCK_CLICKED, NULL);
289}
290
291static void
292_restack(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
293{
294 Widget_Data *wd = elm_widget_data_get(obj);
295 if (!wd) return;
296 evas_object_layer_set(wd->notify,
297 evas_object_layer_get(obj));
298}
299
300static void
301_resize(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
302{
303 _calc(obj);
304}
305
306static void
307_content_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
308{
309 _calc(data);
310}
311
312static void
313_calc(Evas_Object *obj)
314{
315 Widget_Data *wd = elm_widget_data_get(obj);
316 Evas_Coord minw = -1, minh = -1;
317 Evas_Coord x, y, w, h;
318
319 if (!wd) return;
320 _sizing_eval(obj);
321
322 evas_object_geometry_get(obj, &x, &y, &w, &h);
323 edje_object_size_min_get(wd->notify, &minw, &minh);
324 edje_object_size_min_restricted_calc(wd->notify, &minw, &minh, minw, minh);
325
326 if (wd->content)
327 {
328 _notify_move_to_orientation(obj);
329 evas_object_resize(wd->notify, minw, minh);
330 }
331}
332
333static Eina_Bool
334_timer_cb(void *data)
335{
336 Evas_Object *obj = data;
337 Widget_Data *wd = elm_widget_data_get(obj);
338 if (!wd) return ECORE_CALLBACK_CANCEL;
339 wd->timer = NULL;
340 evas_object_hide(obj);
341 evas_object_smart_callback_call(obj, SIG_TIMEOUT, NULL);
342 return ECORE_CALLBACK_CANCEL;
343}
344
345static void
346_timer_init(Evas_Object *obj, Widget_Data *wd)
347{
348 if (wd->timer)
349 {
350 ecore_timer_del(wd->timer);
351 wd->timer = NULL;
352 }
353 if ((evas_object_visible_get(obj)) && (wd->timeout > 0.0))
354 wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
355}
356
357static void
358_show(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
359{
360 Widget_Data *wd = elm_widget_data_get(obj);
361 if (!wd) return;
362 evas_object_show(wd->notify);
363 if (!wd->allow_events) evas_object_show(wd->block_events);
364 _timer_init(obj, wd);
365 elm_object_focus_set(obj, EINA_TRUE);
366}
367
368static void
369_hide(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
370{
371 Widget_Data *wd = elm_widget_data_get(obj);
372 if (!wd) return;
373 evas_object_hide(wd->notify);
374 if (!wd->allow_events) evas_object_hide(wd->block_events);
375 if (wd->timer)
376 {
377 ecore_timer_del(wd->timer);
378 wd->timer = NULL;
379 }
380}
381
382static void
383_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
384{
385 Widget_Data *wd = elm_widget_data_get(data);
386 if (!wd) return;
387 wd->parent = NULL;
388 evas_object_hide(data);
389}
390
391static void
392_parent_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
393{
394 Widget_Data *wd = elm_widget_data_get(data);
395 if (!wd) return;
396 evas_object_hide(data);
397}
398
399static Eina_Bool
400_elm_notify_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
401{
402 Widget_Data *wd = elm_widget_data_get(obj);
403 Evas_Object *cur;
404
405 if ((!wd) || (!wd->content))
406 return EINA_FALSE;
407
408 cur = wd->content;
409
410 /* Try Focus cycle in subitem */
411 return elm_widget_focus_next_get(cur, dir, next);
412}
413
414static void
415_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
416{
417 ELM_CHECK_WIDTYPE(obj, widtype);
418 Widget_Data *wd;
419 if (part && strcmp(part ,"default")) return;
420 wd = elm_widget_data_get(obj);
421 if (!wd) return;
422 if (wd->content == content) return;
423 if (wd->content) evas_object_del(wd->content);
424 wd->content = content;
425
426 if (content)
427 {
428 elm_widget_sub_object_add(obj, content);
429 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
430 _changed_size_hints, obj);
431 evas_object_event_callback_add(content, EVAS_CALLBACK_RESIZE,
432 _content_resize, obj);
433 edje_object_part_swallow(wd->notify, "elm.swallow.content", content);
434 }
435 _sizing_eval(obj);
436 _calc(obj);
437}
438
439static Evas_Object *
440_content_get_hook(const Evas_Object *obj, const char *part)
441{
442 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
443 Widget_Data *wd;
444 if (part && strcmp(part ,"default")) return NULL;
445 wd = elm_widget_data_get(obj);
446 if (!wd) return NULL;
447 return wd->content;
448}
449
450static Evas_Object *
451_content_unset_hook(Evas_Object *obj, const char *part)
452{
453 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
454 Widget_Data *wd;
455 Evas_Object *content;
456 if (part && strcmp(part ,"default")) return NULL;
457 wd = elm_widget_data_get(obj);
458 if (!wd) return NULL;
459 if (!wd->content) return NULL;
460 content = wd->content;
461 elm_widget_sub_object_del(obj, wd->content);
462 edje_object_part_unswallow(wd->notify, content);
463 return content;
464}
465
466EAPI Evas_Object *
467elm_notify_add(Evas_Object *parent)
468{
469 Evas_Object *obj;
470 Evas *e;
471 Widget_Data *wd;
472
473 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
474
475 ELM_SET_WIDTYPE(widtype, "notify");
476 elm_widget_type_set(obj, "notify");
477 elm_widget_sub_object_add(parent, obj);
478 elm_widget_data_set(obj, wd);
479 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
480 elm_widget_del_hook_set(obj, _del_hook);
481 elm_widget_theme_hook_set(obj, _theme_hook);
482 elm_widget_can_focus_set(obj, EINA_FALSE);
483 elm_widget_focus_next_hook_set(obj, _elm_notify_focus_next_hook);
484 elm_widget_content_set_hook_set(obj, _content_set_hook);
485 elm_widget_content_get_hook_set(obj, _content_get_hook);
486 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
487
488 wd->allow_events = EINA_TRUE;
489
490 wd->notify = edje_object_add(e);
491 wd->orient = -1;
492 elm_notify_orient_set(obj, ELM_NOTIFY_ORIENT_TOP);
493
494 elm_notify_parent_set(obj, parent);
495
496 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
497 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
498 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE, _resize, obj);
499 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW, _show, obj);
500 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE, _hide, obj);
501 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESTACK, _restack, obj);
502 _mirrored_set(obj, elm_widget_mirrored_get(obj));
503 _sizing_eval(obj);
504
505 evas_object_smart_callbacks_descriptions_set(obj, _signals);
506 return obj;
507}
508
509EAPI void
510elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent)
511{
512 ELM_CHECK_WIDTYPE(obj, widtype);
513 Widget_Data *wd = elm_widget_data_get(obj);
514 if (!wd) return;
515 if (wd->parent)
516 {
517 evas_object_event_callback_del_full(wd->parent,
518 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
519 _changed_size_hints, obj);
520 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_RESIZE,
521 _changed_size_hints, obj);
522 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_MOVE,
523 _changed_size_hints, obj);
524 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_DEL,
525 _parent_del, obj);
526 evas_object_event_callback_del_full(wd->parent, EVAS_CALLBACK_HIDE,
527 _parent_hide, obj);
528 wd->parent = NULL;
529 }
530
531 if (parent)
532 {
533 wd->parent = parent;
534 evas_object_event_callback_add(parent,
535 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
536 _changed_size_hints, obj);
537 evas_object_event_callback_add(parent, EVAS_CALLBACK_RESIZE,
538 _changed_size_hints, obj);
539 evas_object_event_callback_add(parent, EVAS_CALLBACK_MOVE,
540 _changed_size_hints, obj);
541 evas_object_event_callback_add(parent, EVAS_CALLBACK_DEL,
542 _parent_del, obj);
543 evas_object_event_callback_add(parent, EVAS_CALLBACK_HIDE,
544 _parent_hide, obj);
545 _sizing_eval(obj);
546 }
547 _calc(obj);
548}
549
550EAPI Evas_Object *
551elm_notify_parent_get(const Evas_Object *obj)
552{
553 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
554 Widget_Data *wd = elm_widget_data_get(obj);
555 if (!wd) return NULL;
556 return wd->parent;
557}
558
559EAPI void
560elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient)
561{
562 ELM_CHECK_WIDTYPE(obj, widtype);
563 Widget_Data *wd = elm_widget_data_get(obj);
564 if (!wd) return;
565 if (wd->orient == orient) return;
566 wd->orient = orient;
567 _notify_theme_apply(obj);
568 _resize(obj, NULL, obj, NULL);
569}
570
571EAPI Elm_Notify_Orient
572elm_notify_orient_get(const Evas_Object *obj)
573{
574 ELM_CHECK_WIDTYPE(obj, widtype) -1;
575 Widget_Data *wd = elm_widget_data_get(obj);
576 if (!wd) return -1;
577 return wd->orient;
578}
579
580EAPI void
581elm_notify_timeout_set(Evas_Object *obj, double timeout)
582{
583 ELM_CHECK_WIDTYPE(obj, widtype);
584 Widget_Data *wd = elm_widget_data_get(obj);
585 if (!wd) return;
586 wd->timeout = timeout;
587 _timer_init(obj, wd);
588}
589
590EAPI double
591elm_notify_timeout_get(const Evas_Object *obj)
592{
593 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
594 Widget_Data *wd = elm_widget_data_get(obj);
595 if (!wd) return 0.0;
596 return wd->timeout;
597}
598
599EAPI void
600elm_notify_allow_events_set(Evas_Object *obj, Eina_Bool allow)
601{
602 ELM_CHECK_WIDTYPE(obj, widtype);
603 Widget_Data *wd = elm_widget_data_get(obj);
604 if (!wd) return;
605 if (allow == wd->allow_events) return;
606 wd->allow_events = allow;
607 if (!allow)
608 {
609 wd->block_events = edje_object_add(evas_object_evas_get(obj));
610 _block_events_theme_apply(obj);
611 elm_widget_resize_object_set(obj, wd->block_events);
612 edje_object_signal_callback_add(wd->block_events, "elm,action,click",
613 "elm", _signal_block_clicked, obj);
614 }
615 else
616 evas_object_del(wd->block_events);
617}
618
619EAPI Eina_Bool
620elm_notify_allow_events_get(const Evas_Object *obj)
621{
622 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
623 Widget_Data *wd = elm_widget_data_get(obj);
624 if (!wd) return EINA_FALSE;
625 return wd->allow_events;
626}
diff --git a/libraries/elementary/src/lib/elm_notify.h b/libraries/elementary/src/lib/elm_notify.h
new file mode 100644
index 0000000..0fab742
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_notify.h
@@ -0,0 +1,173 @@
1/**
2 * @defgroup Notify Notify
3 * @ingroup Elementary
4 *
5 * @image html img/widget/notify/preview-00.png
6 * @image latex img/widget/notify/preview-00.eps
7 *
8 * Display a container in a particular region of the parent(top, bottom,
9 * etc). A timeout can be set to automatically hide the notify. This is so
10 * that, after an evas_object_show() on a notify object, if a timeout was set
11 * on it, it will @b automatically get hidden after that time.
12 *
13 * Signals that you can add callbacks for are:
14 * @li "timeout" - when timeout happens on notify and it's hidden
15 * @li "block,clicked" - when a click outside of the notify happens
16 *
17 * Default content parts of the notify widget that you can use for are:
18 * @li "default" - A content of the notify
19 *
20 * Supported elm_object common APIs.
21 * @li @ref elm_object_part_content_set
22 * @li @ref elm_object_part_content_get
23 * @li @ref elm_object_part_content_unset
24 *
25 * @ref tutorial_notify show usage of the API.
26 *
27 * @{
28 */
29
30/**
31 * @brief Possible orient values for notify.
32 *
33 * This values should be used in conjunction to elm_notify_orient_set() to
34 * set the position in which the notify should appear(relative to its parent)
35 * and in conjunction with elm_notify_orient_get() to know where the notify
36 * is appearing.
37 */
38typedef enum
39{
40 ELM_NOTIFY_ORIENT_TOP, /**< Notify should appear in the top of parent, default */
41 ELM_NOTIFY_ORIENT_CENTER, /**< Notify should appear in the center of parent */
42 ELM_NOTIFY_ORIENT_BOTTOM, /**< Notify should appear in the bottom of parent */
43 ELM_NOTIFY_ORIENT_LEFT, /**< Notify should appear in the left of parent */
44 ELM_NOTIFY_ORIENT_RIGHT, /**< Notify should appear in the right of parent */
45 ELM_NOTIFY_ORIENT_TOP_LEFT, /**< Notify should appear in the top left of parent */
46 ELM_NOTIFY_ORIENT_TOP_RIGHT, /**< Notify should appear in the top right of parent */
47 ELM_NOTIFY_ORIENT_BOTTOM_LEFT, /**< Notify should appear in the bottom left of parent */
48 ELM_NOTIFY_ORIENT_BOTTOM_RIGHT, /**< Notify should appear in the bottom right of parent */
49 ELM_NOTIFY_ORIENT_LAST /**< Sentinel value, @b don't use */
50} Elm_Notify_Orient;
51
52/**
53 * @brief Add a new notify to the parent
54 *
55 * @param parent The parent object
56 * @return The new object or NULL if it cannot be created
57 *
58 * @ingroup Notify
59 */
60EAPI Evas_Object *elm_notify_add(Evas_Object *parent);
61
62/**
63 * @brief Set the notify parent
64 *
65 * @param obj The notify object
66 * @param parent The new parent
67 *
68 * Once the parent object is set, a previously set one will be disconnected
69 * and replaced.
70 *
71 * @ingroup Notify
72 */
73EAPI void elm_notify_parent_set(Evas_Object *obj, Evas_Object *parent);
74
75/**
76 * @brief Get the notify parent
77 *
78 * @param obj The notify object
79 * @return The parent
80 *
81 * @see elm_notify_parent_set()
82 *
83 * @ingroup Notify
84 */
85EAPI Evas_Object *elm_notify_parent_get(const Evas_Object *obj);
86
87/**
88 * @brief Set the orientation
89 *
90 * @param obj The notify object
91 * @param orient The new orientation
92 *
93 * Sets the position in which the notify will appear in its parent.
94 *
95 * @see @ref Elm_Notify_Orient for possible values.
96 *
97 * @ingroup Notify
98 */
99EAPI void elm_notify_orient_set(Evas_Object *obj, Elm_Notify_Orient orient);
100
101/**
102 * @brief Return the orientation
103 * @param obj The notify object
104 * @return The orientation of the notification
105 *
106 * @see elm_notify_orient_set()
107 * @see Elm_Notify_Orient
108 *
109 * @ingroup Notify
110 */
111EAPI Elm_Notify_Orient elm_notify_orient_get(const Evas_Object *obj);
112
113/**
114 * @brief Set the time interval after which the notify window is going to be
115 * hidden.
116 *
117 * @param obj The notify object
118 * @param timeout The timeout in seconds
119 *
120 * This function sets a timeout and starts the timer controlling when the
121 * notify is hidden. Since calling evas_object_show() on a notify restarts
122 * the timer controlling when the notify is hidden, setting this before the
123 * notify is shown will in effect mean starting the timer when the notify is
124 * shown.
125 *
126 * @note Set a value <= 0.0 to disable a running timer.
127 *
128 * @note If the value > 0.0 and the notify is previously visible, the
129 * timer will be started with this value, canceling any running timer.
130 *
131 * @ingroup Notify
132 */
133EAPI void elm_notify_timeout_set(Evas_Object *obj, double timeout);
134
135/**
136 * @brief Return the timeout value (in seconds)
137 * @param obj the notify object
138 *
139 * @see elm_notify_timeout_set()
140 *
141 * @ingroup Notify
142 */
143EAPI double elm_notify_timeout_get(const Evas_Object *obj);
144
145/**
146 * @brief Sets whether events should be passed to by a click outside
147 * its area.
148 *
149 * @param obj The notify object
150 * @param allow EINA_TRUE If events are allowed, otherwise not
151 *
152 * When true if the user clicks outside the window the events will be caught
153 * by the others widgets, else the events are blocked.
154 *
155 * @note The default value is EINA_TRUE.
156 *
157 * @ingroup Notify
158 */
159EAPI void elm_notify_allow_events_set(Evas_Object *obj, Eina_Bool allow);
160
161/**
162 * @brief Return true if events are allowed below the notify object
163 * @param obj the notify object
164 *
165 * @see elm_notify_allow_events_set()
166 *
167 * @ingroup Notify
168 */
169EAPI Eina_Bool elm_notify_allow_events_get(const Evas_Object *obj);
170
171/**
172 * @}
173 */
diff --git a/libraries/elementary/src/lib/elm_object.h b/libraries/elementary/src/lib/elm_object.h
new file mode 100644
index 0000000..68a863d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_object.h
@@ -0,0 +1,376 @@
1/**
2 * Set a label of an object
3 *
4 * @param obj The Elementary object
5 * @param part The text part name to set (NULL for the default label)
6 * @param label The new text of the label
7 *
8 * @note Elementary objects may have many labels (e.g. Action Slider)
9 *
10 * @ingroup General
11 */
12EAPI void elm_object_part_text_set(Evas_Object *obj, const char *part, const char *label);
13
14#define elm_object_text_set(obj, label) elm_object_part_text_set((obj), NULL, (label))
15
16/**
17 * Get a label of an object
18 *
19 * @param obj The Elementary object
20 * @param part The text part name to get (NULL for the default label)
21 * @return text of the label or NULL for any error
22 *
23 * @note Elementary objects may have many labels (e.g. Action Slider)
24 *
25 * @ingroup General
26 */
27EAPI const char *elm_object_part_text_get(const Evas_Object *obj, const char *part);
28
29#define elm_object_text_get(obj) elm_object_part_text_get((obj), NULL)
30
31/**
32 * Set a content of an object
33 *
34 * @param obj The Elementary object
35 * @param part The content part name to set (NULL for the default content)
36 * @param content The new content of the object
37 *
38 * This sets a new object to a widget as a content object. If any object was
39 * already set as a content object in the same part, previous object will be
40 * deleted automatically.
41 *
42 * @note Elementary objects may have many contents
43 *
44 * @ingroup General
45 */
46EAPI void elm_object_part_content_set(Evas_Object *obj, const char *part, Evas_Object *content);
47
48#define elm_object_content_set(obj, content) elm_object_part_content_set((obj), NULL, (content))
49
50/**
51 * Get a content of an object
52 *
53 * @param obj The Elementary object
54 * @param part The content part name to get (NULL for the default content)
55 * @return content of the object or NULL for any error
56 *
57 * @note Elementary objects may have many contents
58 *
59 * @ingroup General
60 */
61EAPI Evas_Object *elm_object_part_content_get(const Evas_Object *obj, const char *part);
62
63#define elm_object_content_get(obj) elm_object_part_content_get((obj), NULL)
64
65/**
66 * Unset a content of an object
67 *
68 * @param obj The Elementary object
69 * @param part The content part name to unset (NULL for the default content)
70 *
71 * @note Elementary objects may have many contents
72 *
73 * @ingroup General
74 */
75EAPI Evas_Object *elm_object_part_content_unset(Evas_Object *obj, const char *part);
76
77#define elm_object_content_unset(obj) elm_object_part_content_unset((obj), NULL)
78
79/**
80 * Set the text to read out when in accessibility mode
81 *
82 * @param obj The object which is to be described
83 * @param txt The text that describes the widget to people with poor or no vision
84 *
85 * @ingroup General
86 */
87EAPI void elm_object_access_info_set(Evas_Object *obj, const char *txt);
88
89/**
90 * Get a named object from the children
91 *
92 * @param obj The parent object whose children to look at
93 * @param name The name of the child to find
94 * @param recurse Set to the maximum number of levels to recurse (0 == none, 1 is only look at 1 level of children etc.)
95 * @return The found object of that name, or NULL if none is found
96 *
97 * This function searches the children (or recursively children of
98 * children and so on) of the given @p obj object looking for a child with
99 * the name of @p name. If the child is found the object is returned, or
100 * NULL is returned. You can set the name of an object with
101 * evas_object_name_set(). If the name is not unique within the child
102 * objects (or the tree is @p recurse is greater than 0) then it is
103 * undefined as to which child of that name is returned, so ensure the name
104 * is unique amongst children. If recurse is set to -1 it will recurse
105 * without limit.
106 *
107 * @ingroup General
108 */
109EAPI Evas_Object *elm_object_name_find(const Evas_Object *obj, const char *name, int recurse);
110
111/**
112 * @defgroup Styles Styles
113 *
114 * Widgets can have different styles of look. These generic API's
115 * set styles of widgets, if they support them (and if the theme(s)
116 * do).
117 *
118 * @ref general_functions_example_page "This" example contemplates
119 * some of these functions.
120 */
121
122/**
123 * Set the style to used by a given widget
124 *
125 * @param obj The Elementary widget to style
126 * @param style The name of the style to use on it
127 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
128 *
129 * This sets the style (by name) that will define the appearance of a
130 * widget. Styles vary from widget to widget and may also be defined
131 * by other themes by means of extensions and overlays.
132 *
133 * @see elm_theme_extension_add()
134 * @see elm_theme_extension_del()
135 * @see elm_theme_overlay_add()
136 * @see elm_theme_overlay_del()
137 *
138 * @ingroup Styles
139 */
140EAPI Eina_Bool elm_object_style_set(Evas_Object *obj, const char *style);
141
142/**
143 * Get the style used by the widget
144 *
145 * This gets the style being used for that widget. Note that the string
146 * pointer is only valid as long as the object is valid and the style doesn't
147 * change.
148 *
149 * @param obj The Elementary widget to query for its style
150 * @return The style name used
151 *
152 * @see elm_object_style_set()
153 *
154 * @ingroup Styles
155 */
156EAPI const char *elm_object_style_get(const Evas_Object *obj);
157
158/**
159 * Set the disabled state of an Elementary object.
160 *
161 * @param obj The Elementary object to operate on
162 * @param disabled The state to put in in: @c EINA_TRUE for
163 * disabled, @c EINA_FALSE for enabled
164 *
165 * Elementary objects can be @b disabled, in which state they won't
166 * receive input and, in general, will be themed differently from
167 * their normal state, usually greyed out. Useful for contexts
168 * where you don't want your users to interact with some of the
169 * parts of you interface.
170 *
171 * This sets the state for the widget, either disabling it or
172 * enabling it back.
173 *
174 * @ingroup Styles
175 */
176EAPI void elm_object_disabled_set(Evas_Object *obj, Eina_Bool disabled);
177
178/**
179 * Get the disabled state of an Elementary object.
180 *
181 * @param obj The Elementary object to operate on
182 * @return @c EINA_TRUE, if the widget is disabled, @c EINA_FALSE
183 * if it's enabled (or on errors)
184 *
185 * This gets the state of the widget, which might be enabled or disabled.
186 *
187 * @ingroup Styles
188 */
189EAPI Eina_Bool elm_object_disabled_get(const Evas_Object *obj);
190
191/**
192 * @defgroup WidgetNavigation Widget Tree Navigation
193 *
194 * These functions provide checks for if a Evas_Object is an Elementary widget,
195 * the possibility of getting a widget's parent, top level parent and getting a
196 * string representation of a widget's type.
197 */
198
199/**
200 * Check if the given Evas Object is an Elementary widget.
201 *
202 * @param obj the object to query.
203 * @return @c EINA_TRUE if it is an elementary widget variant,
204 * @c EINA_FALSE otherwise
205 * @ingroup WidgetNavigation
206 */
207EAPI Eina_Bool elm_object_widget_check(const Evas_Object *obj);
208
209/**
210 * Get the first parent of the given object that is an Elementary
211 * widget.
212 *
213 * @param obj the Elementary object to query parent from.
214 * @return the parent object that is an Elementary widget, or @c
215 * NULL, if it was not found.
216 *
217 * Use this to query for an object's parent widget.
218 *
219 * @note Most of Elementary users wouldn't be mixing non-Elementary
220 * smart objects in the objects tree of an application, as this is
221 * an advanced usage of Elementary with Evas. So, except for the
222 * application's window, which is the root of that tree, all other
223 * objects would have valid Elementary widget parents.
224 *
225 * @ingroup WidgetNavigation
226 */
227EAPI Evas_Object *elm_object_parent_widget_get(const Evas_Object *obj);
228
229/**
230 * Get the top level parent of an Elementary widget.
231 *
232 * @param obj The object to query.
233 * @return The top level Elementary widget, or @c NULL if parent cannot be
234 * found.
235 * @ingroup WidgetNavigation
236 */
237EAPI Evas_Object *elm_object_top_widget_get(const Evas_Object *obj);
238
239/**
240 * Get the string that represents this Elementary widget.
241 *
242 * @note Elementary is weird and exposes itself as a single
243 * Evas_Object_Smart_Class of type "elm_widget", so
244 * evas_object_type_get() always return that, making debug and
245 * language bindings hard. This function tries to mitigate this
246 * problem, but the solution is to change Elementary to use
247 * proper inheritance.
248 *
249 * @param obj the object to query.
250 * @return Elementary widget name, or @c NULL if not a valid widget.
251 * @ingroup WidgetNavigation
252 */
253EAPI const char *elm_object_widget_type_get(const Evas_Object *obj);
254
255/**
256 * Send a signal to the widget edje object.
257 *
258 * This function sends a signal to the edje object of the obj. An
259 * edje program can respond to a signal by specifying matching
260 * 'signal' and 'source' fields.
261 *
262 * @param obj The object
263 * @param emission The signal's name.
264 * @param source The signal's source.
265 * @ingroup General
266 */
267EAPI void elm_object_signal_emit(Evas_Object *obj, const char *emission, const char *source);
268
269/**
270 * Add a callback for a signal emitted by widget edje object.
271 *
272 * This function connects a callback function to a signal emitted by the
273 * edje object of the obj.
274 * Globs can occur in either the emission or source name.
275 *
276 * @param obj The object
277 * @param emission The signal's name.
278 * @param source The signal's source.
279 * @param func The callback function to be executed when the signal is
280 * emitted.
281 * @param data A pointer to data to pass in to the callback function.
282 * @ingroup General
283 */
284EAPI void elm_object_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data);
285
286/**
287 * Remove a signal-triggered callback from a widget edje object.
288 *
289 * @param obj The object handle
290 * @param emission The signal's name.
291 * @param source The signal's source.
292 * @param func The callback function to be executed when the signal is
293 * emitted.
294 * @return The data pointer of the signal callback or @c NULL, on
295 * errors.
296 *
297 * This function removes the @b last callback, previously attached to
298 * a signal emitted by an undelying Edje object of @a obj, whose
299 * parameters @a emission, @a source and @c func match exactly with
300 * those passed to a previous call to
301 * elm_object_signal_callback_add(). The data pointer that was passed
302 * to this call will be returned.
303 *
304 * @ingroup General
305 */
306EAPI void *elm_object_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func);
307
308/**
309 * Add a callback for input events (key up, key down, mouse wheel)
310 * on a given Elementary widget
311 *
312 * @param obj The widget to add an event callback on
313 * @param func The callback function to be executed when the event
314 * happens
315 * @param data Data to pass in to @p func
316 *
317 * Every widget in an Elementary interface set to receive focus,
318 * with elm_object_focus_allow_set(), will propagate @b all of its
319 * key up, key down and mouse wheel input events up to its parent
320 * object, and so on. All of the focusable ones in this chain which
321 * had an event callback set, with this call, will be able to treat
322 * those events. There are two ways of making the propagation of
323 * these event upwards in the tree of widgets to @b cease:
324 * - Just return @c EINA_TRUE on @p func. @c EINA_FALSE will mean
325 * the event was @b not processed, so the propagation will go on.
326 * - The @c event_info pointer passed to @p func will contain the
327 * event's structure and, if you OR its @c event_flags inner
328 * value to @c EVAS_EVENT_FLAG_ON_HOLD, you're telling Elementary
329 * one has already handled it, thus killing the event's
330 * propagation, too.
331 *
332 * @note Your event callback will be issued on those events taking
333 * place only if no other child widget of @p obj has consumed the
334 * event already.
335 *
336 * @note Not to be confused with @c
337 * evas_object_event_callback_add(), which will add event callbacks
338 * per type on general Evas objects (no event propagation
339 * infrastructure taken in account).
340 *
341 * @note Not to be confused with @c
342 * elm_object_signal_callback_add(), which will add callbacks to @b
343 * signals coming from a widget's theme, not input events.
344 *
345 * @note Not to be confused with @c
346 * edje_object_signal_callback_add(), which does the same as
347 * elm_object_signal_callback_add(), but directly on an Edje
348 * object.
349 *
350 * @note Not to be confused with @c
351 * evas_object_smart_callback_add(), which adds callbacks to smart
352 * objects' <b>smart events</b>, and not input events.
353 *
354 * @see elm_object_event_callback_del()
355 *
356 * @ingroup General
357 */
358EAPI void elm_object_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data);
359
360/**
361 * Remove an event callback from a widget.
362 *
363 * This function removes a callback, previously attached to event emission
364 * by the @p obj.
365 * The parameters func and data must match exactly those passed to
366 * a previous call to elm_object_event_callback_add(). The data pointer that
367 * was passed to this call will be returned.
368 *
369 * @param obj The object
370 * @param func The callback function to be executed when the event is
371 * emitted.
372 * @param data Data to pass in to the callback function.
373 * @return The data pointer
374 * @ingroup General
375 */
376EAPI void *elm_object_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data);
diff --git a/libraries/elementary/src/lib/elm_object_item.h b/libraries/elementary/src/lib/elm_object_item.h
new file mode 100644
index 0000000..01bb6b6
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_object_item.h
@@ -0,0 +1,434 @@
1/**
2 * Get the widget object's handle which contains a given item
3 *
4 * @param it The Elementary object item
5 * @return The widget object
6 *
7 * @note This returns the widget object itself that an item belongs to.
8 * @note Every elm_object_item supports this API
9 * @ingroup General
10 */
11EAPI Evas_Object *elm_object_item_widget_get(const Elm_Object_Item *it);
12
13/**
14 * Set a content of an object item
15 *
16 * @param it The Elementary object item
17 * @param part The content part name to set (NULL for the default content)
18 * @param content The new content of the object item
19 *
20 * This sets a new object to an item as a content object. If any object was
21 * already set as a content object in the same part, previous object will be
22 * deleted automatically.
23 *
24 * @note Elementary object items may have many contents
25 *
26 * @ingroup General
27 */
28EAPI void elm_object_item_part_content_set(Elm_Object_Item *it, const char *part, Evas_Object *content);
29
30#define elm_object_item_content_set(it, content) elm_object_item_part_content_set((it), NULL, (content))
31
32/**
33 * Get a content of an object item
34 *
35 * @param it The Elementary object item
36 * @param part The content part name to unset (NULL for the default content)
37 * @return content of the object item or NULL for any error
38 *
39 * @note Elementary object items may have many contents
40 *
41 * @ingroup General
42 */
43EAPI Evas_Object *elm_object_item_part_content_get(const Elm_Object_Item *it, const char *part);
44
45#define elm_object_item_content_get(it) elm_object_item_part_content_get((it), NULL)
46
47/**
48 * Unset a content of an object item
49 *
50 * @param it The Elementary object item
51 * @param part The content part name to unset (NULL for the default content)
52 *
53 * @note Elementary object items may have many contents
54 *
55 * @ingroup General
56 */
57EAPI Evas_Object *elm_object_item_part_content_unset(Elm_Object_Item *it, const char *part);
58
59#define elm_object_item_content_unset(it) elm_object_item_part_content_unset((it), NULL)
60
61/**
62 * Set a label of an object item
63 *
64 * @param it The Elementary object item
65 * @param part The text part name to set (NULL for the default label)
66 * @param label The new text of the label
67 *
68 * @note Elementary object items may have many labels
69 *
70 * @ingroup General
71 */
72EAPI void elm_object_item_part_text_set(Elm_Object_Item *it, const char *part, const char *label);
73
74#define elm_object_item_text_set(it, label) elm_object_item_part_text_set((it), NULL, (label))
75
76/**
77 * Get a label of an object item
78 *
79 * @param it The Elementary object item
80 * @param part The text part name to get (NULL for the default label)
81 * @return text of the label or NULL for any error
82 *
83 * @note Elementary object items may have many labels
84 *
85 * @ingroup General
86 */
87EAPI const char *elm_object_item_part_text_get(const Elm_Object_Item *it, const char *part);
88
89#define elm_object_item_text_get(it) elm_object_item_part_text_get((it), NULL)
90
91/**
92 * Set the text to read out when in accessibility mode
93 *
94 * @param it The object item which is to be described
95 * @param txt The text that describes the widget to people with poor or no vision
96 *
97 * @ingroup General
98 */
99EAPI void elm_object_item_access_info_set(Elm_Object_Item *it, const char *txt);
100
101/**
102 * Get the data associated with an object item
103 * @param it The Elementary object item
104 * @return The data associated with @p it
105 *
106 * @note Every elm_object_item supports this API
107 * @ingroup General
108 */
109EAPI void *elm_object_item_data_get(const Elm_Object_Item *it);
110
111/**
112 * Set the data associated with an object item
113 * @param it The Elementary object item
114 * @param data The data to be associated with @p it
115 *
116 * @note Every elm_object_item supports this API
117 * @ingroup General
118 */
119EAPI void elm_object_item_data_set(Elm_Object_Item *it, void *data);
120
121/**
122 * Send a signal to the edje object of the widget item.
123 *
124 * This function sends a signal to the edje object of the obj item. An
125 * edje program can respond to a signal by specifying matching
126 * 'signal' and 'source' fields.
127 *
128 * @param it The Elementary object item
129 * @param emission The signal's name.
130 * @param source The signal's source.
131 * @ingroup General
132 */
133EAPI void elm_object_item_signal_emit(Elm_Object_Item *it, const char *emission, const char *source);
134
135/**
136 * Set the disabled state of an widget item.
137 *
138 * @param it The Elementary object item
139 * @param disabled The state to put in in: @c EINA_TRUE for
140 * disabled, @c EINA_FALSE for enabled
141 *
142 * Elementary object item can be @b disabled, in which state they won't
143 * receive input and, in general, will be themed differently from
144 * their normal state, usually greyed out. Useful for contexts
145 * where you don't want your users to interact with some of the
146 * parts of you interface.
147 *
148 * This sets the state for the widget item, either disabling it or
149 * enabling it back.
150 *
151 * @ingroup Styles
152 */
153EAPI void elm_object_item_disabled_set(Elm_Object_Item *it, Eina_Bool disabled);
154
155/**
156 * Get the disabled state of an widget item.
157 *
158 * @param it The Elementary object item
159 * @return @c EINA_TRUE, if the widget item is disabled, @c EINA_FALSE
160 * if it's enabled (or on errors)
161 *
162 * This gets the state of the widget, which might be enabled or disabled.
163 *
164 * @ingroup Styles
165 */
166EAPI Eina_Bool elm_object_item_disabled_get(const Elm_Object_Item *it);
167
168/**
169 * @brief Set the function to be called when an item from the widget is
170 * freed.
171 *
172 * @param it The item to set the callback on
173 * @param del_cb The function called
174 *
175 * That function will receive these parameters:
176 * @li void * item data
177 * @li Evas_Object * widget object
178 * @li Elm_Object_Item * widget item
179 *
180 * @note Every elm_object_item supports this API
181 *
182 * @see elm_object_item_del()
183 * @ingroup General
184 */
185EAPI void elm_object_item_del_cb_set(Elm_Object_Item *it, Evas_Smart_Cb del_cb);
186
187/**
188 * Delete the given item.
189 *
190 * @param it The item to be deleted.
191 *
192 * @ingroup General
193 */
194EAPI void elm_object_item_del(Elm_Object_Item *it);
195
196/**
197 * Set the text to be shown in a given object item's tooltips.
198 *
199 * @param it Target item.
200 * @param text The text to set in the content.
201 *
202 * Setup the text as tooltip to object. The item can have only one tooltip,
203 * so any previous tooltip data - set with this function or
204 * elm_object_item_tooltip_content_cb_set() - is removed.
205 *
206 * @see elm_object_tooltip_text_set() for more details.
207 *
208 * @ingroup General
209 */
210EAPI void elm_object_item_tooltip_text_set(Elm_Object_Item *it, const char *text);
211
212/**
213 * @brief Disable size restrictions on an object's tooltip
214 * @param it The tooltip's anchor object
215 * @param disable If EINA_TRUE, size restrictions are disabled
216 * @return EINA_FALSE on failure, EINA_TRUE on success
217 *
218 * This function allows a tooltip to expand beyond its parent window's canvas.
219 * It will instead be limited only by the size of the display.
220 */
221EAPI Eina_Bool elm_object_item_tooltip_window_mode_set(Elm_Object_Item *it, Eina_Bool disable);
222
223/**
224 * @brief Retrieve size restriction state of an object's tooltip
225 * @param it The tooltip's anchor object
226 * @return If EINA_TRUE, size restrictions are disabled
227 *
228 * This function returns whether a tooltip is allowed to expand beyond
229 * its parent window's canvas.
230 * It will instead be limited only by the size of the display.
231 */
232EAPI Eina_Bool elm_object_item_tooltip_window_mode_get(const Elm_Object_Item *it);
233
234/**
235 * Set the content to be shown in the tooltip item.
236 *
237 * Setup the tooltip to item. The item can have only one tooltip,
238 * so any previous tooltip data is removed. @p func(with @p data) will
239 * be called every time that need show the tooltip and it should
240 * return a valid Evas_Object. This object is then managed fully by
241 * tooltip system and is deleted when the tooltip is gone.
242 *
243 * @param it the object item being attached a tooltip.
244 * @param func the function used to create the tooltip contents.
245 * @param data what to provide to @a func as callback data/context.
246 * @param del_cb called when data is not needed anymore, either when
247 * another callback replaces @a func, the tooltip is unset with
248 * elm_object_item_tooltip_unset() or the owner @a item
249 * dies. This callback receives as the first parameter the
250 * given @a data, and @c event_info is the item.
251 *
252 * @see elm_object_tooltip_content_cb_set() for more details.
253 *
254 * @ingroup General
255 */
256EAPI void elm_object_item_tooltip_content_cb_set(Elm_Object_Item *it, Elm_Tooltip_Item_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
257
258/**
259 * Unset tooltip from item.
260 *
261 * @param it object item to remove previously set tooltip.
262 *
263 * Remove tooltip from item. The callback provided as del_cb to
264 * elm_object_item_tooltip_content_cb_set() will be called to notify
265 * it is not used anymore.
266 *
267 * @see elm_object_tooltip_unset() for more details.
268 * @see elm_object_item_tooltip_content_cb_set()
269 *
270 * @ingroup General
271 */
272EAPI void elm_object_item_tooltip_unset(Elm_Object_Item *it);
273
274/**
275 * Sets a different style for this item tooltip.
276 *
277 * @note before you set a style you should define a tooltip with
278 * elm_object_item_tooltip_content_cb_set() or
279 * elm_object_item_tooltip_text_set()
280 *
281 * @param it object item with tooltip already set.
282 * @param style the theme style to use (default, transparent, ...)
283 *
284 * @see elm_object_tooltip_style_set() for more details.
285 *
286 * @ingroup General
287 */
288EAPI void elm_object_item_tooltip_style_set(Elm_Object_Item *it, const char *style);
289
290/**
291 * Get the style for this item tooltip.
292 *
293 * @param it object item with tooltip already set.
294 * @return style the theme style in use, defaults to "default". If the
295 * object does not have a tooltip set, then NULL is returned.
296 *
297 * @see elm_object_tooltip_style_get() for more details.
298 * @see elm_object_item_tooltip_style_set()
299 *
300 * @ingroup General
301 */
302EAPI const char *elm_object_item_tooltip_style_get(const Elm_Object_Item *it);
303
304/**
305 * Set the type of mouse pointer/cursor decoration to be shown,
306 * when the mouse pointer is over the given item
307 *
308 * @param it item to customize cursor on
309 * @param cursor the cursor type's name
310 *
311 * This function works analogously as elm_object_cursor_set(), but
312 * here the cursor's changing area is restricted to the item's
313 * area, and not the whole widget's. Note that that item cursors
314 * have precedence over widget cursors, so that a mouse over an
315 * item with custom cursor set will always show @b that cursor.
316 *
317 * If this function is called twice for an object, a previously set
318 * cursor will be unset on the second call.
319 *
320 * @see elm_object_cursor_set()
321 * @see elm_object_item_cursor_get()
322 * @see elm_object_item_cursor_unset()
323 *
324 * @ingroup General
325 */
326EAPI void elm_object_item_cursor_set(Elm_Object_Item *it, const char *cursor);
327
328/*
329 * Get the type of mouse pointer/cursor decoration set to be shown,
330 * when the mouse pointer is over the given item
331 *
332 * @param it item with custom cursor set
333 * @return the cursor type's name or @c NULL, if no custom cursors
334 * were set to @p item (and on errors)
335 *
336 * @see elm_object_cursor_get()
337 * @see elm_object_item_cursor_set()
338 * @see elm_object_item_cursor_unset()
339 *
340 * @ingroup General
341 */
342EAPI const char *elm_object_item_cursor_get(const Elm_Object_Item *it);
343
344/**
345 * Unset any custom mouse pointer/cursor decoration set to be
346 * shown, when the mouse pointer is over the given
347 * item, thus making it show the @b default cursor again.
348 *
349 * @param it the item
350 *
351 * Use this call to undo any custom settings on this item's cursor
352 * decoration, bringing it back to defaults (no custom style set).
353 *
354 * @see elm_object_cursor_unset()
355 * @see elm_object_item_cursor_set()
356 *
357 * @ingroup General
358 */
359EAPI void elm_object_item_cursor_unset(Elm_Object_Item *it);
360
361/**
362 * Set a different @b style for a given custom cursor set for an
363 * item.
364 *
365 * @param it item with custom cursor set
366 * @param style the <b>theme style</b> to use (e.g. @c "default",
367 * @c "transparent", etc)
368 *
369 * This function only makes sense when one is using custom mouse
370 * cursor decorations <b>defined in a theme file</b>, which can have,
371 * given a cursor name/type, <b>alternate styles</b> on it. It
372 * works analogously as elm_object_cursor_style_set(), but here
373 * applies only to item objects.
374 *
375 * @warning Before you set a cursor style you should have defined a
376 * custom cursor previously on the item, with
377 * elm_object_item_cursor_set()
378 *
379 * @see elm_object_item_cursor_engine_only_set()
380 * @see elm_object_item_cursor_style_get()
381 *
382 * @ingroup General
383 */
384EAPI void elm_object_item_cursor_style_set(Elm_Object_Item *it, const char *style);
385
386/**
387 * Get the current @b style set for a given item's custom
388 * cursor
389 *
390 * @param it item with custom cursor set.
391 * @return style the cursor style in use. If the object does not
392 * have a cursor set, then @c NULL is returned.
393 *
394 * @see elm_object_item_cursor_style_set() for more details
395 *
396 * @ingroup General
397 */
398EAPI const char *elm_object_item_cursor_style_get(const Elm_Object_Item *it);
399
400/**
401 * Set if the (custom)cursor for a given item should be
402 * searched in its theme, also, or should only rely on the
403 * rendering engine.
404 *
405 * @param it item with custom (custom) cursor already set on
406 * @param engine_only Use @c EINA_TRUE to have cursors looked for
407 * only on those provided by the rendering engine, @c EINA_FALSE to
408 * have them searched on the widget's theme, as well.
409 *
410 * @note This call is of use only if you've set a custom cursor
411 * for items, with elm_object_item_cursor_set().
412 *
413 * @note By default, cursors will only be looked for between those
414 * provided by the rendering engine.
415 *
416 * @ingroup General
417 */
418EAPI void elm_object_item_cursor_engine_only_set(Elm_Object_Item *it, Eina_Bool engine_only);
419
420/**
421 * Get if the (custom) cursor for a given item is being
422 * searched in its theme, also, or is only relying on the rendering
423 * engine.
424 *
425 * @param it an object item
426 * @return @c EINA_TRUE, if cursors are being looked for only on
427 * those provided by the rendering engine, @c EINA_FALSE if they
428 * are being searched on the widget's theme, as well.
429 *
430 * @see elm_object_item_cursor_engine_only_set(), for more details
431 *
432 * @ingroup General
433 */
434EAPI Eina_Bool elm_object_item_cursor_engine_only_get(const Elm_Object_Item *it);
diff --git a/libraries/elementary/src/lib/elm_panel.c b/libraries/elementary/src/lib/elm_panel.c
new file mode 100644
index 0000000..a93a7e0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_panel.c
@@ -0,0 +1,399 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4#include "els_box.h"
5
6typedef struct _Widget_Data Widget_Data;
7struct _Widget_Data
8{
9 Evas_Object *scr, *bx, *content;
10 Elm_Panel_Orient orient;
11 Eina_Bool hidden : 1;
12};
13
14static const char *widtype = NULL;
15static void _del_hook(Evas_Object *obj);
16static void _theme_hook(Evas_Object *obj);
17static void _on_focus_hook(void *data, Evas_Object *obj);
18static void _sizing_eval(Evas_Object *obj);
19static void _resize(void *data, Evas *evas, Evas_Object *obj, void *event);
20static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
21static void _toggle_panel(void *data, Evas_Object *obj, const char *emission, const char *source);
22
23static void
24_del_hook(Evas_Object *obj)
25{
26 Widget_Data *wd = elm_widget_data_get(obj);
27 if (!wd) return;
28 free(wd);
29}
30
31static void
32_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
33{
34 Widget_Data *wd = elm_widget_data_get(obj);
35 if (!wd) return;
36
37 if (wd->scr)
38 {
39 elm_widget_mirrored_set(wd->bx, rtl);
40 elm_panel_orient_set(obj, elm_panel_orient_get(obj));
41 }
42}
43
44static void
45_theme_hook(Evas_Object *obj)
46{
47 Widget_Data *wd = elm_widget_data_get(obj);
48 if (!wd) return;
49 _elm_widget_mirrored_reload(obj);
50 if (wd->scr)
51 {
52 Evas_Object *edj;
53 const char *str;
54
55 _mirrored_set(obj, elm_widget_mirrored_get(obj));
56 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base",
57 elm_widget_style_get(obj));
58 // scale = (elm_widget_scale_get(obj) * _elm_config->scale);
59 // edje_object_scale_set(wd->scr, scale);
60 edj = elm_smart_scroller_edje_object_get(wd->scr);
61 str = edje_object_data_get(edj, "focus_highlight");
62 if ((str) && (!strcmp(str, "on")))
63 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
64 else
65 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
66 }
67
68 _sizing_eval(obj);
69}
70
71static void
72_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
73{
74 Widget_Data *wd = elm_widget_data_get(obj);
75 if (!wd) return;
76 if (elm_widget_focus_get(obj))
77 evas_object_focus_set(obj, EINA_TRUE);
78 else
79 evas_object_focus_set(obj, EINA_FALSE);
80}
81
82static Eina_Bool
83_elm_panel_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
84{
85 Widget_Data *wd = elm_widget_data_get(obj);
86 Evas_Object *cur;
87
88 if ((!wd) || (!wd->content))
89 return EINA_FALSE;
90
91 cur = wd->content;
92
93 /* Try Focus cycle in subitem */
94 if (!wd->hidden)
95 return elm_widget_focus_next_get(cur, dir, next);
96
97 /* Return */
98 *next = (Evas_Object *)obj;
99 return !elm_widget_focus_get(obj);
100}
101
102static void
103_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
104{
105 Widget_Data *wd = elm_widget_data_get(obj);
106 if (!wd) return;
107 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
108 emission, source);
109}
110
111static void
112_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
113{
114 Widget_Data *wd = elm_widget_data_get(obj);
115 if (!wd) return;
116 edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
117 emission, source, func_cb, data);
118}
119
120static void
121_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
122{
123 Widget_Data *wd = elm_widget_data_get(obj);
124 edje_object_signal_callback_del_full(
125 elm_smart_scroller_edje_object_get(wd->scr), emission, source,
126 func_cb, data);
127}
128
129static void
130_sizing_eval(Evas_Object *obj)
131{
132 Widget_Data *wd = elm_widget_data_get(obj);
133 Evas_Coord mw = -1, mh = -1;
134 Evas_Coord vw = 0, vh = 0;
135 Evas_Coord w, h;
136 if (!wd) return;
137 evas_object_smart_calculate(wd->bx);
138 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
139 &mw, &mh);
140 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
141 if (w < mw) w = mw;
142 if (h < mh) h = mh;
143 evas_object_resize(wd->scr, w, h);
144
145 evas_object_size_hint_min_get(wd->bx, &mw, &mh);
146 if (w > mw) mw = w;
147 if (h > mh) mh = h;
148 evas_object_resize(wd->bx, mw, mh);
149
150 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
151 mw = mw + (w - vw);
152 mh = mh + (h - vh);
153 evas_object_size_hint_min_set(obj, mw, mh);
154 evas_object_size_hint_max_set(obj, -1, -1);
155}
156
157static void
158_resize(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event __UNUSED__)
159{
160 Widget_Data *wd = elm_widget_data_get(data);
161 Evas_Coord mw, mh, vw, vh, w, h;
162 if (!wd) return;
163 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
164 evas_object_size_hint_min_get(wd->bx, &mw, &mh);
165 evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
166 if ((vw >= mw) || (vh >= mh))
167 {
168 if ((w != vw) || (h != vh)) evas_object_resize(wd->bx, vw, vh);
169 }
170}
171
172static void
173_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
174{
175 Widget_Data *wd = data;
176 if (!wd) return;
177 _els_box_layout(o, priv, EINA_TRUE, EINA_FALSE, EINA_FALSE);
178}
179
180static void
181_toggle_panel(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
182{
183 Widget_Data *wd = elm_widget_data_get(data);
184 if (!wd) return;
185 if (wd->hidden)
186 {
187 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
188 "elm,action,show", "elm");
189 wd->hidden = EINA_FALSE;
190 evas_object_repeat_events_set(obj, EINA_FALSE);
191 }
192 else
193 {
194 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
195 "elm,action,hide", "elm");
196 wd->hidden = EINA_TRUE;
197 evas_object_repeat_events_set(obj, EINA_TRUE);
198 if (elm_widget_focus_get(wd->content))
199 {
200 elm_widget_focused_object_clear(obj);
201 elm_widget_focus_steal(obj);
202 }
203 }
204}
205
206static Eina_Bool
207_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
208{
209 if ((src != obj) || (type != EVAS_CALLBACK_KEY_DOWN)) return EINA_FALSE;
210
211 Evas_Event_Key_Down *ev = event_info;
212 Widget_Data *wd = elm_widget_data_get(obj);
213 if (!wd) return EINA_FALSE;
214
215 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
216
217 if ((strcmp(ev->keyname, "Return")) &&
218 (strcmp(ev->keyname, "KP_Enter")) &&
219 (strcmp(ev->keyname, "space")))
220 return EINA_FALSE;
221
222 _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
223
224 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
225 return EINA_TRUE;
226}
227
228static void
229_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
230{
231 ELM_CHECK_WIDTYPE(obj, widtype);
232 Widget_Data *wd;
233
234 if (part && strcmp(part, "default")) return;
235 wd = elm_widget_data_get(obj);
236 if (!wd) return;
237 if (wd->content == content) return;
238 if (wd->content)
239 evas_object_box_remove_all(wd->bx, EINA_TRUE);
240 wd->content = content;
241 if (content)
242 {
243 evas_object_box_append(wd->bx, wd->content);
244 evas_object_show(wd->content);
245 }
246 _sizing_eval(obj);
247}
248
249static Evas_Object *
250_content_get_hook(const Evas_Object *obj, const char *part)
251{
252 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
253 Widget_Data *wd;
254
255 if (part && strcmp(part, "default")) return NULL;
256 wd = elm_widget_data_get(obj);
257 if (!wd) return NULL;
258 return wd->content;
259}
260
261static Evas_Object *
262_content_unset_hook(Evas_Object *obj, const char *part)
263{
264 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
265 Widget_Data *wd;
266 Evas_Object *content;
267 if (part && strcmp(part, "default")) return NULL;
268 wd = elm_widget_data_get(obj);
269 if (!wd) return NULL;
270 if (!wd->content) return NULL;
271 content = wd->content;
272 evas_object_box_remove_all(wd->bx, EINA_FALSE);
273 wd->content = NULL;
274 return content;
275}
276
277EAPI Evas_Object *
278elm_panel_add(Evas_Object *parent)
279{
280 Evas_Object *obj;
281 Evas *e;
282 Widget_Data *wd;
283
284 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
285
286 ELM_SET_WIDTYPE(widtype, "panel");
287 elm_widget_type_set(obj, "panel");
288 elm_widget_sub_object_add(parent, obj);
289 elm_widget_data_set(obj, wd);
290 elm_widget_del_hook_set(obj, _del_hook);
291 elm_widget_theme_hook_set(obj, _theme_hook);
292 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
293 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
294 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
295 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
296 elm_widget_focus_next_hook_set(obj, _elm_panel_focus_next_hook);
297 elm_widget_can_focus_set(obj, EINA_TRUE);
298 elm_widget_event_hook_set(obj, _event_hook);
299 elm_widget_content_set_hook_set(obj, _content_set_hook);
300 elm_widget_content_get_hook_set(obj, _content_get_hook);
301 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
302
303 wd->scr = elm_smart_scroller_add(e);
304 elm_smart_scroller_widget_set(wd->scr, obj);
305 _theme_hook(obj);
306 elm_smart_scroller_bounce_allow_set(wd->scr, EINA_FALSE, EINA_FALSE);
307 elm_widget_resize_object_set(obj, wd->scr);
308 elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
309 ELM_SMART_SCROLLER_POLICY_OFF);
310
311 wd->hidden = EINA_FALSE;
312 wd->orient = ELM_PANEL_ORIENT_LEFT;
313
314 wd->bx = evas_object_box_add(e);
315 evas_object_size_hint_align_set(wd->bx, 0.5, 0.5);
316 evas_object_box_layout_set(wd->bx, _layout, wd, NULL);
317 elm_widget_sub_object_add(obj, wd->bx);
318 elm_smart_scroller_child_set(wd->scr, wd->bx);
319 evas_object_show(wd->bx);
320
321 edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
322 "elm,action,panel,toggle", "*",
323 _toggle_panel, obj);
324
325 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
326
327 _mirrored_set(obj, elm_widget_mirrored_get(obj));
328 _sizing_eval(obj);
329 return obj;
330}
331
332EAPI void
333elm_panel_orient_set(Evas_Object *obj, Elm_Panel_Orient orient)
334{
335 ELM_CHECK_WIDTYPE(obj, widtype);
336 Widget_Data *wd = elm_widget_data_get(obj);
337 if (!wd) return;
338 wd->orient = orient;
339 switch (orient)
340 {
341 case ELM_PANEL_ORIENT_TOP:
342 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "top");
343 break;
344 case ELM_PANEL_ORIENT_BOTTOM:
345 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "bottom");
346 break;
347 case ELM_PANEL_ORIENT_LEFT:
348 if (!elm_widget_mirrored_get(obj))
349 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left");
350 else
351 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "right");
352 break;
353 case ELM_PANEL_ORIENT_RIGHT:
354 if (!elm_widget_mirrored_get(obj))
355 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "right");
356 else
357 elm_smart_scroller_object_theme_set(obj, wd->scr, "panel", "base", "left");
358 break;
359 }
360
361 _sizing_eval(obj);
362}
363
364EAPI Elm_Panel_Orient
365elm_panel_orient_get(const Evas_Object *obj)
366{
367 ELM_CHECK_WIDTYPE(obj, widtype) ELM_PANEL_ORIENT_LEFT;
368 Widget_Data *wd = elm_widget_data_get(obj);
369 if (!wd) return ELM_PANEL_ORIENT_LEFT;
370 return wd->orient;
371}
372
373EAPI void
374elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden)
375{
376 ELM_CHECK_WIDTYPE(obj, widtype);
377 Widget_Data *wd = elm_widget_data_get(obj);
378 if (!wd) return;
379 if (wd->hidden == hidden) return;
380 _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
381}
382
383EAPI Eina_Bool
384elm_panel_hidden_get(const Evas_Object *obj)
385{
386 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
387 Widget_Data *wd = elm_widget_data_get(obj);
388 if (!wd) return EINA_FALSE;
389 return wd->hidden;
390}
391
392EAPI void
393elm_panel_toggle(Evas_Object *obj)
394{
395 ELM_CHECK_WIDTYPE(obj, widtype);
396 Widget_Data *wd = elm_widget_data_get(obj);
397 if (!wd) return;
398 _toggle_panel(obj, NULL, "elm,action,panel,toggle", "*");
399}
diff --git a/libraries/elementary/src/lib/elm_panel.h b/libraries/elementary/src/lib/elm_panel.h
new file mode 100644
index 0000000..fabbcc0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_panel.h
@@ -0,0 +1,105 @@
1/**
2 * @defgroup Panel Panel
3 * @ingroup Elementary
4 *
5 * @image html img/widget/panel/preview-00.png
6 * @image latex img/widget/panel/preview-00.eps
7 *
8 * @brief A panel is a type of animated container that contains subobjects.
9 * It can be expanded or contracted by clicking the button on it's edge.
10 *
11 * Orientations are as follows:
12 * @li ELM_PANEL_ORIENT_TOP
13 * @li ELM_PANEL_ORIENT_LEFT
14 * @li ELM_PANEL_ORIENT_RIGHT
15 *
16 * Default content parts of the panel widget that you can use for are:
17 * @li "default" - A content of the panel
18 *
19 * Supported elm_object common APIs.
20 * @li @ref elm_object_signal_emit
21 * @li @ref elm_object_signal_callback_add
22 * @li @ref elm_object_signal_callback_del
23 * @li @ref elm_object_part_content_set
24 * @li @ref elm_object_part_content_get
25 * @li @ref elm_object_part_content_unset
26 *
27 * @ref tutorial_panel shows one way to use this widget.
28 * @{
29 */
30typedef enum
31{
32 ELM_PANEL_ORIENT_TOP, /**< Panel (dis)appears from the top */
33 ELM_PANEL_ORIENT_BOTTOM, /**< Not implemented */
34 ELM_PANEL_ORIENT_LEFT, /**< Panel (dis)appears from the left */
35 ELM_PANEL_ORIENT_RIGHT, /**< Panel (dis)appears from the right */
36} Elm_Panel_Orient;
37
38/**
39 * @brief Adds a panel object
40 *
41 * @param parent The parent object
42 *
43 * @return The panel object, or NULL on failure
44 *
45 * @ingroup Panel
46 */
47EAPI Evas_Object *elm_panel_add(Evas_Object *parent);
48
49/**
50 * @brief Sets the orientation of the panel
51 *
52 * @param obj The panel object
53 * @param orient The panel orientation. Can be one of the following:
54 * @li ELM_PANEL_ORIENT_TOP
55 * @li ELM_PANEL_ORIENT_LEFT
56 * @li ELM_PANEL_ORIENT_RIGHT
57 *
58 * Sets from where the panel will (dis)appear.
59 *
60 * @ingroup Panel
61 */
62EAPI void elm_panel_orient_set(Evas_Object *obj, Elm_Panel_Orient orient);
63
64/**
65 * @brief Get the orientation of the panel.
66 *
67 * @param obj The panel object
68 * @return The Elm_Panel_Orient, or ELM_PANEL_ORIENT_LEFT on failure.
69 *
70 * @ingroup Panel
71 */
72EAPI Elm_Panel_Orient elm_panel_orient_get(const Evas_Object *obj);
73
74/**
75 * @brief Set the state of the panel.
76 *
77 * @param obj The panel object
78 * @param hidden If true, the panel will run the animation to disappear.
79 *
80 * @ingroup Panel
81 */
82EAPI void elm_panel_hidden_set(Evas_Object *obj, Eina_Bool hidden);
83
84/**
85 * @brief Get the state of the panel.
86 *
87 * @param obj The panel object
88 * @return EINA_TRUE if it is hidden state
89 *
90 * @ingroup Panel
91 */
92EAPI Eina_Bool elm_panel_hidden_get(const Evas_Object *obj);
93
94/**
95 * @brief Toggle the hidden state of the panel from code
96 *
97 * @param obj The panel object
98 *
99 * @ingroup Panel
100 */
101EAPI void elm_panel_toggle(Evas_Object *obj);
102
103/**
104 * @}
105 */
diff --git a/libraries/elementary/src/lib/elm_panes.c b/libraries/elementary/src/lib/elm_panes.c
new file mode 100644
index 0000000..249f9e2
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_panes.c
@@ -0,0 +1,470 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4/**
5 * TODO
6 * Update the minimun height of the bar in the theme.
7 * No minimun should be set in the vertical theme
8 * Add events (move, start ...)
9 */
10
11typedef struct _Widget_Data Widget_Data;
12
13struct _Widget_Data
14{
15 Evas_Object *panes;
16
17 struct
18 {
19 Evas_Object *left;
20 Evas_Object *right;
21 } contents;
22
23 struct
24 {
25 int x_diff;
26 int y_diff;
27 Eina_Bool move;
28 } move;
29
30 Eina_Bool clicked_double;
31 Eina_Bool horizontal;
32 Eina_Bool fixed;
33};
34
35static const char *widtype = NULL;
36static void _del_hook(Evas_Object *obj);
37static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
38static void _theme_hook(Evas_Object *obj);
39static void _sizing_eval(Evas_Object *obj);
40static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
41
42static const char SIG_CLICKED[] = "clicked";
43static const char SIG_PRESS[] = "press";
44static const char SIG_UNPRESS[] = "unpress";
45static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
46
47static const Evas_Smart_Cb_Description _signals[] = {
48 {SIG_CLICKED, ""},
49 {SIG_PRESS, ""},
50 {SIG_UNPRESS, ""},
51 {SIG_CLICKED_DOUBLE, ""},
52 {NULL, NULL}
53};
54
55static void
56_del_hook(Evas_Object *obj)
57{
58 Widget_Data *wd = elm_widget_data_get(obj);
59 if (!wd) return;
60 free(wd);
61}
62
63static void
64_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
65{
66 Widget_Data *wd = elm_widget_data_get(obj);
67 if (!wd) return;
68 edje_object_mirrored_set(wd->panes, rtl);
69}
70
71static void
72_theme_hook(Evas_Object *obj)
73{
74 Widget_Data *wd = elm_widget_data_get(obj);
75 const char *style = elm_widget_style_get(obj);
76 double size;
77
78 if (!wd) return;
79 _elm_widget_mirrored_reload(obj);
80 _mirrored_set(obj, elm_widget_mirrored_get(obj));
81 size = elm_panes_content_left_size_get(obj);
82
83 if (wd->horizontal)
84 _elm_theme_object_set(obj, wd->panes, "panes", "horizontal", style);
85 else
86 _elm_theme_object_set(obj, wd->panes, "panes", "vertical", style);
87
88 if (wd->contents.left)
89 edje_object_part_swallow(wd->panes, "elm.swallow.left", wd->contents.left);
90 if (wd->contents.right)
91 edje_object_part_swallow(wd->panes, "elm.swallow.right", wd->contents.right);
92 if (wd->fixed)
93 edje_object_signal_emit(wd->panes, "elm.panes.fixed", "elm");
94
95 edje_object_scale_set(wd->panes, elm_widget_scale_get(obj) *
96 _elm_config->scale);
97 _sizing_eval(obj);
98 elm_panes_content_left_size_set(obj, size);
99}
100
101static Eina_Bool
102_elm_panes_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
103{
104 Widget_Data *wd = elm_widget_data_get(obj);
105 if (!wd) return EINA_FALSE;
106
107 double w, h;
108 edje_object_part_drag_value_get(wd->panes, "elm.bar", &w, &h);
109 if (((wd->horizontal) && ( h == 0.0 )) || ((!wd->horizontal) && ( w == 0.0 )))
110 return elm_widget_focus_next_get(wd->contents.right, dir, next);
111
112 Evas_Object *chain[2];
113
114 /* Direction */
115 if (dir == ELM_FOCUS_PREVIOUS)
116 {
117 chain[0] = wd->contents.right;
118 chain[1] = wd->contents.left;
119 }
120 else if (dir == ELM_FOCUS_NEXT)
121 {
122 chain[0] = wd->contents.left;
123 chain[1] = wd->contents.right;
124 }
125 else
126 return EINA_FALSE;
127
128 unsigned char i = elm_widget_focus_get(chain[1]);
129
130 if (elm_widget_focus_next_get(chain[i], dir, next))
131 return EINA_TRUE;
132
133 i = !i;
134
135 Evas_Object *to_focus;
136 if (elm_widget_focus_next_get(chain[i], dir, &to_focus))
137 {
138 *next = to_focus;
139 return !!i;
140 }
141
142 return EINA_FALSE;
143}
144
145static void
146_sizing_eval(Evas_Object *obj)
147{
148 Widget_Data *wd = elm_widget_data_get(obj);
149 if (!wd) return;
150}
151
152static void
153_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
154{
155 _sizing_eval(data);
156}
157
158static void
159_sub_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
160{
161 Widget_Data *wd = elm_widget_data_get(obj);
162 Evas_Object *sub = event_info;
163
164 if (!wd) return;
165 if (sub == wd->contents.left)
166 {
167 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
168 _changed_size_hints, obj);
169 edje_object_part_unswallow(wd->panes, sub);
170 wd->contents.left = NULL;
171 _sizing_eval(obj);
172 }
173 else if (sub == wd->contents.right)
174 {
175 evas_object_event_callback_del_full(sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
176 _changed_size_hints, obj);
177 edje_object_part_unswallow(wd->panes, sub);
178 wd->contents.right= NULL;
179 _sizing_eval(obj);
180 }
181}
182
183static void
184_clicked(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
185{
186 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
187}
188
189static void
190_clicked_double(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
191{
192 Widget_Data *wd = elm_widget_data_get(data);
193
194 wd->clicked_double = EINA_TRUE;
195}
196
197static void
198_press(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
199{
200 evas_object_smart_callback_call(data, SIG_PRESS, NULL);
201}
202
203static void
204_unpress(void *data, Evas_Object *obj __UNUSED__ , const char *emission __UNUSED__, const char *source __UNUSED__)
205{
206 Widget_Data *wd = elm_widget_data_get(data);
207 evas_object_smart_callback_call(data, SIG_UNPRESS, NULL);
208
209 if (wd->clicked_double)
210 {
211 evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
212 wd->clicked_double = EINA_FALSE;
213 }
214}
215
216static void
217_content_left_set(Evas_Object *obj, Evas_Object *content)
218{
219 Widget_Data *wd = elm_widget_data_get(obj);
220 if (wd->contents.left == content) return;
221 if (wd->contents.left)
222 evas_object_del(wd->contents.left);
223 wd->contents.left = content;
224 if (content)
225 {
226 elm_widget_sub_object_add(obj, content);
227 edje_object_part_swallow(wd->panes, "elm.swallow.left", content);
228 }
229}
230
231static void
232_content_right_set(Evas_Object *obj, Evas_Object *content)
233{
234 Widget_Data *wd = elm_widget_data_get(obj);
235 if (wd->contents.right == content) return;
236 if (wd->contents.right)
237 evas_object_del(wd->contents.right);
238 wd->contents.right = content;
239 if (content)
240 {
241 elm_widget_sub_object_add(obj, content);
242 edje_object_part_swallow(wd->panes, "elm.swallow.right", content);
243 }
244}
245
246static Evas_Object *
247_content_left_unset(Evas_Object *obj)
248{
249 Widget_Data *wd = elm_widget_data_get(obj);
250 if (!wd->contents.left) return NULL;
251 Evas_Object *content = wd->contents.left;
252 elm_widget_sub_object_del(obj, content);
253 return content;
254}
255
256static Evas_Object *
257_content_right_unset(Evas_Object *obj)
258{
259 Widget_Data *wd = elm_widget_data_get(obj);
260 if (!wd->contents.right) return NULL;
261 Evas_Object *content = wd->contents.right;
262 elm_widget_sub_object_del(obj, content);
263 return content;
264}
265
266static void
267_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
268{
269 ELM_CHECK_WIDTYPE(obj, widtype);
270 Widget_Data *wd = elm_widget_data_get(obj);
271 if (!wd) return;
272 if (part && (!strncmp(part, "elm.swallow.", 12))) part += 12;
273 if (!part || !strcmp(part, "left"))
274 _content_left_set(obj, content);
275 else if (!strcmp(part, "right"))
276 _content_right_set(obj, content);
277}
278
279static Evas_Object *
280_content_get_hook(const Evas_Object *obj, const char *part)
281{
282 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
283 Widget_Data *wd = elm_widget_data_get(obj);
284 if (!wd) return NULL;
285 if (part && (!strncmp(part, "elm.swallow.", 12))) part += 12;
286 if (!part || !strcmp(part, "left"))
287 return wd->contents.left;
288 else if (!strcmp(part, "right"))
289 return wd->contents.right;
290 return NULL;
291}
292
293static Evas_Object *
294_content_unset_hook(Evas_Object *obj, const char *part)
295{
296 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
297 Widget_Data *wd = elm_widget_data_get(obj);
298 if (!wd) return NULL;
299 if (part && (!strncmp(part, "elm.swallow.", 12))) part += 12;
300 if (!part || !strcmp(part, "left"))
301 return _content_left_unset(obj);
302 else if (!strcmp(part, "right"))
303 return _content_right_unset(obj);
304 return NULL;
305}
306
307EAPI Evas_Object *
308elm_panes_add(Evas_Object *parent)
309{
310 Evas_Object *obj;
311 Evas *e;
312 Widget_Data *wd;
313
314 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
315
316 ELM_SET_WIDTYPE(widtype, "panes");
317 elm_widget_type_set(obj, "panes");
318 elm_widget_sub_object_add(parent, obj);
319 elm_widget_data_set(obj, wd);
320 elm_widget_del_hook_set(obj, _del_hook);
321 elm_widget_theme_hook_set(obj, _theme_hook);
322 elm_widget_focus_next_hook_set(obj, _elm_panes_focus_next_hook);
323 elm_widget_content_set_hook_set(obj, _content_set_hook);
324 elm_widget_content_get_hook_set(obj, _content_get_hook);
325 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
326 elm_widget_can_focus_set(obj, EINA_FALSE);
327
328 wd->panes = edje_object_add(e);
329 _elm_theme_object_set(obj, wd->panes, "panes", "vertical", "default");
330 elm_widget_resize_object_set(obj, wd->panes);
331 evas_object_show(wd->panes);
332
333 elm_panes_content_left_size_set(obj, 0.5);
334
335 edje_object_signal_callback_add(wd->panes, "elm,action,click", "",
336 _clicked, obj);
337 edje_object_signal_callback_add(wd->panes, "elm,action,click,double", "",
338 _clicked_double, obj);
339 edje_object_signal_callback_add(wd->panes, "elm,action,press", "",
340 _press, obj);
341 edje_object_signal_callback_add(wd->panes, "elm,action,unpress", "",
342 _unpress, obj);
343
344 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
345 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
346 _changed_size_hints, obj);
347
348 evas_object_smart_callbacks_descriptions_set(obj, _signals);
349
350 _mirrored_set(obj, elm_widget_mirrored_get(obj));
351 _sizing_eval(obj);
352 return obj;
353}
354
355EINA_DEPRECATED EAPI void
356elm_panes_content_left_set(Evas_Object *obj, Evas_Object *content)
357{
358 _content_set_hook(obj, "left", content);
359}
360
361EINA_DEPRECATED EAPI void
362elm_panes_content_right_set(Evas_Object *obj, Evas_Object *content)
363{
364 _content_set_hook(obj, "right", content);
365}
366
367EINA_DEPRECATED EAPI Evas_Object *
368elm_panes_content_left_get(const Evas_Object *obj)
369{
370 return _content_get_hook(obj, "left");
371}
372
373EINA_DEPRECATED EAPI Evas_Object *
374elm_panes_content_right_get(const Evas_Object *obj)
375{
376 return _content_get_hook(obj, "right");
377}
378
379EINA_DEPRECATED EAPI Evas_Object *
380elm_panes_content_left_unset(Evas_Object *obj)
381{
382 return _content_unset_hook(obj, "left");
383}
384
385EINA_DEPRECATED EAPI Evas_Object *
386elm_panes_content_right_unset(Evas_Object *obj)
387{
388 return _content_unset_hook(obj, "right");
389}
390
391EAPI double
392elm_panes_content_left_size_get(const Evas_Object *obj)
393{
394 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
395 Widget_Data *wd = elm_widget_data_get(obj);
396 double w, h;
397
398 if (!wd) return 0;
399 edje_object_part_drag_value_get(wd->panes, "elm.bar", &w, &h);
400 if (wd->horizontal) return h;
401 else return w;
402}
403
404EAPI void
405elm_panes_content_left_size_set(Evas_Object *obj, double size)
406{
407 ELM_CHECK_WIDTYPE(obj, widtype);
408 Widget_Data *wd = elm_widget_data_get(obj);
409 if (!wd) return;
410 if (size < 0.0) size = 0.0;
411 else if (size > 1.0) size = 1.0;
412 if (wd->horizontal)
413 edje_object_part_drag_value_set(wd->panes, "elm.bar", 0.0, size);
414 else
415 edje_object_part_drag_value_set(wd->panes, "elm.bar", size, 0.0);
416}
417
418EAPI double
419elm_panes_content_right_size_get(const Evas_Object *obj)
420{
421 return (1.0 - elm_panes_content_left_size_get(obj));
422}
423
424EAPI void
425elm_panes_content_right_size_set(Evas_Object *obj, double size)
426{
427 elm_panes_content_left_size_set(obj, (1.0 - size));
428}
429
430EAPI void
431elm_panes_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
432{
433 ELM_CHECK_WIDTYPE(obj, widtype);
434 Widget_Data *wd = elm_widget_data_get(obj);
435 if (!wd) return;
436 wd->horizontal = horizontal;
437 _theme_hook(obj);
438 elm_panes_content_left_size_set(obj, 0.5);
439}
440
441EAPI Eina_Bool
442elm_panes_horizontal_get(const Evas_Object *obj)
443{
444 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
445 Widget_Data *wd = elm_widget_data_get(obj);
446 if (!wd) return EINA_FALSE;
447 return wd->horizontal;
448}
449
450EAPI void
451elm_panes_fixed_set(Evas_Object *obj, Eina_Bool fixed)
452{
453 ELM_CHECK_WIDTYPE(obj, widtype);
454 Widget_Data *wd = elm_widget_data_get(obj);
455 if (!wd) return;
456 wd->fixed = !!fixed;
457 if (wd->fixed == EINA_TRUE)
458 edje_object_signal_emit(wd->panes, "elm.panes.fixed", "elm");
459 else
460 edje_object_signal_emit(wd->panes, "elm.panes.unfixed", "elm");
461}
462
463EAPI Eina_Bool
464elm_panes_fixed_get(const Evas_Object *obj)
465{
466 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
467 Widget_Data *wd = elm_widget_data_get(obj);
468 if (!wd) return EINA_FALSE;
469 return wd->fixed;
470}
diff --git a/libraries/elementary/src/lib/elm_panes.h b/libraries/elementary/src/lib/elm_panes.h
new file mode 100644
index 0000000..f0fa004
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_panes.h
@@ -0,0 +1,205 @@
1/**
2 * @defgroup Panes Panes
3 * @ingroup Elementary
4 *
5 * @image html img/widget/panes/preview-00.png
6 * @image latex img/widget/panes/preview-00.eps width=\textwidth
7 *
8 * @image html img/panes.png
9 * @image latex img/panes.eps width=\textwidth
10 *
11 * The panes widget adds a draggable bar between two contents. When dragged
12 * this bar will resize contents' size.
13 *
14 * Panes can be displayed vertically or horizontally, and contents
15 * size proportion can be customized (homogeneous by default).
16 *
17 * Smart callbacks one can listen to:
18 * - "press" - The panes has been pressed (button wasn't released yet).
19 * - "unpressed" - The panes was released after being pressed.
20 * - "clicked" - The panes has been clicked>
21 * - "clicked,double" - The panes has been double clicked
22 *
23 * Available styles for it:
24 * - @c "default"
25 *
26 * Default content parts of the panes widget that you can use are:
27 * @li "left" - A leftside content of the panes
28 * @li "right" - A rightside content of the panes
29 *
30 * If panes are displayed vertically, left content will be displayed on
31 * top.
32 *
33 * Supported elm_object common APIs.
34 * @li @ref elm_object_part_content_set
35 * @li @ref elm_object_part_content_get
36 * @li @ref elm_object_part_content_unset
37 *
38 * Here is an example on its usage:
39 * @li @ref panes_example
40 */
41
42/**
43 * @addtogroup Panes
44 * @{
45 */
46
47/**
48 * Add a new panes widget to the given parent Elementary
49 * (container) object.
50 *
51 * @param parent The parent object.
52 * @return a new panes widget handle or @c NULL, on errors.
53 *
54 * This function inserts a new panes widget on the canvas.
55 *
56 * @ingroup Panes
57 */
58EAPI Evas_Object *elm_panes_add(Evas_Object *parent);
59
60/**
61 * Set whether the left and right panes resize homogeneously or not.
62 *
63 * @param obj The panes object.
64 * @param fixed Use @c EINA_TRUE to make @p obj to be
65 * resize the left and right panes @b homogeneously.
66 * Use @c EINA_FALSE to make use of the values specified in
67 * elm_panes_content_left_size_set() and
68 * elm_panes_content_right_size_set()
69 * to resize the left and right panes.
70 *
71 * By default panes are resized homogeneously.
72 *
73 * @see elm_panes_fixed_get()
74 * @see elm_panes_content_left_size_set()
75 * @see elm_panes_content_right_size_set()
76 *
77 * @ingroup Panes
78 */
79EAPI void elm_panes_fixed_set(Evas_Object *obj, Eina_Bool fixed);
80
81/**
82 * Retrieve the resize mode for the panes of a given panes widget.
83 *
84 * @param obj The panes object.
85 * @return @c EINA_TRUE, if @p obj is set to be resized @b homogeneously,
86 *
87 * @see elm_panes_fixed_set() for more details.
88 * @see elm_panes_content_left_size_get()
89 * @see elm_panes_content_right_size_get()
90 *
91 * @ingroup Panes
92 */
93EAPI Eina_Bool elm_panes_fixed_get(const Evas_Object *obj);
94
95/**
96 * Get the size proportion of panes widget's left side.
97 *
98 * @param obj The panes object.
99 * @return float value between 0.0 and 1.0 representing size proportion
100 * of left side.
101 *
102 * @see elm_panes_content_left_size_set() for more details.
103 *
104 * @ingroup Panes
105 */
106EAPI double elm_panes_content_left_size_get(const Evas_Object *obj);
107
108/**
109 * Set the size proportion of panes widget's left side.
110 *
111 * @param obj The panes object.
112 * @param size Value between 0.0 and 1.0 representing size proportion
113 * of left side.
114 *
115 * By default it's homogeneous, i.e., both sides have the same size.
116 *
117 * If something different is required, it can be set with this function.
118 * For example, if the left content should be displayed over
119 * 75% of the panes size, @p size should be passed as @c 0.75.
120 * This way, right content will be resized to 25% of panes size.
121 *
122 * If displayed vertically, left content is displayed at top, and
123 * right content at bottom.
124 *
125 * @note This proportion will change when user drags the panes bar.
126 *
127 * @see elm_panes_content_left_size_get()
128 *
129 * @ingroup Panes
130 */
131EAPI void elm_panes_content_left_size_set(Evas_Object *obj, double size);
132
133/**
134 * Get the size proportion of panes widget's right side.
135 *
136 * @param obj The panes object.
137 * @return float value between 0.0 and 1.0 representing size proportion
138 * of right side.
139 *
140 * @see elm_panes_content_right_size_set() for more details.
141 *
142 * @ingroup Panes
143 */
144EAPI double elm_panes_content_right_size_get(const Evas_Object *obj);
145
146/**
147 * Set the size proportion of panes widget's right side.
148 *
149 * @param obj The panes object.
150 * @param size Value between 0.0 and 1.0 representing size proportion
151 * of right side.
152 *
153 * By default it's homogeneous, i.e., both sides have the same size.
154 *
155 * If something different is required, it can be set with this function.
156 * For example, if the right content should be displayed over
157 * 75% of the panes size, @p size should be passed as @c 0.75.
158 * This way, left content will be resized to 25% of panes size.
159 *
160 * If displayed vertically, left content is displayed at top, and
161 * right content at bottom.
162 *
163 * @note This proportion will change when user drags the panes bar.
164 *
165 * @see elm_panes_content_right_size_get()
166 *
167 * @ingroup Panes
168 */
169EAPI void elm_panes_content_right_size_set(Evas_Object *obj, double size);
170
171
172/**
173 * Set the orientation of a given panes widget.
174 *
175 * @param obj The panes object.
176 * @param horizontal Use @c EINA_TRUE to make @p obj to be
177 * @b horizontal, @c EINA_FALSE to make it @b vertical.
178 *
179 * Use this function to change how your panes is to be
180 * disposed: vertically or horizontally.
181 *
182 * By default it's displayed horizontally.
183 *
184 * @see elm_panes_horizontal_get()
185 *
186 * @ingroup Panes
187 */
188EAPI void elm_panes_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
189
190/**
191 * Retrieve the orientation of a given panes widget.
192 *
193 * @param obj The panes object.
194 * @return @c EINA_TRUE, if @p obj is set to be @b horizontal,
195 * @c EINA_FALSE if it's @b vertical (and on errors).
196 *
197 * @see elm_panes_horizontal_set() for more details.
198 *
199 * @ingroup Panes
200 */
201EAPI Eina_Bool elm_panes_horizontal_get(const Evas_Object *obj);
202
203/**
204 * @}
205 */
diff --git a/libraries/elementary/src/lib/elm_photo.c b/libraries/elementary/src/lib/elm_photo.c
new file mode 100644
index 0000000..275f52f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_photo.c
@@ -0,0 +1,633 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_icon.h"
4#include "els_scroller.h"
5
6typedef struct _Widget_Data Widget_Data;
7
8struct _Widget_Data
9{
10 Evas_Object *frm;
11 Evas_Object *img;
12 int size;
13 Eina_Bool fill;
14 Ecore_Timer *longtimer;
15
16#ifdef HAVE_ELEMENTARY_ETHUMB
17 struct
18 {
19 int id;
20
21 struct
22 {
23 const char *path;
24 const char *key;
25 } file, thumb;
26
27 Ethumb_Exists *exists;
28
29 Ecore_Event_Handler *eeh;
30
31 Ethumb_Thumb_Format format;
32
33 Eina_Bool retry : 1;
34 } thumb;
35#endif
36
37};
38
39#ifdef HAVE_ELEMENTARY_ETHUMB
40static Eina_List *_elm_icon_retry = NULL;
41static int _icon_pending_request = 0;
42
43static void _icon_thumb_exists(void *data, Ethumb_Client *client __UNUSED__, Ethumb_Exists *thread, Eina_Bool exists);
44static void _icon_thumb_stop(Widget_Data *wd, void *ethumbd);
45#endif
46
47static const char *widtype = NULL;
48static void _del_hook(Evas_Object *obj);
49static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
50static void _theme_hook(Evas_Object *obj);
51static void _sizing_eval(Evas_Object *obj);
52static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
53static void _mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
54
55static const char SIG_CLICKED[] = "clicked";
56static const char SIG_DRAG_START[] = "drag,start";
57static const char SIG_DRAG_END[] = "drag,end";
58
59static const Evas_Smart_Cb_Description _signals[] = {
60 {SIG_CLICKED, ""},
61 {SIG_DRAG_START, ""},
62 {SIG_DRAG_END, ""},
63 {NULL, NULL}
64};
65
66
67static void
68_del_hook(Evas_Object *obj)
69{
70 Widget_Data *wd = elm_widget_data_get(obj);
71#ifdef HAVE_ELEMENTARY_ETHUMB
72 Ethumb_Client *ethumbd;
73#endif
74 if (!wd) return;
75
76#ifdef HAVE_ELEMENTARY_ETHUMB
77 ethumbd = elm_thumb_ethumb_client_get();
78 _icon_thumb_stop(wd, ethumbd);
79
80 eina_stringshare_del(wd->thumb.file.path);
81 eina_stringshare_del(wd->thumb.file.key);
82 eina_stringshare_del(wd->thumb.thumb.path);
83 eina_stringshare_del(wd->thumb.thumb.key);
84
85 if (wd->thumb.eeh)
86 ecore_event_handler_del(wd->thumb.eeh);
87#endif
88
89 free(wd);
90}
91
92static void
93_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
94{
95 Widget_Data *wd = elm_widget_data_get(obj);
96 if (!wd) return;
97 edje_object_mirrored_set(wd->frm, rtl);
98}
99
100static void
101_theme_hook(Evas_Object *obj)
102{
103 Widget_Data *wd = elm_widget_data_get(obj);
104 if (!wd) return;
105 _elm_widget_mirrored_reload(obj);
106 _mirrored_set(wd->frm, elm_widget_mirrored_get(obj));
107 _elm_theme_object_set(obj, wd->frm, "photo", "base",
108 elm_widget_style_get(obj));
109 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
110 edje_object_scale_set(wd->frm, elm_widget_scale_get(obj) *
111 _elm_config->scale);
112 _sizing_eval(obj);
113}
114
115static void
116_sizing_eval(Evas_Object *obj)
117{
118 Widget_Data *wd = elm_widget_data_get(obj);
119 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
120
121 if (!wd) return;
122 if (wd->size > 0)
123 {
124 double scale = 0.0;
125
126 scale = (wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
127 evas_object_size_hint_min_set(wd->img, scale, scale);
128 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
129 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
130 edje_object_size_min_restricted_calc(wd->frm, &minw, &minh, minw, minh);
131 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
132 maxw = minw;
133 maxh = minh;
134 evas_object_size_hint_min_set(obj, minw, minh);
135 evas_object_size_hint_max_set(obj, maxw, maxh);
136 }
137}
138
139static void
140_icon_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
141{
142 Evas_Coord w, h;
143 Widget_Data *wd = elm_widget_data_get(data);
144
145 if (!wd) return;
146 if (wd->fill)
147 {
148 Edje_Message_Int_Set *msg;
149 Evas_Object *icon = _els_smart_icon_object_get(wd->img);
150
151 evas_object_geometry_get(icon, NULL, NULL, &w, &h);
152 msg = alloca(sizeof(Edje_Message_Int_Set) + (sizeof(int)));
153 msg->count=2;
154 msg->val[0] = (int)w;
155 msg->val[1] = (int)h;
156
157 edje_object_message_send(wd->frm, EDJE_MESSAGE_INT_SET, 0, msg);
158 }
159
160#ifdef HAVE_ELEMENTARY_ETHUMB
161 if (wd->thumb.file.path)
162 elm_photo_thumb_set(data, wd->thumb.file.path, wd->thumb.file.key);
163#endif
164}
165
166
167static void
168_drag_done_cb(void *unused __UNUSED__, Evas_Object *obj)
169{
170 elm_object_scroll_freeze_pop(obj);
171 evas_object_smart_callback_call(obj, SIG_DRAG_END, NULL);
172}
173
174static Eina_Bool
175_longpress(void *objv)
176{
177 Widget_Data *wd = elm_widget_data_get(objv);
178 Evas_Object *tmp;
179 const char *file;
180
181 DBG("Long press: start drag!");
182 wd->longtimer = NULL; /* clear: must return NULL now */
183 evas_object_event_callback_del(objv, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move);
184
185 tmp = _els_smart_icon_object_get(wd->img);
186 file = NULL;
187 evas_object_image_file_get(tmp,&file,NULL);
188 if (file)
189 {
190 char buf[4096 + 7];
191 /* FIXME: Deal with relative paths; use PATH_MAX */
192 snprintf(buf, sizeof(buf), "file://%s", file);
193 if (elm_drag_start(objv, ELM_SEL_FORMAT_IMAGE,
194 buf, _drag_done_cb, NULL))
195 {
196 elm_object_scroll_freeze_push(objv);
197 evas_object_smart_callback_call(objv, SIG_DRAG_START, NULL);
198 }
199 }
200
201 return 0; /* Don't call again */
202}
203
204static void
205_mouse_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event)
206{
207 Widget_Data *wd = elm_widget_data_get(data);
208 Evas_Event_Mouse_Move *move = event;
209
210 /* Sanity */
211 if (!wd->longtimer)
212 {
213 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move);
214 return;
215 }
216
217 /* if the event is held, stop waiting */
218 if (move->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
219 {
220 /* Moved too far: No longpress for you! */
221 ecore_timer_del(wd->longtimer);
222 wd->longtimer = NULL;
223 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_MOVE,
224 _mouse_move);
225 }
226}
227
228static void
229_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
230{
231 Widget_Data *wd = elm_widget_data_get(data);
232
233 if (wd->longtimer) ecore_timer_del(wd->longtimer);
234
235 /* FIXME: Hard coded timeout */
236 wd->longtimer = ecore_timer_add(0.7, _longpress, data);
237 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_MOVE,
238 _mouse_move, data);
239}
240
241static void
242_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
243{
244 Widget_Data *wd = elm_widget_data_get(data);
245
246 if ((wd) && (wd->longtimer))
247 {
248 ecore_timer_del(wd->longtimer);
249 wd->longtimer = NULL;
250 }
251
252 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
253}
254
255static inline int
256_icon_size_min_get(Evas_Object *icon)
257{
258 int size;
259 _els_smart_icon_size_get(icon, &size, NULL);
260 return (size < 32) ? 32 : size;
261}
262
263
264#ifdef HAVE_ELEMENTARY_ETHUMB
265static void
266_icon_thumb_stop(Widget_Data *wd, void *ethumbd)
267{
268 if (wd->thumb.id >= 0)
269 {
270 ethumb_client_generate_cancel(ethumbd, wd->thumb.id, NULL, NULL, NULL);
271 wd->thumb.id = -1;
272 _icon_pending_request--;
273 }
274
275 if (wd->thumb.exists)
276 {
277 ethumb_client_thumb_exists_cancel(wd->thumb.exists);
278 wd->thumb.exists = NULL;
279 _icon_pending_request--;
280 }
281
282 if (wd->thumb.retry)
283 {
284 _elm_icon_retry = eina_list_remove(_elm_icon_retry, wd);
285 wd->thumb.retry = EINA_FALSE;
286 }
287}
288
289static Eina_Bool
290_icon_thumb_display(Widget_Data *wd)
291{
292 Eina_Bool ret = EINA_FALSE;
293
294 if (wd->thumb.format == ETHUMB_THUMB_EET)
295 {
296 static const char *extensions[] = {
297 ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
298 };
299 const char **ext, *ptr;
300 int prefix_size;
301 Eina_Bool video = EINA_FALSE;
302
303 prefix_size = eina_stringshare_strlen(wd->thumb.file.path) - 4;
304 if (prefix_size >= 0)
305 {
306 ptr = wd->thumb.file.path + prefix_size;
307 for (ext = extensions; *ext; ++ext)
308 if (!strcasecmp(ptr, *ext))
309 {
310 video = EINA_TRUE;
311 break;
312 }
313 }
314
315 if (video)
316 ret = _els_smart_icon_file_edje_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
317 }
318
319 if (!ret)
320 ret = _els_smart_icon_file_key_set(wd->img, wd->thumb.thumb.path, wd->thumb.thumb.key);
321
322 return ret;
323}
324
325static Eina_Bool
326_icon_thumb_retry(Widget_Data *wd)
327{
328 return _icon_thumb_display(wd);
329}
330
331static void
332_icon_thumb_cleanup(Ethumb_Client *ethumbd)
333{
334 Eina_List *l, *ll;
335 Widget_Data *wd;
336
337 EINA_LIST_FOREACH_SAFE(_elm_icon_retry, l, ll, wd)
338 if (_icon_thumb_retry(wd))
339 {
340 _elm_icon_retry = eina_list_remove_list(_elm_icon_retry, l);
341 wd->thumb.retry = EINA_FALSE;
342 }
343
344 if (_icon_pending_request == 0)
345 EINA_LIST_FREE(_elm_icon_retry, wd)
346 _icon_thumb_stop(wd, ethumbd);
347}
348
349static void
350_icon_thumb_finish(Widget_Data *wd, Ethumb_Client *ethumbd)
351{
352 const char *file = NULL, *group = NULL;
353 Eina_Bool ret;
354
355 _els_smart_icon_file_get(wd->img, &file, &group);
356 file = eina_stringshare_ref(file);
357 group = eina_stringshare_ref(group);
358
359 ret = _icon_thumb_display(wd);
360
361 if (!ret && file)
362 {
363 const char *p;
364
365 if (!wd->thumb.retry)
366 {
367 _elm_icon_retry = eina_list_append(_elm_icon_retry, wd);
368 wd->thumb.retry = EINA_TRUE;
369 }
370
371 /* Back to previous image */
372 if (((p = strrchr(file, '.'))) && (!strcasecmp(p, ".edj")))
373 _els_smart_icon_file_edje_set(wd->img, file, group);
374 else
375 _els_smart_icon_file_key_set(wd->img, file, group);
376 }
377
378 _icon_thumb_cleanup(ethumbd);
379
380 eina_stringshare_del(file);
381 eina_stringshare_del(group);
382}
383
384static void
385_icon_thumb_cb(void *data,
386 Ethumb_Client *ethumbd,
387 int id,
388 const char *file __UNUSED__,
389 const char *key __UNUSED__,
390 const char *thumb_path,
391 const char *thumb_key,
392 Eina_Bool success)
393{
394 Widget_Data *wd = data;
395
396 EINA_SAFETY_ON_FALSE_RETURN(wd->thumb.id == id);
397 wd->thumb.id = -1;
398
399 _icon_pending_request--;
400
401 if (success)
402 {
403 eina_stringshare_replace(&wd->thumb.thumb.path, thumb_path);
404 eina_stringshare_replace(&wd->thumb.thumb.key, thumb_key);
405 wd->thumb.format = ethumb_client_format_get(ethumbd);
406
407 _icon_thumb_finish(wd, ethumbd);
408 }
409 else
410 {
411 ERR("could not generate thumbnail for %s (key: %s)", file, key);
412 _icon_thumb_cleanup(ethumbd);
413 }
414}
415
416static void
417_icon_thumb_exists(void *data, Ethumb_Client *client __UNUSED__, Ethumb_Exists *thread, Eina_Bool exists)
418{
419 Widget_Data *wd = data;
420 Ethumb_Client *ethumbd;
421
422 if (ethumb_client_thumb_exists_check(thread))
423 return ;
424
425 wd->thumb.exists = NULL;
426
427 ethumbd = elm_thumb_ethumb_client_get();
428
429 if (exists)
430 {
431 const char *thumb_path, *thumb_key;
432
433 _icon_pending_request--;
434 ethumb_client_thumb_path_get(ethumbd, &thumb_path, &thumb_key);
435 eina_stringshare_replace(&wd->thumb.thumb.path, thumb_path);
436 eina_stringshare_replace(&wd->thumb.thumb.key, thumb_key);
437 wd->thumb.format = ethumb_client_format_get(ethumbd);
438
439 _icon_thumb_finish(wd, ethumbd);
440 }
441 else if ((wd->thumb.id = ethumb_client_generate(ethumbd, _icon_thumb_cb, wd, NULL)) == -1)
442 {
443 ERR("Generate was unable to start !");
444 /* Failed to generate thumbnail */
445 _icon_pending_request--;
446 }
447}
448
449static void
450_icon_thumb_apply(Widget_Data *wd)
451{
452 Ethumb_Client *ethumbd;
453
454 ethumbd = elm_thumb_ethumb_client_get();
455
456 _icon_thumb_stop(wd, ethumbd);
457
458 if (!wd->thumb.file.path) return ;
459
460 _icon_pending_request++;
461 if (!ethumb_client_file_set(ethumbd, wd->thumb.file.path, wd->thumb.file.key)) return ;
462 ethumb_client_size_set(ethumbd, _icon_size_min_get(wd->img), _icon_size_min_get(wd->img));
463 wd->thumb.exists = ethumb_client_thumb_exists(ethumbd, _icon_thumb_exists, wd);
464}
465
466static Eina_Bool
467_icon_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
468{
469 Widget_Data *wd = data;
470
471 _icon_thumb_apply(wd);
472 return ECORE_CALLBACK_RENEW;
473}
474#endif
475
476EAPI Evas_Object *
477elm_photo_add(Evas_Object *parent)
478{
479 Evas_Object *obj;
480 Evas *e;
481 Widget_Data *wd;
482 Evas_Object *icon;
483
484 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
485
486 ELM_SET_WIDTYPE(widtype, "photo");
487 elm_widget_type_set(obj, "photo");
488 elm_widget_sub_object_add(parent, obj);
489 elm_widget_data_set(obj, wd);
490 elm_widget_del_hook_set(obj, _del_hook);
491 elm_widget_theme_hook_set(obj, _theme_hook);
492 elm_widget_can_focus_set(obj, EINA_FALSE);
493
494 wd->frm = edje_object_add(e);
495 _elm_theme_object_set(obj, wd->frm, "photo", "base", "default");
496 elm_widget_resize_object_set(obj, wd->frm);
497
498 wd->img = _els_smart_icon_add(e);
499 _els_smart_icon_scale_up_set(wd->img, 1);
500 _els_smart_icon_scale_down_set(wd->img, 1);
501 _els_smart_icon_smooth_scale_set(wd->img, 1);
502 _els_smart_icon_fill_inside_set(wd->img, 0);
503 _els_smart_icon_scale_size_set(wd->img, 0);
504 wd->fill = EINA_FALSE;
505 _els_smart_icon_scale_set(wd->img,
506 elm_widget_scale_get(obj) * _elm_config->scale);
507 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
508 _mouse_up, obj);
509 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
510 _mouse_down, obj);
511 evas_object_repeat_events_set(wd->img, 1);
512 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->img);
513 evas_object_show(wd->img);
514 elm_widget_sub_object_add(obj, wd->img);
515
516 wd->longtimer = NULL;
517
518 icon = _els_smart_icon_object_get(wd->img);
519 evas_object_event_callback_add(icon, EVAS_CALLBACK_MOVE,
520 _icon_move_resize, obj);
521 evas_object_event_callback_add(icon, EVAS_CALLBACK_RESIZE,
522 _icon_move_resize, obj);
523
524 evas_object_smart_callbacks_descriptions_set(obj, _signals);
525
526#ifdef HAVE_ELEMENTARY_ETHUMB
527 wd->thumb.id = -1;
528#endif
529
530 _mirrored_set(obj, elm_widget_mirrored_get(obj));
531 _sizing_eval(obj);
532 return obj;
533}
534
535EAPI Eina_Bool
536elm_photo_file_set(Evas_Object *obj, const char *file)
537{
538 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
539 Widget_Data *wd = elm_widget_data_get(obj);
540
541 if (!wd) return EINA_FALSE;
542 if (!_els_smart_icon_file_key_set(wd->img, file, NULL))
543 return EINA_FALSE;
544
545 _sizing_eval(obj);
546 return EINA_TRUE;
547}
548
549EAPI void
550elm_photo_size_set(Evas_Object *obj, int size)
551{
552 ELM_CHECK_WIDTYPE(obj, widtype);
553 Widget_Data *wd = elm_widget_data_get(obj);
554
555 if (!wd) return;
556 wd->size = (size > 0) ? size : 0;
557
558 _els_smart_icon_scale_size_set(wd->img, wd->size);
559
560 _sizing_eval(obj);
561}
562
563EAPI void
564elm_photo_fill_inside_set(Evas_Object *obj, Eina_Bool fill)
565{
566 ELM_CHECK_WIDTYPE(obj, widtype);
567 Widget_Data *wd = elm_widget_data_get(obj);
568
569 if (!wd) return;
570 _els_smart_icon_fill_inside_set(wd->img, fill);
571 wd->fill = fill;
572 _sizing_eval(obj);
573}
574
575EAPI void
576elm_photo_editable_set(Evas_Object *obj, Eina_Bool set)
577{
578 ELM_CHECK_WIDTYPE(obj, widtype);
579 Widget_Data *wd = elm_widget_data_get(obj);
580
581 if (!wd) return;;
582 _els_smart_icon_edit_set(wd->img, set, obj);
583}
584
585EAPI void
586elm_photo_thumb_set(const Evas_Object *obj, const char *file, const char *group)
587{
588 ELM_CHECK_WIDTYPE(obj, widtype);
589 Widget_Data *wd = elm_widget_data_get(obj);
590 if (!wd) return;
591
592#ifdef HAVE_ELEMENTARY_ETHUMB
593 eina_stringshare_replace(&wd->thumb.file.path, file);
594 eina_stringshare_replace(&wd->thumb.file.key, group);
595
596 if (elm_thumb_ethumb_client_connected_get())
597 {
598 _icon_thumb_apply(wd);
599 return ;
600 }
601
602 if (!wd->thumb.eeh)
603 {
604 wd->thumb.eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, _icon_thumb_apply_cb, wd);
605 }
606#else
607 (void) obj;
608 (void) file;
609 (void) group;
610#endif
611}
612
613EAPI void
614elm_photo_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed)
615{
616 ELM_CHECK_WIDTYPE(obj, widtype);
617 Widget_Data *wd = elm_widget_data_get(obj);
618 if (!wd) return;
619 return _els_smart_icon_aspect_fixed_set(wd->img, fixed);
620}
621
622EAPI Eina_Bool
623elm_photo_aspect_fixed_get(const Evas_Object *obj)
624{
625 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
626 Widget_Data *wd = elm_widget_data_get(obj);
627 if (!wd) return EINA_FALSE;
628 return _els_smart_icon_aspect_fixed_get(wd->img);
629}
630
631
632
633/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/elm_photo.h b/libraries/elementary/src/lib/elm_photo.h
new file mode 100644
index 0000000..b5e9d78
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_photo.h
@@ -0,0 +1,113 @@
1/**
2 * @defgroup Photo Photo
3 * @ingroup Elementary
4 *
5 * For displaying a photo, for ex., a person (contact). Simple, yet
6 * with a very specific purpose.
7 *
8 * Signals that you can add callbacks for are:
9 *
10 * "clicked" - This is called when a user has clicked the photo
11 * "drag,start" - dragging the image out of the photo object
12 * "drag,end" - Drop the dragged item
13 *
14 * @{
15 */
16
17/**
18 * Add a new photo to the parent
19 *
20 * @param parent The parent object
21 * @return The new object or NULL if it cannot be created
22 *
23 * @ingroup Photo
24 */
25EAPI Evas_Object *elm_photo_add(Evas_Object *parent);
26
27/**
28 * Set the file that will be used as photo
29 *
30 * @param obj The photo object
31 * @param file The path to file that will be used as photo
32 *
33 * @return (1 = success, 0 = error)
34 *
35 * @ingroup Photo
36 */
37EAPI Eina_Bool elm_photo_file_set(Evas_Object *obj, const char *file);
38
39/**
40 * Set the file that will be used as thumbnail in the photo.
41 *
42 * @param obj The photo object.
43 * @param file The path to file that will be used as thumbnail.
44 * @param group The key used in case of an EET file.
45 *
46 * @ingroup Photo
47 */
48EAPI void elm_photo_thumb_set(const Evas_Object *obj, const char *file, const char *group);
49
50/**
51 * Set the size that will be used on the photo
52 *
53 * @param obj The photo object
54 * @param size The size of the photo
55 *
56 * @ingroup Photo
57 */
58EAPI void elm_photo_size_set(Evas_Object *obj, int size);
59
60/**
61 * Set if the photo should be completely visible or not.
62 *
63 * @param obj The photo object
64 * @param fill if true the photo will be completely visible
65 *
66 * @ingroup Photo
67 */
68EAPI void elm_photo_fill_inside_set(Evas_Object *obj, Eina_Bool fill);
69
70/**
71 * Set editability of the photo.
72 *
73 * An editable photo can be dragged to or from, and can be cut or
74 * pasted too. Note that pasting an image or dropping an item on
75 * the image will delete the existing content.
76 *
77 * @param obj The photo object.
78 * @param set To set of clear editability.
79 */
80EAPI void elm_photo_editable_set(Evas_Object *obj, Eina_Bool set);
81
82/**
83 * Set whether the original aspect ratio of the photo should be kept on resize.
84 *
85 * @param obj The photo object.
86 * @param fixed @c EINA_TRUE if the photo should fix the aspect,
87 * @c EINA_FALSE otherwise.
88 *
89 * The original aspect ratio (width / height) of the photo is usually
90 * distorted to match the object's size. Enabling this option will fix
91 * this original aspect, and the way that the photo is fit into
92 * the object's area
93 *
94 * @see elm_photo_aspect_fixed_get()
95 *
96 * @ingroup Photo
97 */
98EAPI void elm_photo_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed);
99
100/**
101 * Get if the object keeps the original aspect ratio.
102 *
103 * @param obj The photo object.
104 * @return @c EINA_TRUE if the object keeps the original aspect, @c EINA_FALSE
105 * otherwise.
106 *
107 * @ingroup Photo
108 */
109EAPI Eina_Bool elm_photo_aspect_fixed_get(const Evas_Object *obj);
110
111/**
112 * @}
113 */
diff --git a/libraries/elementary/src/lib/elm_photocam.c b/libraries/elementary/src/lib/elm_photocam.c
new file mode 100644
index 0000000..021ddcf
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_photocam.c
@@ -0,0 +1,1962 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4
5/*
6 * TODO (maybe - optional future stuff):
7 *
8 * 1. wrap photo in theme edje so u can have styling around photo (like white
9 * photo bordering).
10 * 2. exif handling
11 * 3. rotation flags in exif handling (nasty! should have rot in evas)
12 */
13
14typedef struct _Widget_Data Widget_Data;
15typedef struct _Pan Pan;
16typedef struct _Grid Grid;
17typedef struct _Grid_Item Grid_Item;
18
19struct _Grid_Item
20{
21 Widget_Data *wd;
22 Evas_Object *img;
23 struct
24 {
25 int x, y, w, h;
26 } src, out;
27 Eina_Bool want : 1;
28 Eina_Bool have : 1;
29};
30
31struct _Grid
32{
33 int tsize; // size of tile (tsize x tsize pixels)
34 int zoom; // zoom level tiles want for optimal display (1, 2, 4, 8)
35 int iw, ih; // size of image in pixels
36 int w, h; // size of grid image in pixels (represented by grid)
37 int gw, gh; // size of grid in tiles
38 Grid_Item *grid; // the grid (gw * gh items)
39 Eina_Bool dead : 1; // old grid. will die as soon as anim is over
40};
41
42struct _Widget_Data
43{
44 Evas_Object *obj;
45 Evas_Object *scr;
46 Evas_Object *pan_smart;
47 Evas_Object *gest;
48 double gest_start;
49
50 Pan *pan;
51 Evas_Coord pan_x, pan_y, minw, minh;
52
53 double zoom;
54 Elm_Photocam_Zoom_Mode mode;
55 Evas_Coord pvx, pvy, px, py, zoom_point_x, zoom_point_y;
56 struct
57 {
58 int imx, imy;
59 struct
60 {
61 int x_start, y_start;
62 int x_end, y_end;
63 double t_start;
64 double t_end;
65 Ecore_Animator *animator;
66 } bounce;
67 } gzoom;
68 const char *file;
69
70 Ecore_Job *calc_job;
71 Ecore_Timer *scr_timer;
72 Ecore_Timer *long_timer;
73 Ecore_Animator *zoom_animator;
74 double t_start, t_end;
75 struct
76 {
77 int imw, imh;
78 int w, h;
79 int ow, oh, nw, nh;
80 struct
81 {
82 double x, y;
83 } spos;
84 } size;
85 struct
86 {
87 Eina_Bool show : 1;
88 Evas_Coord x, y ,w ,h;
89 } show;
90 int tsize;
91 Evas_Object *img; // low res version of image (scale down == 8)
92 int nosmooth;
93 int preload_num;
94 Eina_List *grids;
95 Eina_Bool main_load_pending : 1;
96 Eina_Bool resized : 1;
97 Eina_Bool longpressed : 1;
98 Eina_Bool on_hold : 1;
99 Eina_Bool paused : 1;
100 Eina_Bool do_region : 1;
101 Eina_Bool do_gesture : 1;
102 Eina_Bool zoom_gest : 1;
103};
104
105struct _Pan
106{
107 Evas_Object_Smart_Clipped_Data __clipped_data;
108 Widget_Data *wd;
109};
110
111static const char *widtype = NULL;
112static void _del_hook(Evas_Object *obj);
113static void _theme_hook(Evas_Object *obj);
114static void _on_focus_hook(void *data, Evas_Object *obj);
115//static void _show_region_hook(void *data, Evas_Object *obj);
116static void _sizing_eval(Evas_Object *obj);
117static void _calc_job(void *data);
118static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
119 Evas_Callback_Type type, void *event_info);
120static 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);
121static void grid_clear(Evas_Object *obj, Grid *g);
122static Grid *grid_create(Evas_Object *obj);
123static void grid_load(Evas_Object *obj, Grid *g);
124
125static const char SIG_CLICKED[] = "clicked";
126static const char SIG_PRESS[] = "press";
127static const char SIG_LONGPRESSED[] = "longpressed";
128static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
129static const char SIG_LOAD[] = "load";
130static const char SIG_LOADED[] = "loaded";
131static const char SIG_LOAD_DETAIL[] = "load,detail";
132static const char SIG_LOADED_DETAIL[] = "loaded,detail";
133static const char SIG_ZOOM_START[] = "zoom,start";
134static const char SIG_ZOOM_STOP[] = "zoom,stop";
135static const char SIG_ZOOM_CHANGE[] = "zoom,change";
136static const char SIG_SCROLL[] = "scroll";
137static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
138static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
139static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
140static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
141
142static const Evas_Smart_Cb_Description _signals[] = {
143 {SIG_CLICKED, ""},
144 {SIG_PRESS, ""},
145 {SIG_LONGPRESSED, ""},
146 {SIG_CLICKED_DOUBLE, ""},
147 {SIG_LOAD, ""},
148 {SIG_LOADED, ""},
149 {SIG_LOAD_DETAIL, ""},
150 {SIG_LOADED_DETAIL, ""},
151 {SIG_ZOOM_START, ""},
152 {SIG_ZOOM_STOP, ""},
153 {SIG_ZOOM_CHANGE, ""},
154 {SIG_SCROLL, ""},
155 {SIG_SCROLL_ANIM_START, ""},
156 {SIG_SCROLL_ANIM_STOP, ""},
157 {SIG_SCROLL_DRAG_START, ""},
158 {SIG_SCROLL_DRAG_STOP, ""},
159 {NULL, NULL}
160};
161
162
163static int
164nearest_pow2(int num)
165{
166 unsigned int n = num - 1;
167 n |= n >> 1;
168 n |= n >> 2;
169 n |= n >> 4;
170 n |= n >> 8;
171 n |= n >> 16;
172 return n + 1;
173}
174
175static void
176img_place(Evas_Object *obj, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
177{
178 Widget_Data *wd = elm_widget_data_get(obj);
179 Evas_Coord ax, ay, gw, gh;
180 if (!wd) return;
181 ax = 0;
182 ay = 0;
183 gw = wd->size.w;
184 gh = wd->size.h;
185 if (!wd->zoom_gest)
186 {
187 if (ow > gw) ax = (ow - gw) / 2;
188 if (oh > gh) ay = (oh - gh) / 2;
189 }
190 evas_object_move(wd->img, ox + 0 - px + ax, oy + 0 - py + ay);
191 evas_object_resize(wd->img, gw, gh);
192
193 if (wd->show.show)
194 {
195 wd->show.show = EINA_FALSE;
196 elm_smart_scroller_child_region_show(wd->scr, wd->show.x, wd->show.y, wd->show.w, wd->show.h);
197 }
198}
199
200static void
201grid_place(Evas_Object *obj, Grid *g, Evas_Coord px, Evas_Coord py, Evas_Coord ox, Evas_Coord oy, Evas_Coord ow, Evas_Coord oh)
202{
203 Widget_Data *wd = elm_widget_data_get(obj);
204 Evas_Coord ax, ay, gw, gh, tx, ty;
205 int x, y;
206 if (!wd) return;
207 ax = 0;
208 ay = 0;
209 gw = wd->size.w;
210 gh = wd->size.h;
211 if (!wd->zoom_gest)
212 {
213 if (ow > gw) ax = (ow - gw) / 2;
214 if (oh > gh) ay = (oh - gh) / 2;
215 }
216 for (y = 0; y < g->gh; y++)
217 {
218 for (x = 0; x < g->gw; x++)
219 {
220 int tn, xx, yy, ww, hh;
221
222 tn = (y * g->gw) + x;
223 xx = g->grid[tn].out.x;
224 yy = g->grid[tn].out.y;
225 ww = g->grid[tn].out.w;
226 hh = g->grid[tn].out.h;
227 if ((gw != g->w) && (g->w > 0))
228 {
229 tx = xx;
230 xx = (gw * xx) / g->w;
231 ww = ((gw * (tx + ww)) / g->w) - xx;
232 }
233 if ((gh != g->h) && (g->h > 0))
234 {
235 ty = yy;
236 yy = (gh * yy) / g->h;
237 hh = ((gh * (ty + hh)) / g->h) - yy;
238 }
239 evas_object_move(g->grid[tn].img,
240 ox + xx - px + ax,
241 oy + yy - py + ay);
242 evas_object_resize(g->grid[tn].img, ww, hh);
243 }
244 }
245}
246
247static void
248grid_clear(Evas_Object *obj, Grid *g)
249{
250 Widget_Data *wd = elm_widget_data_get(obj);
251 int x, y;
252 if (!wd) return;
253 if (!g->grid) return;
254 for (y = 0; y < g->gh; y++)
255 {
256 for (x = 0; x < g->gw; x++)
257 {
258 int tn;
259
260 tn = (y * g->gw) + x;
261 evas_object_del(g->grid[tn].img);
262 if (g->grid[tn].want)
263 {
264 wd->preload_num--;
265 if (!wd->preload_num)
266 {
267 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
268 "elm,state,busy,stop", "elm");
269 evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
270 }
271 }
272 }
273 }
274 free(g->grid);
275 g->grid = NULL;
276 g->gw = 0;
277 g->gh = 0;
278}
279
280static void
281_tile_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
282{
283 Grid_Item *git = data;
284
285 if (git->want)
286 {
287 git->want = 0;
288 evas_object_show(git->img);
289 git->have = 1;
290 git->wd->preload_num--;
291 if (!git->wd->preload_num)
292 {
293 edje_object_signal_emit(elm_smart_scroller_edje_object_get(git->wd->scr),
294 "elm,state,busy,stop", "elm");
295 evas_object_smart_callback_call(git->wd->obj, SIG_LOADED_DETAIL, NULL);
296 }
297 }
298}
299
300static int
301grid_zoom_calc(double zoom)
302{
303 int z = zoom;
304 if (z < 1) z = 1;
305 return nearest_pow2(z);
306}
307
308static Grid *
309grid_create(Evas_Object *obj)
310{
311 Widget_Data *wd = elm_widget_data_get(obj);
312 int x, y;
313 Grid *g;
314
315 if (!wd) return NULL;
316 g = calloc(1, sizeof(Grid));
317 if (!g) return NULL;
318
319 g->zoom = grid_zoom_calc(wd->zoom);
320 g->tsize = wd->tsize;
321 g->iw = wd->size.imw;
322 g->ih = wd->size.imh;
323
324 g->w = g->iw / g->zoom;
325 g->h = g->ih / g->zoom;
326 if (g->zoom >= 8)
327 {
328 free(g);
329 return NULL;
330 }
331 if (wd->do_region)
332 {
333 g->gw = (g->w + g->tsize - 1) / g->tsize;
334 g->gh = (g->h + g->tsize - 1) / g->tsize;
335 }
336 else
337 {
338 g->gw = 1;
339 g->gh = 1;
340 }
341 g->grid = calloc(1, sizeof(Grid_Item) * g->gw * g->gh);
342 if (!g->grid)
343 {
344 g->gw = 0;
345 g->gh = 0;
346 return g;
347 }
348 for (y = 0; y < g->gh; y++)
349 {
350 for (x = 0; x < g->gw; x++)
351 {
352 int tn;
353
354 tn = (y * g->gw) + x;
355 g->grid[tn].src.x = x * g->tsize;
356 if (x == (g->gw - 1))
357 g->grid[tn].src.w = g->w - ((g->gw - 1) * g->tsize);
358 else
359 g->grid[tn].src.w = g->tsize;
360 g->grid[tn].src.y = y * g->tsize;
361 if (y == (g->gh - 1))
362 g->grid[tn].src.h = g->h - ((g->gh - 1) * g->tsize);
363 else
364 g->grid[tn].src.h = g->tsize;
365
366 g->grid[tn].out.x = g->grid[tn].src.x;
367 g->grid[tn].out.y = g->grid[tn].src.y;
368 g->grid[tn].out.w = g->grid[tn].src.w;
369 g->grid[tn].out.h = g->grid[tn].src.h;
370
371 g->grid[tn].wd = wd;
372 g->grid[tn].img =
373 evas_object_image_add(evas_object_evas_get(obj));
374 evas_object_image_load_orientation_set(g->grid[tn].img, EINA_TRUE);
375 evas_object_image_scale_hint_set
376 (g->grid[tn].img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
377 evas_object_pass_events_set(g->grid[tn].img, EINA_TRUE);
378 evas_object_smart_member_add(g->grid[tn].img,
379 wd->pan_smart);
380 elm_widget_sub_object_add(obj, g->grid[tn].img);
381 evas_object_image_filled_set(g->grid[tn].img, 1);
382 evas_object_event_callback_add(g->grid[tn].img,
383 EVAS_CALLBACK_IMAGE_PRELOADED,
384 _tile_preloaded,
385 &(g->grid[tn]));
386 }
387 }
388 return g;
389}
390
391static void
392grid_load(Evas_Object *obj, Grid *g)
393{
394 Widget_Data *wd = elm_widget_data_get(obj);
395 int x, y;
396 Evas_Coord ox, oy, ow, oh, cvx, cvy, cvw, cvh, gw, gh, tx, ty;
397 if (!wd) return;
398 evas_object_geometry_get(wd->pan_smart, &ox, &oy, &ow, &oh);
399 evas_output_viewport_get(evas_object_evas_get(wd->obj), &cvx, &cvy, &cvw, &cvh);
400 gw = wd->size.w;
401 gh = wd->size.h;
402 for (y = 0; y < g->gh; y++)
403 {
404 for (x = 0; x < g->gw; x++)
405 {
406 int tn, xx, yy, ww, hh;
407 Eina_Bool visible = EINA_FALSE;
408
409 tn = (y * g->gw) + x;
410 xx = g->grid[tn].out.x;
411 yy = g->grid[tn].out.y;
412 ww = g->grid[tn].out.w;
413 hh = g->grid[tn].out.h;
414 if ((gw != g->w) && (g->w > 0))
415 {
416 tx = xx;
417 xx = (gw * xx) / g->w;
418 ww = ((gw * (tx + ww)) / g->w) - xx;
419 }
420 if ((gh != g->h) && (g->h > 0))
421 {
422 ty = yy;
423 yy = (gh * yy) / g->h;
424 hh = ((gh * (ty + hh)) / g->h) - yy;
425 }
426 if (ELM_RECTS_INTERSECT(xx - wd->pan_x + ox,
427 yy - wd->pan_y + oy,
428 ww, hh,
429 cvx, cvy, cvw, cvh))
430 visible = 1;
431 if ((visible) && (!g->grid[tn].have) && (!g->grid[tn].want))
432 {
433 g->grid[tn].want = 1;
434 evas_object_hide(g->grid[tn].img);
435 evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
436 evas_object_image_load_scale_down_set(g->grid[tn].img, g->zoom);
437 evas_object_image_load_region_set(g->grid[tn].img,
438 g->grid[tn].src.x,
439 g->grid[tn].src.y,
440 g->grid[tn].src.w,
441 g->grid[tn].src.h);
442 evas_object_image_file_set(g->grid[tn].img, wd->file, NULL);
443 evas_object_image_preload(g->grid[tn].img, 0);
444 wd->preload_num++;
445 if (wd->preload_num == 1)
446 {
447 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
448 "elm,state,busy,start", "elm");
449 evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
450 }
451 }
452 else if ((g->grid[tn].want) && (!visible))
453 {
454 wd->preload_num--;
455 if (!wd->preload_num)
456 {
457 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
458 "elm,state,busy,stop", "elm");
459 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
460 }
461 g->grid[tn].want = 0;
462 evas_object_hide(g->grid[tn].img);
463 evas_object_image_preload(g->grid[tn].img, 1);
464 evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
465 }
466 else if ((g->grid[tn].have) && (!visible))
467 {
468 g->grid[tn].have = 0;
469 evas_object_hide(g->grid[tn].img);
470 evas_object_image_preload(g->grid[tn].img, 1);
471 evas_object_image_file_set(g->grid[tn].img, NULL, NULL);
472 }
473 }
474 }
475}
476
477static void
478grid_clearall(Evas_Object *obj)
479{
480 Widget_Data *wd = elm_widget_data_get(obj);
481 Grid *g;
482 if (!wd) return;
483 EINA_LIST_FREE(wd->grids, g)
484 {
485 grid_clear(obj, g);
486 free(g);
487 }
488}
489
490static void
491_smooth_update(Evas_Object *obj)
492{
493 Widget_Data *wd = elm_widget_data_get(obj);
494 int x, y;
495 Eina_List *l;
496 Grid *g;
497 if (!wd) return;
498 EINA_LIST_FOREACH(wd->grids, l, g)
499 {
500 for (y = 0; y < g->gh; y++)
501 {
502 for (x = 0; x < g->gw; x++)
503 {
504 int tn;
505
506 tn = (y * g->gw) + x;
507 evas_object_image_smooth_scale_set(g->grid[tn].img, (!wd->nosmooth));
508 }
509 }
510 }
511 evas_object_image_smooth_scale_set(wd->img, (!wd->nosmooth));
512}
513
514static void
515_grid_raise(Grid *g)
516{
517 int x, y;
518
519 for (y = 0; y < g->gh; y++)
520 {
521 for (x = 0; x < g->gw; x++)
522 {
523 int tn;
524
525 tn = (y * g->gw) + x;
526 evas_object_raise(g->grid[tn].img);
527 }
528 }
529}
530
531static Eina_Bool
532_scr_timeout(void *data)
533{
534 Widget_Data *wd = elm_widget_data_get(data);
535 if (!wd) return ECORE_CALLBACK_CANCEL;
536 wd->nosmooth--;
537 if (!wd->nosmooth) _smooth_update(data);
538 wd->scr_timer = NULL;
539 return ECORE_CALLBACK_CANCEL;
540}
541
542static void
543_scr(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
544{
545 Widget_Data *wd = elm_widget_data_get(data);
546 if (!wd) return;
547 if (!wd->scr_timer)
548 {
549 wd->nosmooth++;
550 if (wd->nosmooth == 1) _smooth_update(data);
551 }
552 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
553 wd->scr_timer = ecore_timer_add(0.5, _scr_timeout, data);
554}
555
556static void
557_main_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event_info __UNUSED__)
558{
559 Evas_Object *obj = data;
560 Widget_Data *wd = elm_widget_data_get(obj);
561 Grid *g;
562 if (!wd) return;
563 evas_object_show(wd->img);
564 wd->main_load_pending = 0;
565 g = grid_create(obj);
566 if (g)
567 {
568 wd->grids = eina_list_prepend(wd->grids, g);
569 grid_load(wd->obj, g);
570 }
571 if (wd->calc_job) ecore_job_del(wd->calc_job);
572 wd->calc_job = ecore_job_add(_calc_job, wd);
573 evas_object_smart_callback_call(data, SIG_LOADED, NULL);
574 wd->preload_num--;
575 if (!wd->preload_num)
576 {
577 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
578 "elm,state,busy,stop", "elm");
579 evas_object_smart_callback_call(obj, SIG_LOADED_DETAIL, NULL);
580 }
581}
582
583static Eina_Bool
584zoom_do(Evas_Object *obj, double t)
585{
586 Widget_Data *wd = elm_widget_data_get(obj);
587 Evas_Coord xx, yy, ow, oh;
588 if (!wd) return ECORE_CALLBACK_CANCEL;
589 wd->size.w = (wd->size.ow * (1.0 - t)) + (wd->size.nw * t);
590 wd->size.h = (wd->size.oh * (1.0 - t)) + (wd->size.nh * t);
591 elm_smart_scroller_child_viewport_size_get(wd->scr, &ow, &oh);
592 xx = (wd->size.spos.x * wd->size.w) - (ow / 2);
593 yy = (wd->size.spos.y * wd->size.h) - (oh / 2);
594 if (xx < 0) xx = 0;
595 else if (xx > (wd->size.w - ow)) xx = wd->size.w - ow;
596 if (yy < 0) yy = 0;
597 else if (yy > (wd->size.h - oh)) yy = wd->size.h - oh;
598
599 wd->show.show = EINA_TRUE;
600 wd->show.x = xx;
601 wd->show.y = yy;
602 wd->show.w = ow;
603 wd->show.h = oh;
604
605 if (wd->calc_job) ecore_job_del(wd->calc_job);
606 wd->calc_job = ecore_job_add(_calc_job, wd);
607 if (t >= 1.0)
608 {
609 Eina_List *l, *l_next;
610 Grid *g;
611
612 EINA_LIST_FOREACH_SAFE(wd->grids, l, l_next, g)
613 {
614 if (g->dead)
615 {
616 wd->grids = eina_list_remove_list(wd->grids, l);
617 grid_clear(obj, g);
618 free(g);
619 }
620 }
621 return ECORE_CALLBACK_CANCEL;
622 }
623 return ECORE_CALLBACK_RENEW;
624}
625
626
627static Eina_Bool
628_zoom_anim(void *data)
629{
630 Evas_Object *obj = data;
631 Widget_Data *wd = elm_widget_data_get(obj);
632 double t;
633 Eina_Bool go;
634 if (!wd) return ECORE_CALLBACK_CANCEL;
635 t = ecore_loop_time_get();
636 if (t >= wd->t_end)
637 t = 1.0;
638 else if (wd->t_end > wd->t_start)
639 t = (t - wd->t_start) / (wd->t_end - wd->t_start);
640 else
641 t = 1.0;
642 t = 1.0 - t;
643 t = 1.0 - (t * t);
644 go = zoom_do(obj, t);
645 if (!go)
646 {
647 wd->nosmooth--;
648 if (!wd->nosmooth) _smooth_update(data);
649 wd->zoom_animator = NULL;
650 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
651 }
652 return go;
653}
654
655static void
656_mouse_move(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
657{
658 Widget_Data *wd = elm_widget_data_get(data);
659 // Evas_Event_Mouse_Move *ev = event_info;
660 if (!wd) return;
661}
662
663static Eina_Bool
664_long_press(void *data)
665{
666 Widget_Data *wd = elm_widget_data_get(data);
667 if (!wd) return ECORE_CALLBACK_CANCEL;
668 wd->long_timer = NULL;
669 wd->longpressed = EINA_TRUE;
670 evas_object_smart_callback_call(data, SIG_LONGPRESSED, NULL);
671 return ECORE_CALLBACK_CANCEL;
672}
673
674static void
675_mouse_down(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
676{
677 Widget_Data *wd = elm_widget_data_get(data);
678 Evas_Event_Mouse_Down *ev = event_info;
679 if (!wd) return;
680 if (ev->button != 1) return;
681 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
682 else wd->on_hold = EINA_FALSE;
683 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
684 evas_object_smart_callback_call(data, SIG_CLICKED_DOUBLE, NULL);
685 else
686 evas_object_smart_callback_call(data, SIG_PRESS, NULL);
687 wd->longpressed = EINA_FALSE;
688 if (wd->long_timer) ecore_timer_del(wd->long_timer);
689 wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, _long_press, data);
690}
691
692static void
693_mouse_up(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
694{
695 Widget_Data *wd = elm_widget_data_get(data);
696 Evas_Event_Mouse_Up *ev = event_info;
697 if (!wd) return;
698 if (ev->button != 1) return;
699 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) wd->on_hold = EINA_TRUE;
700 else wd->on_hold = EINA_FALSE;
701 if (wd->long_timer)
702 {
703 ecore_timer_del(wd->long_timer);
704 wd->long_timer = NULL;
705 }
706 if (!wd->on_hold)
707 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
708 wd->on_hold = EINA_FALSE;
709}
710
711static Evas_Smart_Class _pan_sc = EVAS_SMART_CLASS_INIT_NULL;
712
713static void
714_del_hook(Evas_Object *obj)
715{
716 Widget_Data *wd = elm_widget_data_get(obj);
717 Grid *g;
718 if (!wd) return;
719 EINA_LIST_FREE(wd->grids, g)
720 {
721 if (g->grid) free(g->grid);
722 free(g);
723 }
724 evas_object_del(wd->pan_smart);
725 wd->pan_smart = NULL;
726 if (wd->file) eina_stringshare_del(wd->file);
727 if (wd->calc_job) ecore_job_del(wd->calc_job);
728 if (wd->scr_timer) ecore_timer_del(wd->scr_timer);
729 if (wd->zoom_animator) ecore_animator_del(wd->zoom_animator);
730 if (wd->gzoom.bounce.animator) ecore_animator_del(wd->gzoom.bounce.animator);
731 if (wd->long_timer) ecore_timer_del(wd->long_timer);
732 free(wd);
733}
734
735static void
736_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
737{
738 Widget_Data *wd = elm_widget_data_get(obj);
739 if (!wd) return;
740 if (elm_widget_focus_get(obj))
741 {
742 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm");
743 evas_object_focus_set(wd->obj, EINA_TRUE);
744 }
745 else
746 {
747 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm");
748 evas_object_focus_set(wd->obj, EINA_FALSE);
749 }
750}
751
752static void
753_theme_hook(Evas_Object *obj)
754{
755 Widget_Data *wd = elm_widget_data_get(obj);
756 if (!wd) return;
757 elm_smart_scroller_object_theme_set(obj, wd->scr, "photocam", "base", elm_widget_style_get(obj));
758 // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
759 _sizing_eval(obj);
760}
761
762/*
763static void
764_show_region_hook(void *data, Evas_Object *obj)
765{
766 Widget_Data *wd = elm_widget_data_get(data);
767 Evas_Coord x, y, w, h;
768 if (!wd) return;
769 elm_widget_show_region_get(obj, &x, &y, &w, &h);
770 elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
771}
772*/
773
774static void
775_sizing_eval(Evas_Object *obj)
776{
777 Widget_Data *wd = elm_widget_data_get(obj);
778 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
779 if (!wd) return;
780 // evas_object_size_hint_min_get(wd->scr, &minw, &minh);
781 evas_object_size_hint_max_get(wd->scr, &maxw, &maxh);
782 // minw = -1;
783 // minh = -1;
784 // if (wd->mode != ELM_LIST_LIMIT) minw = -1;
785 evas_object_size_hint_min_set(obj, minw, minh);
786 evas_object_size_hint_max_set(obj, maxw, maxh);
787}
788
789static void
790_calc_job(void *data)
791{
792 Widget_Data *wd = data;
793 Evas_Coord minw, minh;
794 if (!wd) return;
795 minw = wd->size.w;
796 minh = wd->size.h;
797 if (wd->resized)
798 {
799 wd->resized = 0;
800 if (wd->mode != ELM_PHOTOCAM_ZOOM_MODE_MANUAL)
801 {
802 double tz = wd->zoom;
803 wd->zoom = 0.0;
804 elm_photocam_zoom_set(wd->obj, tz);
805 }
806 }
807 if ((minw != wd->minw) || (minh != wd->minh))
808 {
809 wd->minw = minw;
810 wd->minh = minh;
811 evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
812 _sizing_eval(wd->obj);
813 }
814 wd->calc_job = NULL;
815 evas_object_smart_changed(wd->pan_smart);
816}
817
818static void
819_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
820{
821 Pan *sd = evas_object_smart_data_get(obj);
822 if (!sd) return;
823 if ((x == sd->wd->pan_x) && (y == sd->wd->pan_y)) return;
824 sd->wd->pan_x = x;
825 sd->wd->pan_y = y;
826 evas_object_smart_changed(obj);
827}
828
829static void
830_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
831{
832 Pan *sd = evas_object_smart_data_get(obj);
833 if (!sd) return;
834 if (x) *x = sd->wd->pan_x;
835 if (y) *y = sd->wd->pan_y;
836}
837
838static void
839_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
840{
841 Pan *sd = evas_object_smart_data_get(obj);
842 Evas_Coord ow, oh;
843 if (!sd) return;
844 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
845 ow = sd->wd->minw - ow;
846 if (ow < 0) ow = 0;
847 oh = sd->wd->minh - oh;
848 if (oh < 0) oh = 0;
849 if (x) *x = ow;
850 if (y) *y = oh;
851}
852
853static void
854_pan_min_get(Evas_Object *obj __UNUSED__, Evas_Coord *x, Evas_Coord *y)
855{
856 if (x) *x = 0;
857 if (y) *y = 0;
858}
859
860static void
861_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
862{
863 Pan *sd = evas_object_smart_data_get(obj);
864 if (!sd) return;
865 if (w) *w = sd->wd->minw;
866 if (h) *h = sd->wd->minh;
867}
868
869static void
870_pan_add(Evas_Object *obj)
871{
872 Pan *sd;
873 Evas_Object_Smart_Clipped_Data *cd;
874 _pan_sc.add(obj);
875 cd = evas_object_smart_data_get(obj);
876 if (!cd) return;
877 sd = calloc(1, sizeof(Pan));
878 if (!sd) return;
879 sd->__clipped_data = *cd;
880 free(cd);
881 evas_object_smart_data_set(obj, sd);
882}
883
884static void
885_pan_del(Evas_Object *obj)
886{
887 Pan *sd = evas_object_smart_data_get(obj);
888 if (!sd) return;
889 _pan_sc.del(obj);
890}
891
892static void
893_pan_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
894{
895 Pan *sd = evas_object_smart_data_get(obj);
896 Evas_Coord ow, oh;
897 if (!sd) return;
898 evas_object_geometry_get(obj, NULL, NULL, &ow, &oh);
899 if ((ow == w) && (oh == h)) return;
900 sd->wd->resized = 1;
901 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
902 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
903}
904
905static void
906_pan_calculate(Evas_Object *obj)
907{
908 Pan *sd = evas_object_smart_data_get(obj);
909 Evas_Coord ox, oy, ow, oh;
910 Eina_List *l;
911 Grid *g;
912 if (!sd) return;
913 evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
914 img_place(sd->wd->obj, sd->wd->pan_x, sd->wd->pan_y,
915 ox - sd->wd->gzoom.imx, oy - sd->wd->gzoom.imy, ow, oh);
916 EINA_LIST_FOREACH(sd->wd->grids, l, g)
917 {
918 grid_load(sd->wd->obj, g);
919 grid_place(sd->wd->obj, g, sd->wd->pan_x, sd->wd->pan_y,
920 ox - sd->wd->gzoom.imx, oy - sd->wd->gzoom.imy, ow, oh);
921 }
922}
923
924static void
925_pan_move(Evas_Object *obj, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
926{
927 Pan *sd = evas_object_smart_data_get(obj);
928 if (!sd) return;
929 if (sd->wd->calc_job) ecore_job_del(sd->wd->calc_job);
930 sd->wd->calc_job = ecore_job_add(_calc_job, sd->wd);
931}
932
933static void
934_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
935{
936 Widget_Data *wd = elm_widget_data_get(obj);
937 if (!wd) return;
938 elm_smart_scroller_hold_set(wd->scr, 1);
939}
940
941static void
942_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
943{
944 Widget_Data *wd = elm_widget_data_get(obj);
945 if (!wd) return;
946 elm_smart_scroller_hold_set(wd->scr, 0);
947}
948
949static void
950_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
951{
952 Widget_Data *wd = elm_widget_data_get(obj);
953 if (!wd) return;
954 elm_smart_scroller_freeze_set(wd->scr, 1);
955}
956
957static void
958_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
959{
960 Widget_Data *wd = elm_widget_data_get(obj);
961 if (!wd) return;
962 elm_smart_scroller_freeze_set(wd->scr, 0);
963}
964
965static void
966_scr_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
967{
968 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
969}
970
971static void
972_scr_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
973{
974 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
975}
976
977static void
978_scr_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
979{
980 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
981}
982
983static void
984_scr_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
985{
986 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
987}
988
989static void
990_scr_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
991{
992 evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
993}
994
995static Eina_Bool
996_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__,
997 Evas_Callback_Type type, void *event_info)
998{
999 double zoom;
1000 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
1001 Evas_Event_Key_Down *ev = event_info;
1002 Widget_Data *wd = elm_widget_data_get(obj);
1003 if (!wd) return EINA_FALSE;
1004 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
1005
1006 Evas_Coord x = 0;
1007 Evas_Coord y = 0;
1008 Evas_Coord step_x = 0;
1009 Evas_Coord step_y = 0;
1010 Evas_Coord v_w = 0;
1011 Evas_Coord v_h = 0;
1012 Evas_Coord page_x = 0;
1013 Evas_Coord page_y = 0;
1014
1015 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
1016 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
1017 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
1018 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
1019
1020 if ((!strcmp(ev->keyname, "Left")) ||
1021 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
1022 {
1023 x -= step_x;
1024 }
1025 else if ((!strcmp(ev->keyname, "Right")) ||
1026 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
1027 {
1028 x += step_x;
1029 }
1030 else if ((!strcmp(ev->keyname, "Up")) ||
1031 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
1032 {
1033 y -= step_y;
1034 }
1035 else if ((!strcmp(ev->keyname, "Down")) ||
1036 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
1037 {
1038 y += step_y;
1039 }
1040 else if ((!strcmp(ev->keyname, "Prior")) ||
1041 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
1042 {
1043 if (page_y < 0)
1044 y -= -(page_y * v_h) / 100;
1045 else
1046 y -= page_y;
1047 }
1048 else if ((!strcmp(ev->keyname, "Next")) ||
1049 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
1050 {
1051 if (page_y < 0)
1052 y += -(page_y * v_h) / 100;
1053 else
1054 y += page_y;
1055 }
1056 else if ((!strcmp(ev->keyname, "KP_Add")))
1057 {
1058 zoom = elm_photocam_zoom_get(obj);
1059 zoom -= 0.5;
1060 elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
1061 elm_photocam_zoom_set(obj, zoom);
1062 return EINA_TRUE;
1063 }
1064 else if ((!strcmp(ev->keyname, "KP_Subtract")))
1065 {
1066 zoom = elm_photocam_zoom_get(obj);
1067 zoom += 0.5;
1068 elm_photocam_zoom_mode_set(obj, ELM_PHOTOCAM_ZOOM_MODE_MANUAL);
1069 elm_photocam_zoom_set(obj, zoom);
1070 return EINA_TRUE;
1071 }
1072 else return EINA_FALSE;
1073
1074 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1075 elm_smart_scroller_child_pos_set(wd->scr, x, y);
1076
1077 return EINA_TRUE;
1078}
1079
1080Eina_Bool
1081_bounce_eval(void *_wd)
1082{
1083 Widget_Data *wd = (Widget_Data *)_wd;
1084 double t, tt;
1085
1086 if (!wd) return ECORE_CALLBACK_CANCEL;
1087 if ((wd->gzoom.imx == wd->gzoom.bounce.x_end) &&
1088 (wd->gzoom.imy == wd->gzoom.bounce.y_end))
1089 {
1090 wd->gzoom.imx = 0;
1091 wd->gzoom.imy = 0;
1092 wd->zoom_gest = EINA_FALSE;
1093 wd->gzoom.bounce.animator = NULL;
1094 _freeze_off(NULL, wd->obj, NULL);
1095 return ECORE_CALLBACK_CANCEL;
1096 }
1097
1098 t = ecore_loop_time_get();
1099 tt = (t - wd->gzoom.bounce.t_start) / (wd->gzoom.bounce.t_end - wd->gzoom.bounce.t_start);
1100 tt = 1.0 - tt;
1101 tt = 1.0 - (tt * tt);
1102
1103 if (t > wd->gzoom.bounce.t_end)
1104 {
1105 wd->gzoom.imx = 0;
1106 wd->gzoom.imy = 0;
1107 wd->zoom_gest = EINA_FALSE;
1108 _freeze_off(NULL, wd->obj, NULL);
1109 zoom_do(wd->obj, 1.0);
1110 wd->gzoom.bounce.animator = NULL;
1111 return ECORE_CALLBACK_CANCEL;
1112 }
1113
1114 if (wd->gzoom.imx != wd->gzoom.bounce.x_end)
1115 wd->gzoom.imx = wd->gzoom.bounce.x_start * (1.0 - tt) + wd->gzoom.bounce.x_end * tt;
1116
1117 if (wd->gzoom.imy != wd->gzoom.bounce.y_end)
1118 wd->gzoom.imy = wd->gzoom.bounce.y_start * (1.0 - tt) + wd->gzoom.bounce.y_end * tt;
1119
1120 zoom_do(wd->obj, 1.0 - (1.0 - tt));
1121 return ECORE_CALLBACK_RENEW;
1122}
1123
1124static void
1125_gzoom(Widget_Data *_wd, Evas_Coord px, Evas_Coord py, Elm_Gesture_Zoom_Info* gest)
1126{
1127 Widget_Data *wd = (Widget_Data *)_wd;
1128 Evas_Coord rx, ry, rw, rh;
1129 int regx, regy, regw, regh, ix, iy, iw, ih;
1130 int xx, yy;
1131
1132 if (!wd) return;
1133 wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
1134 wd->zoom = wd->gest_start / gest->zoom;
1135 wd->size.ow = wd->size.w;
1136 wd->size.oh = wd->size.h;
1137 elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
1138 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1139 if ((rw <= 0) || (rh <= 0)) return;
1140
1141 wd->size.nw = (double)wd->size.imw / wd->zoom;
1142 wd->size.nh = (double)wd->size.imh / wd->zoom;
1143
1144 elm_photocam_image_region_get(wd->obj, &regx, &regy, &regw, &regh);
1145 evas_object_geometry_get(wd->img, &ix, &iy, &iw, &ih);
1146
1147 wd->pvx = gest->x;
1148 wd->pvy = gest->y;
1149
1150 xx = (px / wd->zoom) - wd->pvx;
1151 yy = (py / wd->zoom) - wd->pvy;
1152 wd->gzoom.imx = 0;
1153 wd->gzoom.imy = 0;
1154
1155 if ((xx < 0) || (rw > wd->size.nw))
1156 {
1157 wd->gzoom.imx = xx;
1158 xx = 0;
1159 }
1160 else if ((xx + rw) > wd->size.nw)
1161 {
1162 wd->gzoom.imx = xx + rw - wd->size.nw;
1163 xx = wd->size.nw - rw;
1164 }
1165
1166 if ((yy < 0) || (rh > wd->size.nh))
1167 {
1168 wd->gzoom.imy = yy;
1169 yy = 0;
1170 }
1171 else if ((yy + rh) > wd->size.nh)
1172 {
1173 wd->gzoom.imy = yy + rh - wd->size.nh;
1174 yy = wd->size.nh - rh;
1175 }
1176
1177 wd->size.spos.x = (double)(xx + (rw / 2)) / (double)(wd->size.nw);
1178 wd->size.spos.y = (double)(yy + (rh / 2)) / (double)(wd->size.nh);
1179
1180 zoom_do(wd->obj, 1.0);
1181}
1182
1183static Evas_Event_Flags
1184_gzoom_start(void *_wd, void *event_info)
1185{
1186 Widget_Data *wd = (Widget_Data *)_wd;
1187 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
1188 Evas_Coord rw, rh;
1189 int x,y,w,h;
1190 double marginx = 0, marginy = 0;
1191
1192 if (wd->gzoom.bounce.animator)
1193 {
1194 ecore_animator_del(wd->gzoom.bounce.animator);
1195 wd->gzoom.bounce.animator = NULL;
1196 }
1197 wd->zoom_gest = EINA_TRUE;
1198 _freeze_on(NULL, wd->obj, NULL);
1199
1200 elm_photocam_image_region_get(wd->obj, &x, &y, &w, &h);
1201 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1202
1203 if (rw > wd->size.nw)
1204 marginx = (rw - wd->size.nw) / 2;
1205 if (rh > wd->size.nh)
1206 marginy = (rh - wd->size.nh) / 2;
1207
1208 wd->gest_start = wd->zoom;
1209
1210 wd->zoom_point_x = x + ((p->x - marginx) * wd->zoom) + wd->gzoom.imx;
1211 wd->zoom_point_y = y + ((p->y - marginy) * wd->zoom) + wd->gzoom.imy;
1212
1213 return EVAS_EVENT_FLAG_NONE;
1214}
1215
1216static Evas_Event_Flags
1217_gzoom_move(void *_wd, void *event_info)
1218{
1219 Widget_Data *wd = (Widget_Data *)_wd;
1220 Elm_Gesture_Zoom_Info *p = (Elm_Gesture_Zoom_Info *) event_info;
1221
1222 _gzoom(wd, wd->zoom_point_x, wd->zoom_point_y, p);
1223 return EVAS_EVENT_FLAG_NONE;
1224}
1225
1226static Evas_Event_Flags
1227_gzoom_end(void *_wd, void *event_info __UNUSED__)
1228{
1229 Widget_Data *wd = (Widget_Data *)_wd;
1230 Evas_Coord rw, rh;
1231
1232 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1233 wd->gest_start = 1.0;
1234
1235 if (wd->gzoom.imx || wd->gzoom.imy)
1236 {
1237 double t;
1238
1239 t = ecore_loop_time_get();
1240 wd->gzoom.bounce.x_start = wd->gzoom.imx;
1241 wd->gzoom.bounce.y_start = wd->gzoom.imy;
1242 wd->gzoom.bounce.x_end = 0;
1243 wd->gzoom.bounce.y_end = 0;
1244
1245 if (rw > wd->size.nw &&
1246 rh > wd->size.nh)
1247 {
1248 Evas_Coord pw, ph;
1249 double z;
1250
1251 if ((wd->size.imw < rw) && (wd->size.imh < rh))
1252 {
1253 wd->zoom = 1;
1254 wd->size.nw = wd->size.imw;
1255 wd->size.nh = wd->size.imh;
1256 }
1257 else
1258 {
1259 ph = (wd->size.imh * rw) / wd->size.imw;
1260 if (ph > rh)
1261 {
1262 pw = (wd->size.imw * rh) / wd->size.imh;
1263 ph = rh;
1264 }
1265 else
1266 {
1267 pw = rw;
1268 }
1269 if (wd->size.imw > wd->size.imh)
1270 z = (double)wd->size.imw / pw;
1271 else
1272 z = (double)wd->size.imh / ph;
1273
1274 wd->zoom = z;
1275 wd->size.nw = pw;
1276 wd->size.nh = ph;
1277 }
1278 wd->gzoom.bounce.x_end = (wd->size.nw - rw) / 2;
1279 wd->gzoom.bounce.y_end = (wd->size.nh - rh) / 2;
1280 }
1281 else
1282 {
1283 int xx, yy;
1284
1285 xx = (wd->zoom_point_x / wd->zoom) - wd->pvx;
1286 yy = (wd->zoom_point_y / wd->zoom) - wd->pvy;
1287
1288 if (xx < 0) xx = 0;
1289 if (yy < 0) yy = 0;
1290
1291 if (rw > wd->size.nw)
1292 wd->gzoom.bounce.x_end = (wd->size.nw -rw) / 2;
1293 if ((xx + rw) > wd->size.nw)
1294 xx = wd->size.nw - rw;
1295
1296 if (rh > wd->size.nh)
1297 wd->gzoom.bounce.y_end = (wd->size.nh - rh) / 2;
1298 if ((yy + rh) > wd->size.nh)
1299 yy = wd->size.nh - rh;
1300
1301 wd->size.spos.x = (double)(xx + (rw / 2)) / (double)(wd->size.nw);
1302 wd->size.spos.y = (double)(yy + (rh / 2)) / (double)(wd->size.nh);
1303 }
1304
1305 wd->gzoom.bounce.t_start = t;
1306 wd->gzoom.bounce.t_end = t + _elm_config->page_scroll_friction;
1307
1308 wd->gzoom.bounce.animator = ecore_animator_add(_bounce_eval, wd);
1309 }
1310 else
1311 {
1312 _freeze_off(NULL, wd->obj, NULL);
1313 wd->zoom_gest = EINA_FALSE;
1314 }
1315
1316 return EVAS_EVENT_FLAG_NONE;
1317}
1318
1319EAPI Evas_Object *
1320elm_photocam_add(Evas_Object *parent)
1321{
1322 Evas_Object *obj;
1323 Evas *e;
1324 Widget_Data *wd;
1325 Evas_Coord minw, minh;
1326 static Evas_Smart *smart = NULL;
1327 Eina_Bool bounce = _elm_config->thumbscroll_bounce_enable;
1328
1329 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1330
1331 ELM_SET_WIDTYPE(widtype, "photocam");
1332 elm_widget_type_set(obj, "photocam");
1333 elm_widget_sub_object_add(parent, obj);
1334 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1335 elm_widget_data_set(obj, wd);
1336 elm_widget_del_hook_set(obj, _del_hook);
1337 elm_widget_theme_hook_set(obj, _theme_hook);
1338 elm_widget_can_focus_set(obj, EINA_TRUE);
1339 elm_widget_event_hook_set(obj, _event_hook);
1340
1341 wd->scr = elm_smart_scroller_add(e);
1342 elm_smart_scroller_widget_set(wd->scr, obj);
1343 elm_smart_scroller_object_theme_set(obj, wd->scr, "photocam", "base", "default");
1344 evas_object_smart_callback_add(wd->scr, "scroll", _scr, obj);
1345 evas_object_smart_callback_add(wd->scr, "drag", _scr, obj);
1346 elm_widget_resize_object_set(obj, wd->scr);
1347
1348 evas_object_smart_callback_add(wd->scr, "animate,start", _scr_anim_start, obj);
1349 evas_object_smart_callback_add(wd->scr, "animate,stop", _scr_anim_stop, obj);
1350 evas_object_smart_callback_add(wd->scr, "drag,start", _scr_drag_start, obj);
1351 evas_object_smart_callback_add(wd->scr, "drag,stop", _scr_drag_stop, obj);
1352 evas_object_smart_callback_add(wd->scr, "scroll", _scr_scroll, obj);
1353
1354 elm_smart_scroller_bounce_allow_set(wd->scr, bounce, bounce);
1355
1356 wd->obj = obj;
1357
1358 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
1359 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
1360 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
1361 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
1362
1363 if (!smart)
1364 {
1365 static Evas_Smart_Class sc;
1366
1367 evas_object_smart_clipped_smart_set(&_pan_sc);
1368 sc = _pan_sc;
1369 sc.name = "elm_photocam_pan";
1370 sc.version = EVAS_SMART_CLASS_VERSION;
1371 sc.add = _pan_add;
1372 sc.del = _pan_del;
1373 sc.resize = _pan_resize;
1374 sc.move = _pan_move;
1375 sc.calculate = _pan_calculate;
1376 smart = evas_smart_class_new(&sc);
1377 }
1378 if (smart)
1379 {
1380 wd->pan_smart = evas_object_smart_add(e, smart);
1381 wd->pan = evas_object_smart_data_get(wd->pan_smart);
1382 wd->pan->wd = wd;
1383 }
1384
1385 elm_smart_scroller_extern_pan_set(wd->scr, wd->pan_smart,
1386 _pan_set, _pan_get, _pan_max_get,
1387 _pan_min_get, _pan_child_size_get);
1388
1389 wd->zoom_gest = EINA_FALSE;
1390 wd->gest_start = 1.0;
1391 wd->zoom = 1;
1392 wd->mode = ELM_PHOTOCAM_ZOOM_MODE_MANUAL;
1393 wd->tsize = 512;
1394
1395 wd->img = evas_object_image_add(e);
1396 evas_object_image_load_orientation_set(wd->img, EINA_TRUE);
1397 evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_DYNAMIC);
1398 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_DOWN,
1399 _mouse_down, obj);
1400 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
1401 _mouse_up, obj);
1402 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_MOVE,
1403 _mouse_move, obj);
1404 evas_object_image_scale_hint_set(wd->img, EVAS_IMAGE_SCALE_HINT_STATIC);
1405 evas_object_smart_member_add(wd->img, wd->pan_smart);
1406 elm_widget_sub_object_add(obj, wd->img);
1407 evas_object_image_filled_set(wd->img, 1);
1408 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_IMAGE_PRELOADED,
1409 _main_preloaded, obj);
1410
1411 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
1412 &minw, &minh);
1413 evas_object_size_hint_min_set(obj, minw, minh);
1414
1415 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1416
1417 _sizing_eval(obj);
1418 return obj;
1419}
1420
1421EAPI Evas_Load_Error
1422elm_photocam_file_set(Evas_Object *obj, const char *file)
1423{
1424 ELM_CHECK_WIDTYPE(obj, widtype) EVAS_LOAD_ERROR_NONE;
1425 Widget_Data *wd = elm_widget_data_get(obj);
1426 int w, h;
1427 if (!wd) return EVAS_LOAD_ERROR_GENERIC;
1428 if (!eina_stringshare_replace(&wd->file, file)) return EVAS_LOAD_ERROR_NONE;
1429 grid_clearall(obj);
1430
1431 evas_object_hide(wd->img);
1432 evas_object_image_smooth_scale_set(wd->img, (wd->nosmooth == 0));
1433 evas_object_image_file_set(wd->img, NULL, NULL);
1434 evas_object_image_load_scale_down_set(wd->img, 0);
1435 evas_object_image_file_set(wd->img, wd->file, NULL);
1436 evas_object_image_size_get(wd->img, &w, &h);
1437 wd->do_region = evas_object_image_region_support_get(wd->img);
1438 wd->size.imw = w;
1439 wd->size.imh = h;
1440 wd->size.w = wd->size.imw / wd->zoom;
1441 wd->size.h = wd->size.imh / wd->zoom;
1442 if (wd->gzoom.bounce.animator)
1443 {
1444 ecore_animator_del(wd->gzoom.bounce.animator);
1445 wd->gzoom.bounce.animator = NULL;
1446 }
1447 if (wd->zoom_animator)
1448 {
1449 wd->nosmooth--;
1450 if (wd->nosmooth == 0) _smooth_update(obj);
1451 ecore_animator_del(wd->zoom_animator);
1452 wd->zoom_animator = NULL;
1453 }
1454 evas_object_image_file_set(wd->img, NULL, NULL);
1455 evas_object_image_load_scale_down_set(wd->img, 8);
1456 evas_object_image_file_set(wd->img, wd->file, NULL);
1457 evas_object_image_preload(wd->img, 0);
1458 wd->main_load_pending = 1;
1459 if (wd->calc_job) ecore_job_del(wd->calc_job);
1460 wd->calc_job = ecore_job_add(_calc_job, wd);
1461 evas_object_smart_callback_call(obj, SIG_LOAD, NULL);
1462 wd->preload_num++;
1463 if (wd->preload_num == 1)
1464 {
1465 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
1466 "elm,state,busy,start", "elm");
1467 evas_object_smart_callback_call(obj, SIG_LOAD_DETAIL, NULL);
1468 }
1469 {
1470 double tz = wd->zoom;
1471 wd->zoom = 0.0;
1472 elm_photocam_zoom_set(wd->obj, tz);
1473 }
1474 return evas_object_image_load_error_get(wd->img);
1475}
1476
1477EAPI const char *
1478elm_photocam_file_get(const Evas_Object *obj)
1479{
1480 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1481 Widget_Data *wd = elm_widget_data_get(obj);
1482 if (!wd) return NULL;
1483 return wd->file;
1484}
1485
1486EAPI void
1487elm_photocam_zoom_set(Evas_Object *obj, double zoom)
1488{
1489 ELM_CHECK_WIDTYPE(obj, widtype);
1490 Widget_Data *wd = elm_widget_data_get(obj);
1491 Eina_List *l;
1492 Grid *g, *g_zoom = NULL;
1493 Evas_Coord pw, ph, rx, ry, rw, rh;
1494 double z;
1495 int zoom_changed = 0, started = 0;
1496 Ecore_Animator *an;
1497 if (!wd) return;
1498 if (zoom <= (1.0 / 256.0)) zoom = (1.0 / 256.0);
1499 if (zoom == wd->zoom) return;
1500 wd->zoom = zoom;
1501 wd->size.ow = wd->size.w;
1502 wd->size.oh = wd->size.h;
1503 elm_smart_scroller_child_pos_get(wd->scr, &rx, &ry);
1504 elm_smart_scroller_child_viewport_size_get(wd->scr, &rw, &rh);
1505 if ((rw <= 0) || (rh <= 0)) return;
1506
1507 if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_MANUAL)
1508 {
1509 wd->size.nw = (double)wd->size.imw / wd->zoom;
1510 wd->size.nh = (double)wd->size.imh / wd->zoom;
1511 }
1512 else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT)
1513 {
1514 if ((wd->size.imw < 1) || (wd->size.imh < 1))
1515 {
1516 wd->size.nw = 0;
1517 wd->size.nh = 0;
1518 }
1519 else
1520 {
1521 ph = (wd->size.imh * rw) / wd->size.imw;
1522 if (ph > rh)
1523 {
1524 pw = (wd->size.imw * rh) / wd->size.imh;
1525 ph = rh;
1526 }
1527 else
1528 {
1529 pw = rw;
1530 }
1531 if (wd->size.imw > wd->size.imh)
1532 z = (double)wd->size.imw / pw;
1533 else
1534 z = (double)wd->size.imh / ph;
1535 if (z != wd->zoom)
1536 zoom_changed = 1;
1537 wd->zoom = z;
1538 wd->size.nw = pw;
1539 wd->size.nh = ph;
1540 }
1541 }
1542 else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL)
1543 {
1544 if ((wd->size.imw < 1) || (wd->size.imh < 1))
1545 {
1546 wd->size.nw = 0;
1547 wd->size.nw = 0;
1548 }
1549 else
1550 {
1551 ph = (wd->size.imh * rw) / wd->size.imw;
1552 if (ph < rh)
1553 {
1554 pw = (wd->size.imw * rh) / wd->size.imh;
1555 ph = rh;
1556 }
1557 else
1558 {
1559 pw = rw;
1560 }
1561 if (wd->size.imw > wd->size.imh)
1562 z = (double)wd->size.imw / pw;
1563 else
1564 z = (double)wd->size.imh / ph;
1565 if (z != wd->zoom)
1566 zoom_changed = 1;
1567 wd->zoom = z;
1568 wd->size.nw = pw;
1569 wd->size.nh = ph;
1570 }
1571 }
1572 else if (wd->mode == ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT_IN)
1573 {
1574 if ((wd->size.imw < 1) || (wd->size.imh < 1))
1575 {
1576 wd->size.nw = 0;
1577 wd->size.nh = 0;
1578 }
1579 else if ((wd->size.imw < rw) && (wd->size.imh < rh))
1580 {
1581 if (1 != wd->zoom) zoom_changed = 1;
1582 wd->zoom = 1;
1583 wd->size.nw = wd->size.imw;
1584 wd->size.nh = wd->size.imh;
1585 }
1586 else
1587 {
1588 ph = (wd->size.imh * rw) / wd->size.imw;
1589 if (ph > rh)
1590 {
1591 pw = (wd->size.imw * rh) / wd->size.imh;
1592 ph = rh;
1593 }
1594 else
1595 pw = rw;
1596 if (wd->size.imw > wd->size.imh)
1597 z = (double)wd->size.imw / pw;
1598 else
1599 z = (double)wd->size.imh / ph;
1600 if (z != wd->zoom)
1601 zoom_changed = 1;
1602 wd->zoom = z;
1603 wd->size.nw = pw;
1604 wd->size.nh = ph;
1605 }
1606 }
1607 if (wd->main_load_pending)
1608 {
1609 wd->size.w = wd->size.nw;
1610 wd->size.h = wd->size.nh;
1611 goto done;
1612 }
1613 EINA_LIST_FOREACH(wd->grids, l, g)
1614 {
1615 if (g->zoom == grid_zoom_calc(wd->zoom))
1616 {
1617 wd->grids = eina_list_remove(wd->grids, g);
1618 wd->grids = eina_list_prepend(wd->grids, g);
1619 _grid_raise(g);
1620 goto done;
1621 }
1622 }
1623 g = grid_create(obj);
1624 if (g)
1625 {
1626 if (eina_list_count(wd->grids) > 1)
1627 {
1628 g_zoom = eina_list_last(wd->grids)->data;
1629 wd->grids = eina_list_remove(wd->grids, g_zoom);
1630 grid_clear(obj, g_zoom);
1631 free(g_zoom);
1632 EINA_LIST_FOREACH(wd->grids, l, g_zoom)
1633 {
1634 g_zoom->dead = 1;
1635 }
1636 }
1637 wd->grids = eina_list_prepend(wd->grids, g);
1638 }
1639 else
1640 {
1641 EINA_LIST_FREE(wd->grids, g)
1642 {
1643 grid_clear(obj, g);
1644 free(g);
1645 }
1646 }
1647 done:
1648 wd->t_start = ecore_loop_time_get();
1649 wd->t_end = wd->t_start + _elm_config->zoom_friction;
1650 if ((wd->size.w > 0) && (wd->size.h > 0))
1651 {
1652 wd->size.spos.x = (double)(rx + (rw / 2)) / (double)wd->size.w;
1653 wd->size.spos.y = (double)(ry + (rh / 2)) / (double)wd->size.h;
1654 }
1655 else
1656 {
1657 wd->size.spos.x = 0.5;
1658 wd->size.spos.y = 0.5;
1659 }
1660 if (rw > wd->size.w) wd->size.spos.x = 0.5;
1661 if (rh > wd->size.h) wd->size.spos.y = 0.5;
1662 if (wd->size.spos.x > 1.0) wd->size.spos.x = 1.0;
1663 if (wd->size.spos.y > 1.0) wd->size.spos.y = 1.0;
1664 if (wd->paused)
1665 {
1666 zoom_do(obj, 1.0);
1667 }
1668 else
1669 {
1670 if (!wd->zoom_animator)
1671 {
1672 wd->zoom_animator = ecore_animator_add(_zoom_anim, obj);
1673 wd->nosmooth++;
1674 if (wd->nosmooth == 1) _smooth_update(obj);
1675 started = 1;
1676 }
1677 }
1678 an = wd->zoom_animator;
1679 if (an)
1680 {
1681 if (!_zoom_anim(obj))
1682 {
1683 ecore_animator_del(an);
1684 an = NULL;
1685 }
1686 }
1687 if (wd->calc_job) ecore_job_del(wd->calc_job);
1688 wd->calc_job = ecore_job_add(_calc_job, wd);
1689 if (!wd->paused)
1690 {
1691 if (started)
1692 evas_object_smart_callback_call(obj, SIG_ZOOM_START, NULL);
1693 if (!an)
1694 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1695 }
1696 if (zoom_changed)
1697 evas_object_smart_callback_call(obj, SIG_ZOOM_CHANGE, NULL);
1698}
1699
1700EAPI double
1701elm_photocam_zoom_get(const Evas_Object *obj)
1702{
1703 ELM_CHECK_WIDTYPE(obj, widtype) 1.0;
1704 Widget_Data *wd = elm_widget_data_get(obj);
1705 if (!wd) return 1.0;
1706 return wd->zoom;
1707}
1708
1709EAPI void
1710elm_photocam_zoom_mode_set(Evas_Object *obj, Elm_Photocam_Zoom_Mode mode)
1711{
1712 ELM_CHECK_WIDTYPE(obj, widtype);
1713 Widget_Data *wd = elm_widget_data_get(obj);
1714 if (!wd) return;
1715 if (wd->mode == mode) return;
1716 wd->mode = mode;
1717 {
1718 double tz = wd->zoom;
1719 wd->zoom = 0.0;
1720 elm_photocam_zoom_set(wd->obj, tz);
1721 }
1722}
1723
1724EAPI Elm_Photocam_Zoom_Mode
1725elm_photocam_zoom_mode_get(const Evas_Object *obj)
1726{
1727 ELM_CHECK_WIDTYPE(obj, widtype) ELM_PHOTOCAM_ZOOM_MODE_LAST;
1728 Widget_Data *wd = elm_widget_data_get(obj);
1729 if (!wd) return ELM_PHOTOCAM_ZOOM_MODE_LAST;
1730 return wd->mode;
1731}
1732
1733EAPI void
1734elm_photocam_image_size_get(const Evas_Object *obj, int *w, int *h)
1735{
1736 ELM_CHECK_WIDTYPE(obj, widtype);
1737 Widget_Data *wd = elm_widget_data_get(obj);
1738 if (!wd) return;
1739 if (w) *w = wd->size.imw;
1740 if (h) *h = wd->size.imh;
1741}
1742
1743EAPI void
1744elm_photocam_image_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
1745{
1746 ELM_CHECK_WIDTYPE(obj, widtype);
1747 Widget_Data *wd = elm_widget_data_get(obj);
1748 Evas_Coord sx, sy, sw, sh;
1749 if (!wd) return;
1750 elm_smart_scroller_child_pos_get(wd->scr, &sx, &sy);
1751 elm_smart_scroller_child_viewport_size_get(wd->scr, &sw, &sh);
1752 if (wd->size.w > 0)
1753 {
1754 if (x)
1755 {
1756 *x = (wd->size.imw * sx) / wd->size.w;
1757 if (*x > wd->size.imw) *x = wd->size.imw;
1758 }
1759 if (w)
1760 {
1761 *w = (wd->size.imw * sw) / wd->size.w;
1762 if (*w > wd->size.imw) *w = wd->size.imw;
1763 else if (*w < 0) *w = 0;
1764 }
1765 }
1766 else
1767 {
1768 if (x) *x = 0;
1769 if (w) *w = 0;
1770 }
1771
1772 if (wd->size.h > 0)
1773 {
1774 if (y)
1775 {
1776 *y = (wd->size.imh * sy) / wd->size.h;
1777 if (*y > wd->size.imh) *y = wd->size.imh;
1778 }
1779 if (h)
1780 {
1781 *h = (wd->size.imh * sh) / wd->size.h;
1782 if (*h > wd->size.imh) *h = wd->size.imh;
1783 else if (*h < 0) *h = 0;
1784 }
1785 }
1786 else
1787 {
1788 if (y) *y = 0;
1789 if (h) *h = 0;
1790 }
1791}
1792
1793EAPI void
1794elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h __UNUSED__)
1795{
1796 ELM_CHECK_WIDTYPE(obj, widtype);
1797 Widget_Data *wd = elm_widget_data_get(obj);
1798 int rx, ry, rw, rh;
1799 if (!wd) return;
1800 if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
1801 rx = (x * wd->size.w) / wd->size.imw;
1802 ry = (y * wd->size.h) / wd->size.imh;
1803 rw = (w * wd->size.w) / wd->size.imw;
1804 rh = (h * wd->size.h) / wd->size.imh;
1805 if (rw < 1) rw = 1;
1806 if (rh < 1) rh = 1;
1807 if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
1808 if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
1809 if (wd->gzoom.bounce.animator)
1810 {
1811 ecore_animator_del(wd->gzoom.bounce.animator);
1812 wd->gzoom.bounce.animator = NULL;
1813 zoom_do(obj, 1.0);
1814 }
1815 if (wd->zoom_animator)
1816 {
1817 wd->nosmooth--;
1818 ecore_animator_del(wd->zoom_animator);
1819 wd->zoom_animator = NULL;
1820 zoom_do(obj, 1.0);
1821 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1822 }
1823 elm_smart_scroller_child_region_show(wd->scr, rx, ry, rw, rh);
1824}
1825
1826EAPI void
1827elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h __UNUSED__)
1828{
1829 ELM_CHECK_WIDTYPE(obj, widtype);
1830 Widget_Data *wd = elm_widget_data_get(obj);
1831 int rx, ry, rw, rh;
1832 if (!wd) return;
1833 if ((wd->size.imw < 1) || (wd->size.imh < 1)) return;
1834 rx = (x * wd->size.w) / wd->size.imw;
1835 ry = (y * wd->size.h) / wd->size.imh;
1836 rw = (w * wd->size.w) / wd->size.imw;
1837 rh = (h * wd->size.h) / wd->size.imh;
1838 if (rw < 1) rw = 1;
1839 if (rh < 1) rh = 1;
1840 if ((rx + rw) > wd->size.w) rx = wd->size.w - rw;
1841 if ((ry + rh) > wd->size.h) ry = wd->size.h - rh;
1842 if (wd->gzoom.bounce.animator)
1843 {
1844 ecore_animator_del(wd->gzoom.bounce.animator);
1845 wd->gzoom.bounce.animator = NULL;
1846 zoom_do(obj, 1.0);
1847 }
1848 if (wd->zoom_animator)
1849 {
1850 wd->nosmooth--;
1851 if (!wd->nosmooth) _smooth_update(obj);
1852 ecore_animator_del(wd->zoom_animator);
1853 wd->zoom_animator = NULL;
1854 zoom_do(obj, 1.0);
1855 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1856 }
1857 elm_smart_scroller_region_bring_in(wd->scr, rx, ry, rw, rh);
1858}
1859
1860EAPI void
1861elm_photocam_paused_set(Evas_Object *obj, Eina_Bool paused)
1862{
1863 ELM_CHECK_WIDTYPE(obj, widtype);
1864 Widget_Data *wd = elm_widget_data_get(obj);
1865 if (!wd) return;
1866 if (wd->paused == !!paused) return;
1867 wd->paused = paused;
1868 if (wd->paused)
1869 {
1870 if (wd->gzoom.bounce.animator)
1871 {
1872 ecore_animator_del(wd->gzoom.bounce.animator);
1873 wd->gzoom.bounce.animator = NULL;
1874 zoom_do(obj, 1.0);
1875 }
1876 if (wd->zoom_animator)
1877 {
1878 ecore_animator_del(wd->zoom_animator);
1879 wd->zoom_animator = NULL;
1880 zoom_do(obj, 1.0);
1881 evas_object_smart_callback_call(obj, SIG_ZOOM_STOP, NULL);
1882 }
1883 }
1884}
1885
1886EAPI Eina_Bool
1887elm_photocam_paused_get(const Evas_Object *obj)
1888{
1889 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1890 Widget_Data *wd = elm_widget_data_get(obj);
1891 if (!wd) return EINA_FALSE;
1892 return wd->paused;
1893}
1894
1895EAPI Evas_Object *
1896elm_photocam_internal_image_get(const Evas_Object *obj)
1897{
1898 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1899 Widget_Data *wd = elm_widget_data_get(obj);
1900 if (!wd) return NULL;
1901 return wd->img;
1902}
1903
1904EAPI void
1905elm_photocam_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
1906{
1907 ELM_CHECK_WIDTYPE(obj, widtype);
1908 Widget_Data *wd = elm_widget_data_get(obj);
1909 if (!wd) return;
1910 elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
1911}
1912
1913EAPI void
1914elm_photocam_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
1915{
1916 ELM_CHECK_WIDTYPE(obj, widtype);
1917 Widget_Data *wd = elm_widget_data_get(obj);
1918 if (!wd) return;
1919 elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
1920}
1921
1922EAPI void
1923elm_photocam_gesture_enabled_set(Evas_Object *obj, Eina_Bool gesture)
1924{
1925 ELM_CHECK_WIDTYPE(obj, widtype);
1926 Widget_Data *wd = elm_widget_data_get(obj);
1927 if (!wd) return;
1928 if (wd->do_gesture == !!gesture) return;
1929
1930 if (wd->gest)
1931 {
1932 evas_object_del(wd->gest);
1933 wd->gest = NULL;
1934 }
1935
1936 if (gesture)
1937 {
1938 wd->gest = elm_gesture_layer_add(wd->obj);
1939 if (!wd->gest) return;
1940 elm_gesture_layer_attach(wd->gest, wd->obj);
1941 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_START,
1942 _gzoom_start, wd);
1943 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_MOVE,
1944 _gzoom_move, wd);
1945 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_END,
1946 _gzoom_end, wd);
1947 elm_gesture_layer_cb_set(wd->gest, ELM_GESTURE_ZOOM, ELM_GESTURE_STATE_ABORT,
1948 _gzoom_end, wd);
1949 }
1950
1951 wd->do_gesture = !!gesture;
1952}
1953
1954EAPI Eina_Bool
1955elm_photocam_gesture_enabled_get(const Evas_Object *obj)
1956{
1957 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1958 Widget_Data *wd = elm_widget_data_get(obj);
1959 if (!wd) return EINA_FALSE;
1960
1961 return wd->do_gesture;
1962}
diff --git a/libraries/elementary/src/lib/elm_photocam.h b/libraries/elementary/src/lib/elm_photocam.h
new file mode 100644
index 0000000..2adb1b0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_photocam.h
@@ -0,0 +1,318 @@
1/**
2 * @defgroup Photocam Photocam
3 * @ingroup Elementary
4 *
5 * @image html img/widget/photocam/preview-00.png
6 * @image latex img/widget/photocam/preview-00.eps
7 *
8 * This is a widget specifically for displaying high-resolution digital
9 * camera photos giving speedy feedback (fast load), low memory footprint
10 * and zooming and panning as well as fitting logic. It is entirely focused
11 * on jpeg images, and takes advantage of properties of the jpeg format (via
12 * evas loader features in the jpeg loader).
13 *
14 * Signals that you can add callbacks for are:
15 * @li "clicked" - This is called when a user has clicked the photo without
16 * dragging around.
17 * @li "press" - This is called when a user has pressed down on the photo.
18 * @li "longpressed" - This is called when a user has pressed down on the
19 * photo for a long time without dragging around.
20 * @li "clicked,double" - This is called when a user has double-clicked the
21 * photo.
22 * @li "load" - Photo load begins.
23 * @li "loaded" - This is called when the image file load is complete for the
24 * first view (low resolution blurry version).
25 * @li "load,detail" - Photo detailed data load begins.
26 * @li "loaded,detail" - This is called when the image file load is complete
27 * for the detailed image data (full resolution needed).
28 * @li "zoom,start" - Zoom animation started.
29 * @li "zoom,stop" - Zoom animation stopped.
30 * @li "zoom,change" - Zoom changed when using an auto zoom mode.
31 * @li "scroll" - the content has been scrolled (moved)
32 * @li "scroll,anim,start" - scrolling animation has started
33 * @li "scroll,anim,stop" - scrolling animation has stopped
34 * @li "scroll,drag,start" - dragging the contents around has started
35 * @li "scroll,drag,stop" - dragging the contents around has stopped
36 *
37 * @ref tutorial_photocam shows the API in action.
38 * @{
39 */
40
41/**
42 * @brief Types of zoom available.
43 */
44typedef enum
45{
46 ELM_PHOTOCAM_ZOOM_MODE_MANUAL = 0, /**< Zoom controlled normally by elm_photocam_zoom_set */
47 ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT, /**< Zoom until photo fits in photocam */
48 ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL, /**< Zoom until photo fills photocam */
49 ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT_IN, /**< Zoom in until photo fits in photocam */
50 ELM_PHOTOCAM_ZOOM_MODE_LAST
51} Elm_Photocam_Zoom_Mode;
52
53/**
54 * @brief Add a new Photocam object
55 *
56 * @param parent The parent object
57 * @return The new object or NULL if it cannot be created
58 *
59 * @ingroup Photocam
60 */
61EAPI Evas_Object *elm_photocam_add(Evas_Object *parent);
62
63/**
64 * @brief Set the photo file to be shown
65 *
66 * @param obj The photocam object
67 * @param file The photo file
68 * @return The return error (see EVAS_LOAD_ERROR_NONE, EVAS_LOAD_ERROR_GENERIC etc.)
69 *
70 * This sets (and shows) the specified file (with a relative or absolute
71 * path) and will return a load error (same error that
72 * evas_object_image_load_error_get() will return). The image will change and
73 * adjust its size at this point and begin a background load process for this
74 * photo that at some time in the future will be displayed at the full
75 * quality needed.
76 *
77 * @ingroup Photocam
78 */
79EAPI Evas_Load_Error elm_photocam_file_set(Evas_Object *obj, const char *file);
80
81/**
82 * @brief Returns the path of the current image file
83 *
84 * @param obj The photocam object
85 * @return Returns the path
86 *
87 * @see elm_photocam_file_set()
88 *
89 * @ingroup Photocam
90 */
91EAPI const char *elm_photocam_file_get(const Evas_Object *obj);
92
93/**
94 * @brief Set the zoom level of the photo
95 *
96 * @param obj The photocam object
97 * @param zoom The zoom level to set
98 *
99 * This sets the zoom level. 1 will be 1:1 pixel for pixel. 2 will be 2:1
100 * (that is 2x2 photo pixels will display as 1 on-screen pixel). 4:1 will be
101 * 4x4 photo pixels as 1 screen pixel, and so on. The @p zoom parameter must
102 * be greater than 0. It is suggested to stick to powers of 2. (1, 2, 4, 8,
103 * 16, 32, etc.).
104 *
105 * @ingroup Photocam
106 */
107EAPI void elm_photocam_zoom_set(Evas_Object *obj, double zoom);
108
109/**
110 * @brief Get the zoom level of the photo
111 *
112 * @param obj The photocam object
113 * @return The current zoom level
114 *
115 * This returns the current zoom level of the photocam object. Note that if
116 * you set the fill mode to other than ELM_PHOTOCAM_ZOOM_MODE_MANUAL
117 * (which is the default), the zoom level may be changed at any time by the
118 * photocam object itself to account for photo size and photocam viewport
119 * size.
120 *
121 * @see elm_photocam_zoom_set()
122 * @see elm_photocam_zoom_mode_set()
123 *
124 * @ingroup Photocam
125 */
126EAPI double elm_photocam_zoom_get(const Evas_Object *obj);
127
128/**
129 * @brief Set the zoom mode
130 *
131 * @param obj The photocam object
132 * @param mode The desired mode
133 *
134 * This sets the zoom mode to manual or one of several automatic levels.
135 * Manual (ELM_PHOTOCAM_ZOOM_MODE_MANUAL) means that zoom is set manually by
136 * elm_photocam_zoom_set() and will stay at that level until changed by code
137 * or until zoom mode is changed. This is the default mode. The Automatic
138 * modes will allow the photocam object to automatically adjust zoom mode
139 * based on properties. ELM_PHOTOCAM_ZOOM_MODE_AUTO_FIT) will adjust zoom so
140 * the photo fits EXACTLY inside the scroll frame with no pixels outside this
141 * region. ELM_PHOTOCAM_ZOOM_MODE_AUTO_FILL will be similar but ensure no
142 * pixels within the frame are left unfilled.
143 *
144 * @ingroup Photocam
145 */
146EAPI void elm_photocam_zoom_mode_set(Evas_Object *obj, Elm_Photocam_Zoom_Mode mode);
147
148/**
149 * @brief Get the zoom mode
150 *
151 * @param obj The photocam object
152 * @return The current zoom mode
153 *
154 * This gets the current zoom mode of the photocam object.
155 *
156 * @see elm_photocam_zoom_mode_set()
157 *
158 * @ingroup Photocam
159 */
160EAPI Elm_Photocam_Zoom_Mode elm_photocam_zoom_mode_get(const Evas_Object *obj);
161
162/**
163 * @brief Get the current image pixel width and height
164 *
165 * @param obj The photocam object
166 * @param w A pointer to the width return
167 * @param h A pointer to the height return
168 *
169 * This gets the current photo pixel width and height (for the original).
170 * The size will be returned in the integers @p w and @p h that are pointed
171 * to.
172 *
173 * @ingroup Photocam
174 */
175EAPI void elm_photocam_image_size_get(const Evas_Object *obj, int *w, int *h);
176
177/**
178 * @brief Get the region of the image that is currently shown
179 *
180 * @param obj
181 * @param x A pointer to the X-coordinate of region
182 * @param y A pointer to the Y-coordinate of region
183 * @param w A pointer to the width
184 * @param h A pointer to the height
185 *
186 * @see elm_photocam_image_region_show()
187 * @see elm_photocam_image_region_bring_in()
188 *
189 * @ingroup Photocam
190 */
191EAPI void elm_photocam_image_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h);
192
193/**
194 * @brief Set the viewed region of the image
195 *
196 * @param obj The photocam object
197 * @param x X-coordinate of region in image original pixels
198 * @param y Y-coordinate of region in image original pixels
199 * @param w Width of region in image original pixels
200 * @param h Height of region in image original pixels
201 *
202 * This shows the region of the image without using animation.
203 *
204 * @ingroup Photocam
205 */
206EAPI void elm_photocam_image_region_show(Evas_Object *obj, int x, int y, int w, int h);
207
208/**
209 * @brief Bring in the viewed portion of the image
210 *
211 * @param obj The photocam object
212 * @param x X-coordinate of region in image original pixels
213 * @param y Y-coordinate of region in image original pixels
214 * @param w Width of region in image original pixels
215 * @param h Height of region in image original pixels
216 *
217 * This shows the region of the image using animation.
218 *
219 * @ingroup Photocam
220 */
221EAPI void elm_photocam_image_region_bring_in(Evas_Object *obj, int x, int y, int w, int h);
222
223/**
224 * @brief Set the paused state for photocam
225 *
226 * @param obj The photocam object
227 * @param paused The pause state to set
228 *
229 * This sets the paused state to on(EINA_TRUE) or off (EINA_FALSE) for
230 * photocam. The default is off. This will stop zooming using animation on
231 * zoom level changes and change instantly. This will stop any existing
232 * animations that are running.
233 *
234 * @ingroup Photocam
235 */
236EAPI void elm_photocam_paused_set(Evas_Object *obj, Eina_Bool paused);
237
238/**
239 * @brief Get the paused state for photocam
240 *
241 * @param obj The photocam object
242 * @return The current paused state
243 *
244 * This gets the current paused state for the photocam object.
245 *
246 * @see elm_photocam_paused_set()
247 *
248 * @ingroup Photocam
249 */
250EAPI Eina_Bool elm_photocam_paused_get(const Evas_Object *obj);
251
252/**
253 * @brief Get the internal low-res image used for photocam
254 *
255 * @param obj The photocam object
256 * @return The internal image object handle, or NULL if none exists
257 *
258 * This gets the internal image object inside photocam. Do not modify it. It
259 * is for inspection only, and hooking callbacks to. Nothing else. It may be
260 * deleted at any time as well.
261 *
262 * @ingroup Photocam
263 */
264EAPI Evas_Object *elm_photocam_internal_image_get(const Evas_Object *obj);
265
266/**
267 * @brief Set the photocam scrolling bouncing.
268 *
269 * @param obj The photocam object
270 * @param h_bounce set this to @c EINA_TRUE for horizontal bouncing
271 * @param v_bounce set this to @c EINA_TRUE for vertical bouncing
272 *
273 * @ingroup Photocam
274 */
275EAPI void elm_photocam_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
276
277/**
278 * @brief Get the photocam scrolling bouncing.
279 *
280 * @param obj The photocam object
281 * @param h_bounce horizontal bouncing
282 * @param v_bounce vertical bouncing
283 *
284 * @see elm_photocam_bounce_set()
285 *
286 * @ingroup Photocam
287 */
288EAPI void elm_photocam_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
289
290/**
291 * @brief Set the gesture state for photocam.
292 *
293 * @param obj The photocam object
294 * @param gesture The gesture state to set
295 *
296 * This sets the gesture state to on(EINA_TRUE) or off (EINA_FALSE) for
297 * photocam. The default is off. This will start multi touch zooming.
298 *
299 * @ingroup Photocam
300 */
301EAPI void elm_photocam_gesture_enabled_set(Evas_Object *obj, Eina_Bool gesture);
302
303/**
304 * @brief Get the gesture state for photocam.
305 *
306 * @param obj The photocam object
307 * @return The current gesture state
308 *
309 * This gets the current gesture state for the photocam object.
310 *
311 * @see elm_photocam_gesture_enabled_set()
312 *
313 * @ingroup Photocam
314 */
315EAPI Eina_Bool elm_photocam_gesture_enabled_get(const Evas_Object *obj);
316/**
317 * @}
318 */
diff --git a/libraries/elementary/src/lib/elm_plug.c b/libraries/elementary/src/lib/elm_plug.c
new file mode 100644
index 0000000..bf9db91
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_plug.c
@@ -0,0 +1,128 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *img;
9};
10
11static const char *widtype = NULL;
12static void _del_hook(Evas_Object *obj);
13static void _theme_hook(Evas_Object *obj);
14static void _sizing_eval(Evas_Object *obj);
15static void _mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
16
17static const char SIG_CLICKED[] = "clicked";
18
19static const Evas_Smart_Cb_Description _signals[] = {
20 {SIG_CLICKED, ""},
21 {NULL, NULL}
22};
23
24
25static void
26_del_hook(Evas_Object *obj)
27{
28 Widget_Data *wd = elm_widget_data_get(obj);
29
30 if (!wd) return;
31 free(wd);
32}
33
34static void
35_del_pre_hook(Evas_Object *obj)
36{
37 Widget_Data *wd = elm_widget_data_get(obj);
38
39 if (!wd) return;
40 evas_object_del(wd->img);
41}
42
43static void
44_theme_hook(Evas_Object *obj)
45{
46 Widget_Data *wd = elm_widget_data_get(obj);
47
48 if (!wd) return;
49 _sizing_eval(obj);
50}
51
52static void
53_sizing_eval(Evas_Object *obj)
54{
55 Widget_Data *wd = elm_widget_data_get(obj);
56 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
57
58 if (!wd) return;
59 //TODO: get socket object size
60 evas_object_size_hint_min_set(obj, minw, minh);
61 evas_object_size_hint_max_set(obj, maxw, maxh);
62}
63
64static void
65_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
66{
67 evas_object_smart_callback_call(data, SIG_CLICKED, NULL);
68}
69
70
71EAPI Evas_Object *
72elm_plug_image_object_get(const Evas_Object *obj)
73{
74 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
75 Widget_Data *wd = elm_widget_data_get(obj);
76 if (!wd) return NULL;
77 if (!wd->img) return NULL;
78 return wd->img;
79}
80
81EAPI Evas_Object *
82elm_plug_add(Evas_Object *parent)
83{
84 Evas_Object *obj;
85 Evas *e;
86 Widget_Data *wd;
87 Ecore_Evas *ee;
88
89 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
90
91 ELM_SET_WIDTYPE(widtype, "plug");
92 elm_widget_type_set(obj, "plug");
93 elm_widget_sub_object_add(parent, obj);
94 elm_widget_data_set(obj, wd);
95 elm_widget_del_hook_set(obj, _del_hook);
96 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
97 elm_widget_theme_hook_set(obj, _theme_hook);
98 elm_widget_can_focus_set(obj, EINA_FALSE);
99
100 ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
101 if (!ee) return NULL;
102 wd->img = ecore_evas_extn_plug_new(ee);
103 if (!wd->img) return NULL;
104
105 evas_object_event_callback_add(wd->img, EVAS_CALLBACK_MOUSE_UP,
106 _mouse_up, obj);
107 elm_widget_resize_object_set(obj, wd->img);
108
109 evas_object_smart_callbacks_descriptions_set(obj, _signals);
110
111 _sizing_eval(obj);
112 return obj;
113}
114
115EAPI Eina_Bool
116elm_plug_connect(Evas_Object *obj, const char *svcname, int svcnum, Eina_Bool svcsys)
117{
118 Evas_Object *plug_img = NULL;
119
120 plug_img = elm_plug_image_object_get(obj);
121 if (!plug_img) return EINA_FALSE;
122
123 if (ecore_evas_extn_plug_connect(plug_img, svcname, svcnum, svcsys))
124 return EINA_TRUE;
125 else
126 return EINA_FALSE;
127}
128
diff --git a/libraries/elementary/src/lib/elm_plug.h b/libraries/elementary/src/lib/elm_plug.h
new file mode 100644
index 0000000..ed79d85
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_plug.h
@@ -0,0 +1,57 @@
1/**
2 * @defgroup Plug Plug
3 * @ingroup Elementary
4 *
5 * An object that allows one to show an image which other process created.
6 * It can be used anywhere like any other elementary widget.
7 *
8 */
9
10/**
11 * @addtogroup Plug
12 * @{
13 */
14
15/**
16 * Add a new plug image to the parent.
17 *
18 * @param parent The parent object
19 * @return The new plug image object or NULL if it cannot be created
20 *
21 * @ingroup Plug
22 */
23EAPI Evas_Object *elm_plug_add(Evas_Object *parent);
24
25/**
26 * Connect a plug widget to service provided by socket image.
27 *
28 * @param obj The Evas_Object where the new image object will live.
29 * @param svcname The service name to connect to set up by the socket.
30 * @param svcnum The service number to connect to (set up by socket).
31 * @param svcsys Boolean to set if the service is a system one or not (set up by socket).
32 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
33 *
34 * @ingroup Plug
35 */
36EAPI Eina_Bool elm_plug_connect(Evas_Object *obj, const char *svcname, int svcnum, Eina_Bool svcsys);
37
38/**
39 * Get the basic Evas_Image object from this object (widget).
40 *
41 * @param obj The image object to get the inlined image from
42 * @return The inlined image object, or NULL if none exists
43 *
44 * This function allows one to get the underlying @c Evas_Object of type
45 * Image from this elementary widget. It can be useful to do things like get
46 * the pixel data, save the image to a file, etc.
47 *
48 * @note Be careful to not manipulate it, as it is under control of
49 * elementary.
50 *
51 * @ingroup Plug
52 */
53EAPI Evas_Object *elm_plug_image_object_get(const Evas_Object *obj);
54
55/**
56 * @}
57 */
diff --git a/libraries/elementary/src/lib/elm_priv.h b/libraries/elementary/src/lib/elm_priv.h
new file mode 100644
index 0000000..f931bc0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_priv.h
@@ -0,0 +1,315 @@
1#ifndef ELM_PRIV_H
2#define ELM_PRIV_H
3#ifdef HAVE_CONFIG_H
4#include "elementary_config.h"
5#endif
6#ifdef HAVE_ELEMENTARY_X
7#include <Ecore_X.h>
8#endif
9#ifdef HAVE_ELEMENTARY_FB
10#include <Ecore_Fb.h>
11#endif
12#ifdef HAVE_ELEMENTARY_WINCE
13#include <Ecore_WinCE.h>
14#endif
15
16#include "elm_widget.h"
17
18#define CRITICAL(...) EINA_LOG_DOM_CRIT(_elm_log_dom, __VA_ARGS__)
19#define ERR(...) EINA_LOG_DOM_ERR (_elm_log_dom, __VA_ARGS__)
20#define WRN(...) EINA_LOG_DOM_WARN(_elm_log_dom, __VA_ARGS__)
21#define INF(...) EINA_LOG_DOM_INFO(_elm_log_dom, __VA_ARGS__)
22#define DBG(...) EINA_LOG_DOM_DBG (_elm_log_dom, __VA_ARGS__)
23
24#ifdef ENABLE_NLS
25#include <libintl.h>
26#define E_(string) _elm_dgettext(string)
27#else
28#ifndef setlocale
29#define setlocale(c, l)
30#endif
31#ifndef libintl_setlocale
32#define libintl_setlocale(c, l)
33#endif
34#ifndef bindtextdomain
35#define bindtextdomain(domain, dir)
36#endif
37#ifndef libintl_bindtextdomain
38#define libintl_bindtextdomain(domain, dir)
39#endif
40#define E_(string) (string)
41#endif
42#define N_(string) (string)
43
44typedef struct _Elm_Config Elm_Config;
45typedef struct _Elm_Module Elm_Module;
46typedef struct _Elm_Datetime_Module_Data Elm_Datetime_Module_Data;
47
48struct _Elm_Theme
49{
50 Eina_List *overlay;
51 Eina_List *themes;
52 Eina_List *extension;
53 Eina_Hash *cache;
54 Eina_Hash *cache_data;
55 Elm_Theme *ref_theme;
56 Eina_List *referrers;
57 const char *theme;
58 int ref;
59};
60
61/* increment this whenever we change config enough that you need new
62 * defaults for elm to work.
63 */
64#define ELM_CONFIG_EPOCH 0x0001
65/* increment this whenever a new set of config values are added but the users
66 * config doesn't need to be wiped - simply new values need to be put in
67 */
68#define ELM_CONFIG_FILE_GENERATION 0x0003
69#define ELM_CONFIG_VERSION ((ELM_CONFIG_EPOCH << 16) | ELM_CONFIG_FILE_GENERATION)
70/* NB: profile configuration files (.src) must have their
71 * "config_version" entry's value up-to-date with ELM_CONFIG_VERSION
72 * (in decimal)!! */
73
74/* note: always remember to sync it with elm_config.c */
75extern const char *_elm_engines[];
76
77#define ELM_SOFTWARE_X11 (_elm_engines[0])
78#define ELM_SOFTWARE_FB (_elm_engines[1])
79#define ELM_SOFTWARE_DIRECTFB (_elm_engines[2])
80#define ELM_SOFTWARE_16_X11 (_elm_engines[3])
81#define ELM_SOFTWARE_8_X11 (_elm_engines[4])
82#define ELM_XRENDER_X11 (_elm_engines[5])
83#define ELM_OPENGL_X11 (_elm_engines[6])
84#define ELM_SOFTWARE_WIN32 (_elm_engines[7])
85#define ELM_SOFTWARE_16_WINCE (_elm_engines[8])
86#define ELM_SOFTWARE_SDL (_elm_engines[9])
87#define ELM_SOFTWARE_16_SDL (_elm_engines[10])
88#define ELM_OPENGL_SDL (_elm_engines[11])
89#define ELM_BUFFER (_elm_engines[12])
90#define ELM_EWS (_elm_engines[13])
91#define ELM_OPENGL_COCOA (_elm_engines[14])
92#define ELM_SOFTWARE_PSL1GHT (_elm_engines[15])
93#define ELM_WAYLAND_SHM (_elm_engines[16])
94#define ELM_WAYLAND_EGL (_elm_engines[17])
95
96#define ELM_FONT_TOKEN_STYLE ":style="
97
98#define ELM_ACCESS_MODE_OFF 0
99#define ELM_ACCESS_MODE_ON 1
100
101#undef MIN
102#define MIN(x, y) (((x) < (y)) ? (x) : (y))
103#undef MAX
104#define MAX(x, y) (((x) > (y)) ? (x) : (y))
105
106struct _Elm_Config
107{
108 int config_version;
109 const char *engine;
110 unsigned char vsync;
111 unsigned char thumbscroll_enable;
112 int thumbscroll_threshold;
113 double thumbscroll_momentum_threshold;
114 double thumbscroll_friction;
115 double thumbscroll_bounce_friction;
116 double page_scroll_friction;
117 double bring_in_scroll_friction;
118 double zoom_friction;
119 unsigned char thumbscroll_bounce_enable;
120 double thumbscroll_border_friction;
121 double thumbscroll_sensitivity_friction;
122 double scroll_smooth_amount;
123 double scroll_smooth_history_weight;
124 double scroll_smooth_future_time;
125 double scroll_smooth_time_window;
126 double scale;
127 int bgpixmap;
128 int compositing;
129 Eina_List *font_dirs;
130 Eina_List *font_overlays;
131 int font_hinting;
132 int cache_flush_poll_interval;
133 unsigned char cache_flush_enable;
134 int image_cache;
135 int font_cache;
136 int edje_cache;
137 int edje_collection_cache;
138 int finger_size;
139 double fps;
140 const char *theme;
141 const char *modules;
142 double tooltip_delay;
143 unsigned char cursor_engine_only;
144 unsigned char focus_highlight_enable;
145 unsigned char focus_highlight_animate;
146 int toolbar_shrink_mode;
147 unsigned char fileselector_expand_enable;
148 unsigned char inwin_dialogs_enable;
149 int icon_size;
150 double longpress_timeout;
151 unsigned char effect_enable;
152 unsigned char desktop_entry;
153 Eina_Bool password_show_last;
154 double password_show_last_timeout;
155 Eina_Bool glayer_zoom_finger_enable;
156 double glayer_zoom_finger_factor;
157 double glayer_zoom_wheel_factor;
158 double glayer_zoom_distance_tolerance;
159 double glayer_rotate_finger_enable;
160 double glayer_rotate_angular_tolerance;
161 double glayer_line_min_length;
162 double glayer_line_distance_tolerance;
163 double glayer_line_angular_tolerance;
164 unsigned int glayer_flick_time_limit_ms;
165 double glayer_long_tap_start_timeout;
166 int access_mode;
167 Eina_Bool glayer_continues_enable;
168 int week_start;
169 int weekend_start;
170 int weekend_len;
171 int year_min;
172 int year_max;
173 Eina_List *color_palette;
174
175 /* Not part of the EET file */
176 Eina_Bool is_mirrored : 1;
177 Eina_Bool translate : 1;
178};
179
180struct _Elm_Module
181{
182 int version;
183 const char *name;
184 const char *as;
185 const char *so_path;
186 const char *data_dir;
187 const char *bin_dir;
188 Eina_Module *module;
189 void *data;
190 void *api;
191 int (*init_func)(Elm_Module *m);
192 int (*shutdown_func)(Elm_Module *m);
193 int references;
194};
195
196struct _Elm_Datetime_Module_Data
197{
198 Evas_Object *base;
199 void (*field_limit_get)(Evas_Object *obj, Elm_Datetime_Field_Type field_type, int *range_min, int *range_max);
200 const char *(*field_format_get)(Evas_Object * obj, Elm_Datetime_Field_Type field_type);
201};
202
203int _elm_ews_wm_init(void);
204void _elm_ews_wm_shutdown(void);
205void _elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme);
206
207void _elm_win_shutdown(void);
208void _elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme);
209void _elm_win_translate(void);
210
211Eina_Bool _elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style);
212Eina_Bool _elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style);
213Eina_Bool _elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style);
214Eina_Bool _elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style);
215Eina_Bool _elm_theme_parse(Elm_Theme *th, const char *theme);
216void _elm_theme_shutdown(void);
217
218void _elm_module_init(void);
219void _elm_module_shutdown(void);
220void _elm_module_parse(const char *s);
221Elm_Module *_elm_module_find_as(const char *as);
222Elm_Module *_elm_module_add(const char *name, const char *as);
223void _elm_module_del(Elm_Module *m);
224Eina_Bool _elm_module_load(Elm_Module *m);
225void _elm_module_unload(Elm_Module *m);
226const void *_elm_module_symbol_get(Elm_Module *m, const char *name);
227
228void _elm_widget_type_clear(void);
229void _elm_widget_focus_region_show(const Evas_Object *obj);
230void _elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused);
231Eina_Bool _elm_widget_top_win_focused_get(const Evas_Object *obj);
232
233void _elm_unneed_ethumb(void);
234void _elm_unneed_web(void);
235
236void _elm_rescale(void);
237void _elm_widget_mirrored_reload(Evas_Object *obj);
238
239void _elm_config_init(void);
240void _elm_config_sub_init(void);
241void _elm_config_shutdown(void);
242void _elm_config_sub_shutdown(void);
243Eina_Bool _elm_config_save(void);
244void _elm_config_reload(void);
245
246void _elm_recache(void);
247
248const char *_elm_config_current_profile_get(void);
249const char *_elm_config_profile_dir_get(const char *prof, Eina_Bool is_user);
250Eina_List *_elm_config_profiles_list(void);
251void _elm_config_all_update(void);
252void _elm_config_profile_set(const char *profile);
253
254void _elm_config_engine_set(const char *engine);
255
256Eina_List *_elm_config_font_overlays_list(void);
257void _elm_config_font_overlay_set(const char *text_class, const char *font, Evas_Font_Size size);
258void _elm_config_font_overlay_remove(const char *text_class);
259void _elm_config_font_overlay_apply(void);
260Eina_List *_elm_config_text_classes_get(void);
261void _elm_config_text_classes_free(Eina_List *l);
262
263Elm_Font_Properties *_elm_font_properties_get(Eina_Hash **font_hash, const char *font);
264Eina_Hash *_elm_font_available_hash_add(Eina_Hash *font_hash, const char *full_name);
265void _elm_font_available_hash_del(Eina_Hash *hash);
266
267void elm_tooltip_theme(Elm_Tooltip *tt);
268void 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);
269void elm_cursor_theme(Elm_Cursor *cur);
270void elm_object_sub_cursor_set(Evas_Object *eventarea, Evas_Object *owner, const char *cursor);
271
272void elm_menu_clone(Evas_Object *from_menu, Evas_Object *to_menu, Elm_Object_Item *parent);
273
274Eina_Bool _elm_dangerous_call_check(const char *call);
275
276Evas_Object *_elm_scroller_edje_object_get(Evas_Object *obj);
277
278char *_elm_util_mkup_to_text(const char *mkup);
279char *_elm_util_text_to_mkup(const char *text);
280
281Eina_Bool _elm_video_check(Evas_Object *video);
282
283Eina_List *_elm_config_color_list_get(const char *palette_name);
284void _elm_config_color_set(const char *palette_name, int r, int g, int b, int a);
285void _elm_config_colors_free(const char *palette_name);
286
287extern char *_elm_appname;
288extern Elm_Config *_elm_config;
289extern const char *_elm_data_dir;
290extern const char *_elm_lib_dir;
291extern int _elm_log_dom;
292extern Eina_List *_elm_win_list;
293extern int _elm_win_deferred_free;
294extern const char *_elm_preferred_engine;
295
296#ifdef ENABLE_NLS
297/* Our gettext wrapper, used to disable translation of elm if the app
298 * is not translated. */
299static inline const char *
300_elm_dgettext(const char *string)
301{
302 if (EINA_UNLIKELY(_elm_config->translate == EINA_FALSE))
303 {
304 return string;
305 }
306
307 return dgettext(PACKAGE, string);
308}
309
310#endif
311
312/* Used by the paste handler */
313void _elm_entry_entry_paste(Evas_Object *obj, const char *entry);
314
315#endif
diff --git a/libraries/elementary/src/lib/elm_progressbar.c b/libraries/elementary/src/lib/elm_progressbar.c
new file mode 100644
index 0000000..c67c5e6
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_progressbar.c
@@ -0,0 +1,462 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define MIN_RATIO_LVL 0.0
5#define MAX_RATIO_LVL 1.0
6
7typedef struct _Widget_Data Widget_Data;
8
9struct _Widget_Data
10{
11 Evas_Object *progressbar;
12 Evas_Object *spacer;
13 Evas_Object *icon;
14 Evas_Coord size;
15 Eina_Bool horizontal : 1;
16 Eina_Bool inverted : 1;
17 Eina_Bool pulse : 1;
18 Eina_Bool pulse_state : 1;
19 const char *units;
20 const char *label;
21 double val;
22};
23
24static const char *widtype = NULL;
25static void _del_hook(Evas_Object *obj);
26static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
27static void _theme_hook(Evas_Object *obj);
28static void _sizing_eval(Evas_Object *obj);
29static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
30static void _sub_del(void *data, Evas_Object *obj, void *event_info);
31static void _units_set(Evas_Object *obj);
32static void _val_set(Evas_Object *obj);
33
34static void
35_del_hook(Evas_Object *obj)
36{
37 Widget_Data *wd = elm_widget_data_get(obj);
38 if (!wd) return;
39 if (wd->label) eina_stringshare_del(wd->label);
40 if (wd->units) eina_stringshare_del(wd->units);
41 free(wd);
42}
43
44static void
45_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
46{
47 Widget_Data *wd = elm_widget_data_get(obj);
48 if (!wd) return;
49 edje_object_mirrored_set(wd->progressbar, rtl);
50}
51
52static void
53_theme_hook(Evas_Object *obj)
54{
55 Widget_Data *wd = elm_widget_data_get(obj);
56 if (!wd) return;
57 _elm_widget_mirrored_reload(obj);
58 _mirrored_set(obj, elm_widget_mirrored_get(obj));
59 if (wd->horizontal)
60 _elm_theme_object_set(obj, wd->progressbar, "progressbar", "horizontal", elm_widget_style_get(obj));
61 else
62 _elm_theme_object_set(obj, wd->progressbar, "progressbar", "vertical", elm_widget_style_get(obj));
63
64 if (wd->icon)
65 {
66 edje_object_part_swallow(wd->progressbar, "elm.swallow.content", wd->icon);
67 edje_object_signal_emit(wd->progressbar, "elm,state,icon,visible", "elm");
68 }
69 if (wd->label)
70 {
71 edje_object_part_text_escaped_set(wd->progressbar, "elm.text", wd->label);
72 edje_object_signal_emit(wd->progressbar, "elm,state,text,visible", "elm");
73 }
74 if (wd->pulse)
75 edje_object_signal_emit(wd->progressbar, "elm,state,pulse", "elm");
76 else
77 edje_object_signal_emit(wd->progressbar, "elm,state,fraction", "elm");
78 if (wd->pulse_state)
79 edje_object_signal_emit(wd->progressbar, "elm,state,pulse,start", "elm");
80
81 if ((wd->units) && (!wd->pulse))
82 edje_object_signal_emit(wd->progressbar, "elm,state,units,visible", "elm");
83
84 if (wd->horizontal)
85 evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
86 else
87 evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
88
89 edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
90
91 if (wd->inverted)
92 edje_object_signal_emit(wd->progressbar, "elm,state,inverted,on", "elm");
93
94 _units_set(obj);
95 edje_object_message_signal_process(wd->progressbar);
96 edje_object_scale_set(wd->progressbar, elm_widget_scale_get(obj) * _elm_config->scale);
97 _val_set(obj);
98 _sizing_eval(obj);
99}
100
101static void
102_sizing_eval(Evas_Object *obj)
103{
104 Widget_Data *wd = elm_widget_data_get(obj);
105 Evas_Coord minw = -1, minh = -1;
106 if (!wd) return;
107 edje_object_size_min_restricted_calc(wd->progressbar, &minw, &minh, minw, minh);
108 evas_object_size_hint_min_set(obj, minw, minh);
109 evas_object_size_hint_max_set(obj, -1, -1);
110}
111
112static void
113_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
114{
115 Widget_Data *wd = elm_widget_data_get(data);
116 if (!wd) return;
117 if (obj != wd->icon) return;
118 _sizing_eval(data);
119}
120
121static void
122_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
123{
124 Widget_Data *wd = elm_widget_data_get(obj);
125 Evas_Object *sub = event_info;
126 if (!wd) return;
127 if (sub == wd->icon)
128 {
129 edje_object_signal_emit(wd->progressbar, "elm,state,icon,hidden", "elm");
130 evas_object_event_callback_del_full
131 (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
132 wd->icon = NULL;
133 edje_object_message_signal_process(wd->progressbar);
134 _sizing_eval(obj);
135 }
136}
137
138static void
139_val_set(Evas_Object *obj)
140{
141 Widget_Data *wd = elm_widget_data_get(obj);
142 Eina_Bool rtl;
143 double pos;
144 if (!wd) return;
145 pos = wd->val;
146 rtl = elm_widget_mirrored_get(obj);
147 if ((!rtl && wd->inverted) || (rtl &&
148 ((!wd->horizontal && wd->inverted) ||
149 (wd->horizontal && !wd->inverted)))) pos = MAX_RATIO_LVL - pos;
150 edje_object_part_drag_value_set(wd->progressbar, "elm.cur.progressbar", pos, pos);
151}
152
153static void
154_units_set(Evas_Object *obj)
155{
156 Widget_Data *wd = elm_widget_data_get(obj);
157 if (!wd) return;
158 if (wd->units)
159 {
160 char buf[1024];
161 snprintf(buf, sizeof(buf), wd->units, 100 * wd->val);
162 edje_object_part_text_escaped_set(wd->progressbar, "elm.text.status", buf);
163 }
164 else
165 edje_object_part_text_escaped_set(wd->progressbar, "elm.text.status", NULL);
166}
167
168static void
169_elm_progressbar_label_set(Evas_Object *obj, const char *item, const char *label)
170{
171 ELM_CHECK_WIDTYPE(obj, widtype);
172 Widget_Data *wd = elm_widget_data_get(obj);
173 if (item && strcmp(item, "default")) return;
174 if (!wd) return;
175 eina_stringshare_replace(&wd->label, label);
176 if (label)
177 {
178 edje_object_signal_emit(wd->progressbar, "elm,state,text,visible", "elm");
179 edje_object_message_signal_process(wd->progressbar);
180 }
181 else
182 {
183 edje_object_signal_emit(wd->progressbar, "elm,state,text,hidden", "elm");
184 edje_object_message_signal_process(wd->progressbar);
185 }
186 edje_object_part_text_escaped_set(wd->progressbar, "elm.text", label);
187 _sizing_eval(obj);
188}
189
190static const char *
191_elm_progressbar_label_get(const Evas_Object *obj, const char *item)
192{
193 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
194 Widget_Data *wd = elm_widget_data_get(obj);
195 if (item && strcmp(item, "default")) return NULL;
196 if (!wd) return NULL;
197 return wd->label;
198}
199
200static void
201_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
202{
203 ELM_CHECK_WIDTYPE(obj, widtype);
204 Widget_Data *wd;
205 if (part && strcmp(part, "icon")) return;
206 wd = elm_widget_data_get(obj);
207 if (!wd) return;
208 if (wd->icon == content) return;
209 if (wd->icon) evas_object_del(wd->icon);
210 wd->icon = content;
211 if (content)
212 {
213 elm_widget_sub_object_add(obj, content);
214 evas_object_event_callback_add(content,
215 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
216 _changed_size_hints, obj);
217 edje_object_part_swallow(wd->progressbar, "elm.swallow.content", content);
218 edje_object_signal_emit(wd->progressbar, "elm,state,icon,visible", "elm");
219 edje_object_message_signal_process(wd->progressbar);
220 }
221 _sizing_eval(obj);
222}
223
224static Evas_Object *
225_content_get_hook(const Evas_Object *obj, const char *part)
226{
227 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
228 Widget_Data *wd;
229 if (part && strcmp(part, "icon")) return NULL;
230 wd = elm_widget_data_get(obj);
231 if (!wd) return NULL;
232 return wd->icon;
233}
234
235static Evas_Object *
236_content_unset_hook(Evas_Object *obj, const char *part)
237{
238 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
239 Widget_Data *wd;
240 Evas_Object *icon;
241 if (part && strcmp(part, "icon")) return NULL;
242 wd = elm_widget_data_get(obj);
243 if (!wd) return NULL;
244 if (!wd->icon) return NULL;
245 icon = wd->icon;
246 elm_widget_sub_object_del(obj, wd->icon);
247 evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
248 _changed_size_hints, obj);
249 edje_object_part_unswallow(wd->progressbar, wd->icon);
250 wd->icon = NULL;
251 return icon;
252}
253
254
255EAPI Evas_Object *
256elm_progressbar_add(Evas_Object *parent)
257{
258 Evas_Object *obj;
259 Evas *e;
260 Widget_Data *wd;
261
262 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
263
264 ELM_SET_WIDTYPE(widtype, "progressbar");
265 elm_widget_type_set(obj, "progressbar");
266 elm_widget_sub_object_add(parent, obj);
267 elm_widget_data_set(obj, wd);
268 elm_widget_del_hook_set(obj, _del_hook);
269 elm_widget_theme_hook_set(obj, _theme_hook);
270 elm_widget_can_focus_set(obj, EINA_FALSE);
271 elm_widget_text_set_hook_set(obj, _elm_progressbar_label_set);
272 elm_widget_text_get_hook_set(obj, _elm_progressbar_label_get);
273 elm_widget_content_set_hook_set(obj, _content_set_hook);
274 elm_widget_content_get_hook_set(obj, _content_get_hook);
275 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
276
277 wd->horizontal = EINA_TRUE;
278 wd->inverted = EINA_FALSE;
279 wd->pulse = EINA_FALSE;
280 wd->pulse_state = EINA_FALSE;
281 wd->units = eina_stringshare_add("%.0f %%");
282 wd->val = MIN_RATIO_LVL;
283
284 wd->progressbar = edje_object_add(e);
285 _elm_theme_object_set(obj, wd->progressbar, "progressbar", "horizontal", "default");
286 elm_widget_resize_object_set(obj, wd->progressbar);
287
288 wd->spacer = evas_object_rectangle_add(e);
289 evas_object_color_set(wd->spacer, 0, 0, 0, 0);
290 evas_object_pass_events_set(wd->spacer, EINA_TRUE);
291 elm_widget_sub_object_add(obj, wd->spacer);
292 edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
293
294 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
295 _units_set(obj);
296 _val_set(obj);
297 _mirrored_set(obj, elm_widget_mirrored_get(obj));
298 _sizing_eval(obj);
299 return obj;
300}
301
302EAPI void
303elm_progressbar_pulse_set(Evas_Object *obj, Eina_Bool pulse)
304{
305 ELM_CHECK_WIDTYPE(obj, widtype);
306 Widget_Data *wd = elm_widget_data_get(obj);
307 if (!wd) return;
308 pulse = !!pulse;
309 if (wd->pulse == pulse) return;
310 wd->pulse = pulse;
311 _theme_hook(obj);
312}
313
314EAPI Eina_Bool
315elm_progressbar_pulse_get(const Evas_Object *obj)
316{
317 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
318 Widget_Data *wd = elm_widget_data_get(obj);
319 if (!wd) return EINA_FALSE;
320 return wd->pulse;
321}
322
323EAPI void
324elm_progressbar_pulse(Evas_Object *obj, Eina_Bool state)
325{
326 ELM_CHECK_WIDTYPE(obj, widtype);
327 Widget_Data *wd = elm_widget_data_get(obj);
328 if (!wd) return;
329 state = !!state;
330 if ((!wd->pulse) && (wd->pulse_state == state)) return;
331 wd->pulse_state = state;
332 if (wd->pulse_state)
333 edje_object_signal_emit(wd->progressbar, "elm,state,pulse,start", "elm");
334 else
335 edje_object_signal_emit(wd->progressbar, "elm,state,pulse,stop", "elm");
336}
337
338EAPI void
339elm_progressbar_value_set(Evas_Object *obj, double val)
340{
341 ELM_CHECK_WIDTYPE(obj, widtype);
342 Widget_Data *wd = elm_widget_data_get(obj);
343 if (!wd) return;
344 if (wd->val == val) return;
345 wd->val = val;
346 if (wd->val < MIN_RATIO_LVL) wd->val = MIN_RATIO_LVL;
347 if (wd->val > MAX_RATIO_LVL) wd->val = MAX_RATIO_LVL;
348 _val_set(obj);
349 _units_set(obj);
350}
351
352EAPI double
353elm_progressbar_value_get(const Evas_Object *obj)
354{
355 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
356 Widget_Data *wd = elm_widget_data_get(obj);
357 if (!wd) return 0.0;
358 return wd->val;
359}
360
361EAPI void
362elm_progressbar_span_size_set(Evas_Object *obj, Evas_Coord size)
363{
364 ELM_CHECK_WIDTYPE(obj, widtype);
365 Widget_Data *wd = elm_widget_data_get(obj);
366 if (!wd) return;
367 if (wd->size == size) return;
368 wd->size = size;
369 if (wd->horizontal)
370 evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
371 else
372 evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
373 edje_object_part_swallow(wd->progressbar, "elm.swallow.bar", wd->spacer);
374 _sizing_eval(obj);
375}
376
377EAPI Evas_Coord
378elm_progressbar_span_size_get(const Evas_Object *obj)
379{
380 ELM_CHECK_WIDTYPE(obj, widtype) 0;
381 Widget_Data *wd = elm_widget_data_get(obj);
382 if (!wd) return 0;
383 return wd->size;
384}
385
386EAPI void
387elm_progressbar_unit_format_set(Evas_Object *obj, const char *units)
388{
389 ELM_CHECK_WIDTYPE(obj, widtype);
390 Widget_Data *wd = elm_widget_data_get(obj);
391 if (!wd) return;
392 eina_stringshare_replace(&wd->units, units);
393 if (units)
394 {
395 edje_object_signal_emit(wd->progressbar, "elm,state,units,visible", "elm");
396 edje_object_message_signal_process(wd->progressbar);
397 }
398 else
399 {
400 edje_object_signal_emit(wd->progressbar, "elm,state,units,hidden", "elm");
401 edje_object_message_signal_process(wd->progressbar);
402 }
403 _units_set(obj);
404 _sizing_eval(obj);
405}
406
407EAPI const char *
408elm_progressbar_unit_format_get(const Evas_Object *obj)
409{
410 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
411 Widget_Data *wd = elm_widget_data_get(obj);
412 if (!wd) return NULL;
413 return wd->units;
414}
415
416EAPI void
417elm_progressbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
418{
419 ELM_CHECK_WIDTYPE(obj, widtype);
420 Widget_Data *wd = elm_widget_data_get(obj);
421 if (!wd) return;
422 horizontal = !!horizontal;
423 if (wd->horizontal == horizontal) return;
424 wd->horizontal = horizontal;
425 _theme_hook(obj);
426}
427
428EAPI Eina_Bool
429elm_progressbar_horizontal_get(const Evas_Object *obj)
430{
431 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
432 Widget_Data *wd = elm_widget_data_get(obj);
433 if (!wd) return EINA_FALSE;
434 return wd->horizontal;
435}
436
437EAPI void
438elm_progressbar_inverted_set(Evas_Object *obj, Eina_Bool inverted)
439{
440 ELM_CHECK_WIDTYPE(obj, widtype);
441 Widget_Data *wd = elm_widget_data_get(obj);
442 if (!wd) return;
443 inverted = !!inverted;
444 if (wd->inverted == inverted) return;
445 wd->inverted = inverted;
446 if (wd->inverted)
447 edje_object_signal_emit(wd->progressbar, "elm,state,inverted,on", "elm");
448 else
449 edje_object_signal_emit(wd->progressbar, "elm,state,inverted,off", "elm");
450 edje_object_message_signal_process(wd->progressbar);
451 _val_set(obj);
452 _units_set(obj);
453}
454
455EAPI Eina_Bool
456elm_progressbar_inverted_get(const Evas_Object *obj)
457{
458 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
459 Widget_Data *wd = elm_widget_data_get(obj);
460 if (!wd) return EINA_FALSE;
461 return wd->inverted;
462}
diff --git a/libraries/elementary/src/lib/elm_progressbar.h b/libraries/elementary/src/lib/elm_progressbar.h
new file mode 100644
index 0000000..5b08d72
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_progressbar.h
@@ -0,0 +1,289 @@
1/**
2 * @defgroup Progressbar Progress bar
3 * @ingroup Elementary
4 *
5 * The progress bar is a widget for visually representing the
6 * progress status of a given job/task.
7 *
8 * A progress bar may be horizontal or vertical. It may display an
9 * icon besides it, as well as primary and @b units labels. The
10 * former is meant to label the widget as a whole, while the
11 * latter, which is formatted with floating point values (and thus
12 * accepts a <c>printf</c>-style format string, like <c>"%1.2f
13 * units"</c>), is meant to label the widget's <b>progress
14 * value</b>. Label, icon and unit strings/objects are @b optional
15 * for progress bars.
16 *
17 * A progress bar may be @b inverted, in which case it gets its
18 * values inverted, i.e., high values being on the left or top and
19 * low values on the right or bottom, for horizontal and vertical modes
20 * respectively.
21 *
22 * The @b span of the progress, as set by
23 * elm_progressbar_span_size_set(), is its length (horizontally or
24 * vertically), unless one puts size hints on the widget to expand
25 * on desired directions, by any container. That length will be
26 * scaled by the object or applications scaling factor.
27 * Applications can query the progress bar for its value with
28 * elm_progressbar_value_get().
29 *
30 * Available widget styles for progress bars:
31 * - @c "default"
32 * - @c "wheel" (simple style, no text, no progression, only
33 * "pulse" effect is available)
34 *
35 * Default text parts of the progressbar widget that you can use for are:
36 * @li "default" - Label of the progressbar
37 *
38 * Default content parts of the progressbar widget that you can use for are:
39 * @li "icon" - An icon of the progressbar
40 *
41 * Supported elm_object common APIs.
42 * @li @ref elm_object_part_text_set
43 * @li @ref elm_object_part_text_get
44 * @li @ref elm_object_part_content_set
45 * @li @ref elm_object_part_content_get
46 * @li @ref elm_object_part_content_unset
47 *
48 * Here is an example on its usage:
49 * @li @ref progressbar_example
50 */
51
52/**
53 * Add a new progress bar widget to the given parent Elementary
54 * (container) object
55 *
56 * @param parent The parent object
57 * @return a new progress bar widget handle or @c NULL, on errors
58 *
59 * This function inserts a new progress bar widget on the canvas.
60 *
61 * @ingroup Progressbar
62 */
63EAPI Evas_Object *elm_progressbar_add(Evas_Object *parent);
64
65/**
66 * Set whether a given progress bar widget is at "pulsing mode" or
67 * not.
68 *
69 * @param obj The progress bar object
70 * @param pulse @c EINA_TRUE to put @p obj in pulsing mode,
71 * @c EINA_FALSE to put it back to its default one
72 *
73 * By default, progress bars will display values from the low to
74 * high value boundaries. There are, though, contexts in which the
75 * progress of a given task is @b unknown. For such cases,
76 * one can set a progress bar widget to a "pulsing state", to give
77 * the user an idea that some computation is being held, but
78 * without exact progress values. In the default theme, it will
79 * animate its bar with the contents filling in constantly and back
80 * to non-filled, in a loop. To start and stop this pulsing
81 * animation, one has to explicitly call elm_progressbar_pulse().
82 *
83 * @see elm_progressbar_pulse_get()
84 * @see elm_progressbar_pulse()
85 *
86 * @ingroup Progressbar
87 */
88EAPI void elm_progressbar_pulse_set(Evas_Object *obj, Eina_Bool pulse);
89
90/**
91 * Get whether a given progress bar widget is at "pulsing mode" or
92 * not.
93 *
94 * @param obj The progress bar object
95 * @return @c EINA_TRUE, if @p obj is in pulsing mode, @c EINA_FALSE
96 * if it's in the default one (and on errors)
97 *
98 * @ingroup Progressbar
99 */
100EAPI Eina_Bool elm_progressbar_pulse_get(const Evas_Object *obj);
101
102/**
103 * Start/stop a given progress bar "pulsing" animation, if its
104 * under that mode
105 *
106 * @param obj The progress bar object
107 * @param state @c EINA_TRUE, to @b start the pulsing animation,
108 * @c EINA_FALSE to @b stop it
109 *
110 * @note This call won't do anything if @p obj is not under "pulsing mode".
111 *
112 * @see elm_progressbar_pulse_set() for more details.
113 *
114 * @ingroup Progressbar
115 */
116EAPI void elm_progressbar_pulse(Evas_Object *obj, Eina_Bool state);
117
118/**
119 * Set the progress value (in percentage) on a given progress bar
120 * widget
121 *
122 * @param obj The progress bar object
123 * @param val The progress value (@b must be between @c 0.0 and @c
124 * 1.0)
125 *
126 * Use this call to set progress bar levels.
127 *
128 * @note If you passes a value out of the specified range for @p
129 * val, it will be interpreted as the @b closest of the @b boundary
130 * values in the range.
131 *
132 * @ingroup Progressbar
133 */
134EAPI void elm_progressbar_value_set(Evas_Object *obj, double val);
135
136/**
137 * Get the progress value (in percentage) on a given progress bar
138 * widget
139 *
140 * @param obj The progress bar object
141 * @return The value of the progressbar
142 *
143 * @see elm_progressbar_value_set() for more details
144 *
145 * @ingroup Progressbar
146 */
147EAPI double elm_progressbar_value_get(const Evas_Object *obj);
148
149/**
150 * Set the (exact) length of the bar region of a given progress bar
151 * widget
152 *
153 * @param obj The progress bar object
154 * @param size The length of the progress bar's bar region
155 *
156 * This sets the minimum width (when in horizontal mode) or height
157 * (when in vertical mode) of the actual bar area of the progress
158 * bar @p obj. This in turn affects the object's minimum size. Use
159 * this when you're not setting other size hints expanding on the
160 * given direction (like weight and alignment hints) and you would
161 * like it to have a specific size.
162 *
163 * @note Icon, label and unit text around @p obj will require their
164 * own space, which will make @p obj to require more the @p size,
165 * actually.
166 *
167 * @see elm_progressbar_span_size_get()
168 *
169 * @ingroup Progressbar
170 */
171EAPI void elm_progressbar_span_size_set(Evas_Object *obj, Evas_Coord size);
172
173/**
174 * Get the length set for the bar region of a given progress bar
175 * widget
176 *
177 * @param obj The progress bar object
178 * @return The length of the progress bar's bar region
179 *
180 * If that size was not set previously, with
181 * elm_progressbar_span_size_set(), this call will return @c 0.
182 *
183 * @ingroup Progressbar
184 */
185EAPI Evas_Coord elm_progressbar_span_size_get(const Evas_Object *obj);
186
187/**
188 * Set the format string for a given progress bar widget's units
189 * label
190 *
191 * @param obj The progress bar object
192 * @param format The format string for @p obj's units label
193 *
194 * If @c NULL is passed on @p format, it will make @p obj's units
195 * area to be hidden completely. If not, it'll set the <b>format
196 * string</b> for the units label's @b text. The units label is
197 * provided a floating point value, so the units text is up display
198 * at most one floating point value. Note that the units label is
199 * optional. Use a format string such as "%1.2f meters" for
200 * example.
201 *
202 * @note The default format string for a progress bar is an integer
203 * percentage, as in @c "%.0f %%".
204 *
205 * @see elm_progressbar_unit_format_get()
206 *
207 * @ingroup Progressbar
208 */
209EAPI void elm_progressbar_unit_format_set(Evas_Object *obj, const char *format);
210
211/**
212 * Retrieve the format string set for a given progress bar widget's
213 * units label
214 *
215 * @param obj The progress bar object
216 * @return The format set string for @p obj's units label or
217 * @c NULL, if none was set (and on errors)
218 *
219 * @see elm_progressbar_unit_format_set() for more details
220 *
221 * @ingroup Progressbar
222 */
223EAPI const char *elm_progressbar_unit_format_get(const Evas_Object *obj);
224
225/**
226 * Set the orientation of a given progress bar widget
227 *
228 * @param obj The progress bar object
229 * @param horizontal Use @c EINA_TRUE to make @p obj to be
230 * @b horizontal, @c EINA_FALSE to make it @b vertical
231 *
232 * Use this function to change how your progress bar is to be
233 * disposed: vertically or horizontally.
234 *
235 * @see elm_progressbar_horizontal_get()
236 *
237 * @ingroup Progressbar
238 */
239EAPI void elm_progressbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
240
241/**
242 * Retrieve the orientation of a given progress bar widget
243 *
244 * @param obj The progress bar object
245 * @return @c EINA_TRUE, if @p obj is set to be @b horizontal,
246 * @c EINA_FALSE if it's @b vertical (and on errors)
247 *
248 * @see elm_progressbar_horizontal_set() for more details
249 *
250 * @ingroup Progressbar
251 */
252EAPI Eina_Bool elm_progressbar_horizontal_get(const Evas_Object *obj);
253
254/**
255 * Invert a given progress bar widget's displaying values order
256 *
257 * @param obj The progress bar object
258 * @param inverted Use @c EINA_TRUE to make @p obj inverted,
259 * @c EINA_FALSE to bring it back to default, non-inverted values.
260 *
261 * A progress bar may be @b inverted, in which state it gets its
262 * values inverted, with high values being on the left or top and
263 * low values on the right or bottom, as opposed to normally have
264 * the low values on the former and high values on the latter,
265 * respectively, for horizontal and vertical modes.
266 *
267 * @see elm_progressbar_inverted_get()
268 *
269 * @ingroup Progressbar
270 */
271EAPI void elm_progressbar_inverted_set(Evas_Object *obj, Eina_Bool inverted);
272
273/**
274 * Get whether a given progress bar widget's displaying values are
275 * inverted or not
276 *
277 * @param obj The progress bar object
278 * @return @c EINA_TRUE, if @p obj has inverted values,
279 * @c EINA_FALSE otherwise (and on errors)
280 *
281 * @see elm_progressbar_inverted_set() for more details
282 *
283 * @ingroup Progressbar
284 */
285EAPI Eina_Bool elm_progressbar_inverted_get(const Evas_Object *obj);
286
287/**
288 * @}
289 */
diff --git a/libraries/elementary/src/lib/elm_radio.c b/libraries/elementary/src/lib/elm_radio.c
new file mode 100644
index 0000000..0f6c0f6
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_radio.c
@@ -0,0 +1,520 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Group Group;
6
7struct _Group
8{
9 int value;
10 int *valuep;
11 Eina_List *radios;
12};
13
14struct _Widget_Data
15{
16 Evas_Object *radio;
17 Evas_Object *icon;
18 int value;
19 const char *label;
20 Eina_Bool state;
21 Group *group;
22};
23
24static const char *widtype = NULL;
25static void _state_set(Evas_Object *obj, Eina_Bool state);
26static void _del_hook(Evas_Object *obj);
27static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
28static void _theme_hook(Evas_Object *obj);
29static void _disable_hook(Evas_Object *obj);
30static void _sizing_eval(Evas_Object *obj);
31static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
32static void _sub_del(void *data, Evas_Object *obj, void *event_info);
33static void _signal_radio_on(void *data, Evas_Object *obj, const char *emission, const char *source);
34static void _on_focus_hook(void *data, Evas_Object *obj);
35static void _activate(Evas_Object *obj);
36static void _activate_hook(Evas_Object *obj);
37static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
38 Evas_Callback_Type type, void *event_info);
39
40static const char SIG_CHANGED[] = "changed";
41static const Evas_Smart_Cb_Description _signals[] = {
42 {SIG_CHANGED, ""},
43 {NULL, NULL}
44};
45
46static Eina_Bool
47_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
48{
49 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
50 Evas_Event_Key_Down *ev = event_info;
51 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
52 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
53
54 if ((strcmp(ev->keyname, "Return")) &&
55 (strcmp(ev->keyname, "KP_Enter")) &&
56 (strcmp(ev->keyname, "space")))
57 return EINA_FALSE;
58 _activate(obj);
59 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
60 return EINA_TRUE;
61}
62
63static void
64_del_hook(Evas_Object *obj)
65{
66 Widget_Data *wd = elm_widget_data_get(obj);
67 if (!wd) return;
68 if (wd->label) eina_stringshare_del(wd->label);
69 wd->group->radios = eina_list_remove(wd->group->radios, obj);
70 if (!wd->group->radios) free(wd->group);
71 wd->group = NULL;
72 free(wd);
73}
74
75static void
76_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
77{
78 Widget_Data *wd = elm_widget_data_get(obj);
79 if (!wd) return;
80 if (elm_widget_focus_get(obj))
81 {
82 edje_object_signal_emit(wd->radio, "elm,action,focus", "elm");
83 evas_object_focus_set(wd->radio, EINA_TRUE);
84 }
85 else
86 {
87 edje_object_signal_emit(wd->radio, "elm,action,unfocus", "elm");
88 evas_object_focus_set(wd->radio, EINA_FALSE);
89 }
90}
91
92static void
93_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
94{
95 Widget_Data *wd = elm_widget_data_get(obj);
96 if (!wd) return;
97 edje_object_mirrored_set(wd->radio, rtl);
98}
99
100static void
101_theme_hook(Evas_Object *obj)
102{
103 Widget_Data *wd = elm_widget_data_get(obj);
104 if (!wd) return;
105 _elm_widget_mirrored_reload(obj);
106 _mirrored_set(obj, elm_widget_mirrored_get(obj));
107 _elm_theme_object_set(obj, wd->radio, "radio", "base", elm_widget_style_get(obj));
108 if (wd->icon)
109 edje_object_signal_emit(wd->radio, "elm,state,icon,visible", "elm");
110 else
111 edje_object_signal_emit(wd->radio, "elm,state,icon,hidden", "elm");
112 if (wd->state)
113 edje_object_signal_emit(wd->radio, "elm,state,radio,on", "elm");
114 else
115 edje_object_signal_emit(wd->radio, "elm,state,radio,off", "elm");
116 if (wd->label)
117 edje_object_signal_emit(wd->radio, "elm,state,text,visible", "elm");
118 else
119 edje_object_signal_emit(wd->radio, "elm,state,text,hidden", "elm");
120 edje_object_part_text_escaped_set(wd->radio, "elm.text", wd->label);
121 if (elm_widget_disabled_get(obj))
122 {
123 edje_object_signal_emit(wd->radio, "elm,state,disabled", "elm");
124 if (wd->state) _state_set(obj, 0);
125 }
126 edje_object_message_signal_process(wd->radio);
127 edje_object_scale_set(wd->radio, elm_widget_scale_get(obj) * _elm_config->scale);
128 _sizing_eval(obj);
129}
130
131static void
132_disable_hook(Evas_Object *obj)
133{
134 Widget_Data *wd = elm_widget_data_get(obj);
135 if (!wd) return;
136 if (elm_widget_disabled_get(obj))
137 {
138 edje_object_signal_emit(wd->radio, "elm,state,disabled", "elm");
139 if (wd->state) _state_set(obj, 0);
140 }
141 else
142 edje_object_signal_emit(wd->radio, "elm,state,enabled", "elm");
143}
144
145static void
146_sizing_eval(Evas_Object *obj)
147{
148 Widget_Data *wd = elm_widget_data_get(obj);
149 Evas_Coord minw = -1, minh = -1;
150 if (!wd) return;
151 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
152 edje_object_size_min_restricted_calc(wd->radio, &minw, &minh, minw, minh);
153 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
154 evas_object_size_hint_min_set(obj, minw, minh);
155 evas_object_size_hint_max_set(obj, -1, -1);
156}
157
158static void
159_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
160{
161 Widget_Data *wd = elm_widget_data_get(data);
162 if (!wd) return;
163 if (obj != wd->icon) return;
164 _sizing_eval(data);
165}
166
167static void
168_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
169{
170 Widget_Data *wd = elm_widget_data_get(obj);
171 Evas_Object *sub = event_info;
172 if (!wd) return;
173 if (sub == wd->icon)
174 {
175 edje_object_signal_emit(wd->radio, "elm,state,icon,hidden", "elm");
176 evas_object_event_callback_del_full
177 (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
178 wd->icon = NULL;
179 _sizing_eval(obj);
180 }
181}
182
183static void
184_state_set(Evas_Object *obj, Eina_Bool state)
185{
186 Widget_Data *wd = elm_widget_data_get(obj);
187 if (!wd) return;
188 if ((state != wd->state) && (!elm_widget_disabled_get(obj)))
189 {
190 wd->state = state;
191 if (wd->state)
192 edje_object_signal_emit(wd->radio, "elm,state,radio,on", "elm");
193 else
194 edje_object_signal_emit(wd->radio, "elm,state,radio,off", "elm");
195 }
196}
197
198static void
199_state_set_all(Widget_Data *wd)
200{
201 const Eina_List *l;
202 Evas_Object *child, *selected = NULL;
203 Eina_Bool disabled = EINA_FALSE;
204 EINA_LIST_FOREACH(wd->group->radios, l, child)
205 {
206 Widget_Data *wd2 = elm_widget_data_get(child);
207 if (wd2->state) selected = child;
208 if (wd2->value == wd->group->value)
209 {
210 _state_set(child, 1);
211 if (!wd2->state) disabled = EINA_TRUE;
212 }
213 else _state_set(child, 0);
214 }
215 if ((disabled) && (selected)) _state_set(selected, 1);
216}
217
218static void
219_activate(Evas_Object *obj)
220{
221 Widget_Data *wd = elm_widget_data_get(obj);
222 if (!wd) return;
223 if (wd->group->value == wd->value) return;
224 if ((_elm_config->access_mode == ELM_ACCESS_MODE_OFF) ||
225 (_elm_access_2nd_click_timeout(obj)))
226 {
227 wd->group->value = wd->value;
228 if (wd->group->valuep) *(wd->group->valuep) = wd->group->value;
229 _state_set_all(wd);
230 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
231 _elm_access_say(E_("State: On"));
232 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
233 }
234}
235
236static void
237_activate_hook(Evas_Object *obj)
238{
239 _activate(obj);
240}
241
242static void
243_signal_radio_on(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
244{
245 _activate(data);
246}
247
248static void
249_elm_radio_label_set(Evas_Object *obj, const char *item, const char *label)
250{
251 ELM_CHECK_WIDTYPE(obj, widtype);
252 Widget_Data *wd = elm_widget_data_get(obj);
253 if (item && strcmp(item, "default")) return;
254 if (!wd) return;
255 eina_stringshare_replace(&wd->label, label);
256 if (label)
257 {
258 edje_object_signal_emit(wd->radio, "elm,state,text,visible", "elm");
259 edje_object_message_signal_process(wd->radio);
260 }
261 else
262 {
263 edje_object_signal_emit(wd->radio, "elm,state,text,hidden", "elm");
264 edje_object_message_signal_process(wd->radio);
265 }
266 edje_object_part_text_escaped_set(wd->radio, "elm.text", label);
267 _sizing_eval(obj);
268}
269
270static const char *
271_elm_radio_label_get(const Evas_Object *obj, const char *item)
272{
273 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
274 Widget_Data *wd = elm_widget_data_get(obj);
275 if (item && strcmp(item, "default")) return NULL;
276 if (!wd) return NULL;
277 return wd->label;
278}
279
280static char *
281_access_info_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Widget_Item *item __UNUSED__)
282{
283 const char *txt = elm_widget_access_info_get(obj);
284 if (!txt) txt = _elm_radio_label_get(obj, NULL);
285 if (txt) return strdup(txt);
286 return NULL;
287}
288
289static char *
290_access_state_cb(void *data __UNUSED__, Evas_Object *obj, Elm_Widget_Item *item __UNUSED__)
291{
292 Widget_Data *wd = elm_widget_data_get(obj);
293 if (!wd) return NULL;
294 if (elm_widget_disabled_get(obj))
295 return strdup(E_("State: Disabled"));
296 if (wd->state)
297 return strdup(E_("State: On"));
298 return strdup(E_("State: Off"));
299}
300
301static void
302_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
303{
304 ELM_CHECK_WIDTYPE(obj, widtype);
305 Widget_Data *wd;
306
307 if (part && strcmp(part, "icon")) return;
308 wd = elm_widget_data_get(obj);
309 if (!wd) return;
310 if (wd->icon == content) return;
311 if (wd->icon) evas_object_del(wd->icon);
312 wd->icon = content;
313 if (content)
314 {
315 elm_widget_sub_object_add(obj, content);
316 evas_object_event_callback_add(content,
317 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
318 _changed_size_hints, obj);
319 edje_object_part_swallow(wd->radio, "elm.swallow.content", content);
320 edje_object_signal_emit(wd->radio, "elm,state,icon,visible", "elm");
321 edje_object_message_signal_process(wd->radio);
322 }
323 _sizing_eval(obj);
324}
325
326static Evas_Object *
327_content_get_hook(const Evas_Object *obj, const char *part)
328{
329 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
330 Widget_Data *wd;
331
332 if (part && strcmp(part, "icon")) return NULL;
333 wd = elm_widget_data_get(obj);
334 if (!wd) return NULL;
335 return wd->icon;
336}
337
338static Evas_Object *
339_content_unset_hook(Evas_Object *obj, const char *part)
340{
341 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
342 Widget_Data *wd;
343 Evas_Object *icon;
344 if (part && strcmp(part, "icon")) return NULL;
345 wd = elm_widget_data_get(obj);
346 if (!wd) return NULL;
347 if (!wd->icon) return NULL;
348 icon = wd->icon;
349 elm_widget_sub_object_del(obj, wd->icon);
350 evas_object_event_callback_del_full(wd->icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
351 _changed_size_hints, obj);
352 edje_object_part_unswallow(wd->radio, wd->icon);
353 wd->icon = NULL;
354 return icon;
355}
356
357EAPI Evas_Object *
358elm_radio_add(Evas_Object *parent)
359{
360 Evas_Object *obj;
361 Evas *e;
362 Widget_Data *wd;
363
364 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
365
366 ELM_SET_WIDTYPE(widtype, "radio");
367 elm_widget_type_set(obj, "radio");
368 elm_widget_sub_object_add(parent, obj);
369 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
370 elm_widget_data_set(obj, wd);
371 elm_widget_del_hook_set(obj, _del_hook);
372 elm_widget_theme_hook_set(obj, _theme_hook);
373 elm_widget_disable_hook_set(obj, _disable_hook);
374 elm_widget_can_focus_set(obj, EINA_TRUE);
375 elm_widget_activate_hook_set(obj, _activate_hook);
376 elm_widget_event_hook_set(obj, _event_hook);
377 elm_widget_text_set_hook_set(obj, _elm_radio_label_set);
378 elm_widget_text_get_hook_set(obj, _elm_radio_label_get);
379 elm_widget_content_set_hook_set(obj, _content_set_hook);
380 elm_widget_content_get_hook_set(obj, _content_get_hook);
381 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
382
383 wd->radio = edje_object_add(e);
384 _elm_theme_object_set(obj, wd->radio, "radio", "base", "default");
385 edje_object_signal_callback_add(wd->radio, "elm,action,radio,on", "", _signal_radio_on, obj);
386 edje_object_signal_callback_add(wd->radio, "elm,action,radio,toggle", "", _signal_radio_on, obj);
387 elm_widget_resize_object_set(obj, wd->radio);
388
389 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
390
391 wd->group = calloc(1, sizeof(Group));
392 wd->group->radios = eina_list_append(wd->group->radios, obj);
393 wd->state = 0;
394
395 _mirrored_set(obj, elm_widget_mirrored_get(obj));
396 _sizing_eval(obj);
397
398 // TODO: convert Elementary to subclassing of Evas_Smart_Class
399 // TODO: and save some bytes, making descriptions per-class and not instance!
400 evas_object_smart_callbacks_descriptions_set(obj, _signals);
401
402 _elm_access_object_register(obj, wd->radio);
403 _elm_access_text_set(_elm_access_object_get(obj),
404 ELM_ACCESS_TYPE, E_("Radio"));
405 _elm_access_callback_set(_elm_access_object_get(obj),
406 ELM_ACCESS_INFO, _access_info_cb, obj);
407 _elm_access_callback_set(_elm_access_object_get(obj),
408 ELM_ACCESS_STATE, _access_state_cb, obj);
409
410 return obj;
411}
412
413EAPI void
414elm_radio_group_add(Evas_Object *obj, Evas_Object *group)
415{
416 ELM_CHECK_WIDTYPE(obj, widtype);
417 Widget_Data *wd = elm_widget_data_get(obj);
418 Widget_Data *wd2 = elm_widget_data_get(group);
419 if (!wd) return;
420 if (!wd2)
421 {
422 if (eina_list_count(wd->group->radios) == 1)
423 return;
424 wd->group->radios = eina_list_remove(wd->group->radios, obj);
425 wd->group = calloc(1, sizeof(Group));
426 wd->group->radios = eina_list_append(wd->group->radios, obj);
427 }
428 else if (wd->group == wd2->group) return;
429 else
430 {
431 wd->group->radios = eina_list_remove(wd->group->radios, obj);
432 if (!wd->group->radios) free(wd->group);
433 wd->group = wd2->group;
434 wd->group->radios = eina_list_append(wd->group->radios, obj);
435 }
436 if (wd->value == wd->group->value) _state_set(obj, 1);
437 else _state_set(obj, 0);
438}
439
440EAPI void
441elm_radio_state_value_set(Evas_Object *obj, int value)
442{
443 ELM_CHECK_WIDTYPE(obj, widtype);
444 Widget_Data *wd = elm_widget_data_get(obj);
445 if (!wd) return;
446 wd->value = value;
447 if (wd->value == wd->group->value) _state_set(obj, 1);
448 else _state_set(obj, 0);
449}
450
451EAPI int
452elm_radio_state_value_get(const Evas_Object *obj)
453{
454 ELM_CHECK_WIDTYPE(obj, widtype) 0;
455 Widget_Data *wd = elm_widget_data_get(obj);
456 if (!wd) return 0;
457 return wd->value;
458}
459
460EAPI void
461elm_radio_value_set(Evas_Object *obj, int value)
462{
463 ELM_CHECK_WIDTYPE(obj, widtype);
464 Widget_Data *wd = elm_widget_data_get(obj);
465 if (!wd) return;
466 if (value == wd->group->value) return;
467 wd->group->value = value;
468 if (wd->group->valuep) *(wd->group->valuep) = wd->group->value;
469 _state_set_all(wd);
470}
471
472EAPI int
473elm_radio_value_get(const Evas_Object *obj)
474{
475 ELM_CHECK_WIDTYPE(obj, widtype) 0;
476 Widget_Data *wd = elm_widget_data_get(obj);
477 if (!wd) return 0;
478 return wd->group->value;
479}
480
481EAPI void
482elm_radio_value_pointer_set(Evas_Object *obj, int *valuep)
483{
484 ELM_CHECK_WIDTYPE(obj, widtype);
485 Widget_Data *wd = elm_widget_data_get(obj);
486 if (!wd) return;
487 if (valuep)
488 {
489 wd->group->valuep = valuep;
490 if (*(wd->group->valuep) != wd->group->value)
491 {
492 wd->group->value = *(wd->group->valuep);
493 _state_set_all(wd);
494 }
495 }
496 else
497 {
498 wd->group->valuep = NULL;
499 }
500}
501
502EAPI Evas_Object *
503elm_radio_selected_object_get(Evas_Object *obj)
504{
505 Eina_List *l;
506 Evas_Object *child;
507 Widget_Data *wd2;
508
509 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
510 Widget_Data *wd = elm_widget_data_get(obj);
511 if (!wd) return NULL;
512
513 EINA_LIST_FOREACH(wd->group->radios, l, child)
514 {
515 wd2 = elm_widget_data_get(child);
516 if (wd2->value == wd->group->value)
517 return child;
518 }
519 return NULL;
520}
diff --git a/libraries/elementary/src/lib/elm_radio.h b/libraries/elementary/src/lib/elm_radio.h
new file mode 100644
index 0000000..388e720
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_radio.h
@@ -0,0 +1,159 @@
1/**
2 * @defgroup Radio Radio
3 * @ingroup Elementary
4 *
5 * @image html img/widget/radio/preview-00.png
6 * @image latex img/widget/radio/preview-00.eps
7 *
8 * @brief Radio is a widget that allows for 1 or more options to be displayed
9 * and have the user choose only 1 of them.
10 *
11 * A radio object contains an indicator, an optional Label and an optional
12 * icon object. While it's possible to have a group of only one radio they,
13 * are normally used in groups of 2 or more.
14 *
15 * elm_radio objects are grouped in a slightly different, compared to other
16 * UI toolkits. There is no seperate group name/id to remember or manage.
17 * The members represent the group, there are the group. To make a group,
18 * use elm_radio_group_add() and pass existing radio object and the new radio
19 * object.
20 *
21 * The radio object(s) will select from one of a set
22 * of integer values, so any value they are configuring needs to be mapped to
23 * a set of integers. To configure what value that radio object represents,
24 * use elm_radio_state_value_set() to set the integer it represents. To set
25 * the value the whole group(which one is currently selected) is to indicate
26 * use elm_radio_value_set() on any group member, and to get the groups value
27 * use elm_radio_value_get(). For convenience the radio objects are also able
28 * to directly set an integer(int) to the value that is selected. To specify
29 * the pointer to this integer to modify, use elm_radio_value_pointer_set().
30 * The radio objects will modify this directly. That implies the pointer must
31 * point to valid memory for as long as the radio objects exist.
32 *
33 * Signals that you can add callbacks for are:
34 * @li changed - This is called whenever the user changes the state of one of
35 * the radio objects within the group of radio objects that work together.
36 *
37 * Default text parts of the radio widget that you can use for are:
38 * @li "default" - Label of the radio
39 *
40 * Default content parts of the radio widget that you can use for are:
41 * @li "icon" - An icon of the radio
42 *
43 * Supported elm_object common APIs.
44 * @li @ref elm_object_part_text_set
45 * @li @ref elm_object_part_text_get
46 * @li @ref elm_object_part_content_set
47 * @li @ref elm_object_part_content_get
48 * @li @ref elm_object_part_content_unset
49 * @li @ref elm_object_disabled_set
50 * @li @ref elm_object_disabled_get
51 *
52 * @ref tutorial_radio show most of this API in action.
53 * @{
54 */
55
56/**
57 * @brief Add a new radio to the parent
58 *
59 * @param parent The parent object
60 * @return The new object or NULL if it cannot be created
61 *
62 * @ingroup Radio
63 */
64EAPI Evas_Object *elm_radio_add(Evas_Object *parent);
65
66/**
67 * @brief Add this radio to a group of other radio objects
68 *
69 * @param obj The radio object
70 * @param group Any object whose group the @p obj is to join.
71 *
72 * Radio objects work in groups. Each member should have a different integer
73 * value assigned. In order to have them work as a group, they need to know
74 * about each other. This adds the given radio object to the group of which
75 * the group object indicated is a member.
76 *
77 * @ingroup Radio
78 */
79EAPI void elm_radio_group_add(Evas_Object *obj, Evas_Object *group);
80
81/**
82 * @brief Set the integer value that this radio object represents
83 *
84 * @param obj The radio object
85 * @param value The value to use if this radio object is selected
86 *
87 * This sets the value of the radio.
88 *
89 * @ingroup Radio
90 */
91EAPI void elm_radio_state_value_set(Evas_Object *obj, int value);
92
93/**
94 * @brief Get the integer value that this radio object represents
95 *
96 * @param obj The radio object
97 * @return The value used if this radio object is selected
98 *
99 * This gets the value of the radio.
100 * @see elm_radio_value_set()
101 *
102 * @ingroup Radio
103 */
104EAPI int elm_radio_state_value_get(const Evas_Object *obj);
105
106/**
107 * @brief Set the value of the radio group.
108 *
109 * @param obj The radio object (any radio object of the group).
110 * @param value The value to use for the group
111 *
112 * This sets the value of the radio group and will also set the value if
113 * pointed to, to the value supplied, but will not call any callbacks.
114 *
115 * @ingroup Radio
116 */
117EAPI void elm_radio_value_set(Evas_Object *obj, int value);
118
119/**
120 * @brief Get the value of the radio group
121 *
122 * @param obj The radio object (any radio object of the group).
123 * @return The integer state
124 *
125 * @ingroup Radio
126 */
127EAPI int elm_radio_value_get(const Evas_Object *obj);
128
129/**
130 * @brief Set a convenience pointer to a integer to change when radio group
131 * value changes.
132 *
133 * @param obj The radio object (any object of a group)
134 * @param valuep Pointer to the integer to modify
135 *
136 * This sets a pointer to a integer, that, in addition to the radio objects
137 * state will also be modified directly. To stop setting the object pointed
138 * to simply use NULL as the @p valuep argument. If valuep is not NULL, then
139 * when this is called, the radio objects state will also be modified to
140 * reflect the value of the integer valuep points to, just like calling
141 * elm_radio_value_set().
142 *
143 * @ingroup Radio
144 */
145EAPI void elm_radio_value_pointer_set(Evas_Object *obj, int *valuep);
146
147/**
148 * @brief Get the selected radio object.
149 *
150 * @param obj Any radio object (any object of a group)
151 * @return The selected radio object
152 *
153 * @ingroup Radio
154 */
155EAPI Evas_Object *elm_radio_selected_object_get(Evas_Object *obj);
156
157/**
158 * @}
159 */
diff --git a/libraries/elementary/src/lib/elm_route.c b/libraries/elementary/src/lib/elm_route.c
new file mode 100644
index 0000000..cae5074
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_route.c
@@ -0,0 +1,286 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4/**
5 * @defgroup Route MapRoute
6 *
7 * For displaying a route on the map widget
8 *
9 */
10
11typedef struct _Widget_Data Widget_Data;
12typedef struct Segment Segment;
13
14struct _Widget_Data
15{
16 Evas_Object *obj;
17#ifdef ELM_EMAP
18 EMap_Route *emap;
19#endif
20
21 double lon_min, lon_max;
22 double lat_min, lat_max;
23
24 Eina_List *segments; //list of *Segment
25
26 Eina_Bool must_calc_segments :1;
27};
28
29struct Segment
30{
31 Evas_Object *obj;
32
33#ifdef ELM_EMAP
34 EMap_Route_Node *node_start;
35 EMap_Route_Node *node_end;
36#endif
37
38 double start_x, start_y;
39 double end_x, end_y;
40
41 Eina_Bool must_calc :1;
42};
43
44static const char *widtype = NULL;
45static void _del_hook(Evas_Object *obj);
46static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
47static void _theme_hook(Evas_Object *obj);
48static void _sizing_eval(Evas_Object *obj);
49static void _clear_route(Evas_Object *obj);
50#ifdef ELM_EMAP
51static void _update_lon_lat_min_max(Evas_Object *obj, double lon, double lat);
52#endif
53
54static void
55_del_hook(Evas_Object *obj)
56{
57 Widget_Data *wd = elm_widget_data_get(obj);
58 if (!wd) return;
59
60 _clear_route(obj);
61
62 free(wd);
63}
64
65static void
66_resize_cb(void *data __UNUSED__ , Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
67{
68 _sizing_eval(obj);
69}
70
71static void
72_mirrored_set(Evas_Object *obj, Eina_Bool rtl __UNUSED__)
73{
74 Widget_Data *wd = elm_widget_data_get(obj);
75 if (!wd) return;
76}
77
78static void
79_theme_hook(Evas_Object *obj)
80{
81 Widget_Data *wd = elm_widget_data_get(obj);
82 if (!wd) return;
83 //TODO
84 _sizing_eval(obj);
85}
86
87static void
88_sizing_eval(Evas_Object *obj)
89{
90 Eina_List *l;
91 Segment *segment;
92 Evas_Coord x, y, w, h;
93 Evas_Coord start_x, start_y, end_x, end_y;
94
95 Widget_Data *wd = elm_widget_data_get(obj);
96 evas_object_geometry_get(obj, &x, &y, &w, &h);
97
98 EINA_LIST_FOREACH(wd->segments, l, segment)
99 {
100 if (wd->must_calc_segments || segment->must_calc)
101 {
102
103#ifdef ELM_EMAP
104 segment->start_x = (emap_route_node_lon_get(segment->node_start)- wd->lon_min) / (float)(wd->lon_max - wd->lon_min);
105 segment->start_y = 1 - (emap_route_node_lat_get(segment->node_start) - wd->lat_min) / (float)(wd->lat_max - wd->lat_min);
106 segment->end_x = (emap_route_node_lon_get(segment->node_end) - wd->lon_min) / (float)(wd->lon_max - wd->lon_min);
107 segment->end_y = 1 - (emap_route_node_lat_get(segment->node_end) - wd->lat_min) / (float)(wd->lat_max - wd->lat_min);
108#endif
109 segment->must_calc = EINA_FALSE;
110 }
111
112 start_x = x+(int)(segment->start_x*w);
113 start_y = y+(int)(segment->start_y*h);
114 end_x = x+(int)(segment->end_x*w);
115 end_y = y+(int)(segment->end_y*h);
116 evas_object_line_xy_set(segment->obj, start_x, start_y, end_x, end_y);
117 }
118
119 wd->must_calc_segments = EINA_FALSE;
120}
121
122static void
123_clear_route(Evas_Object *obj)
124{
125 Segment *segment;
126 Widget_Data *wd = elm_widget_data_get(obj);
127 if (!wd) return;
128
129#ifdef ELM_EMAP
130 wd->lon_min = EMAP_LON_MAX;
131 wd->lon_max = EMAP_LON_MIN;
132 wd->lat_min = EMAP_LAT_MAX;
133 wd->lat_max = EMAP_LAT_MIN;
134#endif
135
136 EINA_LIST_FREE(wd->segments, segment)
137 {
138 evas_object_del(segment->obj);
139 free(segment);
140 }
141}
142
143#ifdef ELM_EMAP
144static void
145_update_lon_lat_min_max(Evas_Object *obj, double lon, double lat)
146{
147 Widget_Data *wd = elm_widget_data_get(obj);
148
149 if (wd->lon_min > lon)
150 {
151 wd->lon_min = lon;
152 wd->must_calc_segments = EINA_TRUE;
153 }
154 if (wd->lat_min > lat)
155 {
156 wd->lat_min = lat;
157 wd->must_calc_segments = EINA_TRUE;
158 }
159
160 if (wd->lon_max < lon)
161 {
162 wd->lon_max = lon;
163 wd->must_calc_segments = EINA_TRUE;
164 }
165 if (wd->lat_max < lat)
166 {
167 wd->lat_max = lat;
168 wd->must_calc_segments = EINA_TRUE;
169 }
170}
171#endif
172
173/**
174 * Add a new route to the parent
175 *
176 * @param parent The parent object
177 * @return The new object or NULL if it cannot be created
178 *
179 * @ingroup Route
180 */
181EAPI Evas_Object *
182elm_route_add(Evas_Object *parent)
183{
184 Evas_Object *obj;
185 Evas *e;
186 Widget_Data *wd;
187
188 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
189
190 ELM_SET_WIDTYPE(widtype, "map_route");
191 elm_widget_type_set(obj, "map_route");
192 elm_widget_sub_object_add(parent, obj);
193 elm_widget_data_set(obj, wd);
194 elm_widget_del_hook_set(obj, _del_hook);
195 elm_widget_theme_hook_set(obj, _theme_hook);
196 elm_widget_can_focus_set(obj, EINA_FALSE);
197
198 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
199 _resize_cb, obj);
200 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
201 _resize_cb, obj);
202
203#ifdef ELM_EMAP
204 wd->lon_min = EMAP_LON_MAX;
205 wd->lon_max = EMAP_LON_MIN;
206 wd->lat_min = EMAP_LAT_MAX;
207 wd->lat_max = EMAP_LAT_MIN;
208#endif
209
210 _mirrored_set(obj, elm_widget_mirrored_get(obj));
211 _sizing_eval(obj);
212 return obj;
213}
214
215#ifdef ELM_EMAP
216/**
217 * Set the emap object which describes the route
218 *
219 * @param obj The photo object
220 * @param emap the route
221 *
222 * @return (1 = success, 0 = error)
223 *
224 * @ingroup Route
225 */
226EAPI void
227elm_route_emap_set(Evas_Object *obj, EMap_Route *emap)
228{
229 EMap_Route_Node *node, *node_prev = NULL;
230 Evas_Object *o;
231 Eina_List *l;
232
233 ELM_CHECK_WIDTYPE(obj, widtype);
234 Widget_Data *wd = elm_widget_data_get(obj);
235
236 if (!wd) return;
237 wd->emap = emap;
238
239 _clear_route(obj);
240
241 EINA_LIST_FOREACH(emap_route_nodes_get(wd->emap), l, node)
242 {
243 if (node_prev)
244 {
245 Segment *segment = calloc(1, sizeof(Segment));
246 segment->node_start = node_prev;
247 segment->node_end = node;
248
249 o = evas_object_line_add(evas_object_evas_get(obj));
250 segment->obj = o;
251 evas_object_smart_member_add(o, obj);
252
253 segment->must_calc = EINA_TRUE;
254
255 _update_lon_lat_min_max(obj, emap_route_node_lon_get(node_prev), emap_route_node_lat_get(node_prev));
256 _update_lon_lat_min_max(obj, emap_route_node_lon_get(node), emap_route_node_lat_get(node));
257
258 wd->segments = eina_list_append(wd->segments, segment);
259 }
260 node_prev = node;
261 }
262
263 _sizing_eval(obj);
264}
265#endif
266
267EAPI void
268elm_route_longitude_min_max_get(const Evas_Object *obj, double *min, double *max)
269{
270 ELM_CHECK_WIDTYPE(obj, widtype);
271 Widget_Data *wd = elm_widget_data_get(obj);
272 if (!wd) return;
273 if (min) *min = wd->lon_min;
274 if (max) *max = wd->lon_max;
275}
276
277EAPI void
278elm_route_latitude_min_max_get(const Evas_Object *obj, double *min, double *max)
279{
280 ELM_CHECK_WIDTYPE(obj, widtype);
281 Widget_Data *wd = elm_widget_data_get(obj);
282 if (!wd) return;
283 if (min) *min = wd->lat_min;
284 if (max) *max = wd->lat_max;
285}
286/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/elm_route.h b/libraries/elementary/src/lib/elm_route.h
new file mode 100644
index 0000000..5f5f446
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_route.h
@@ -0,0 +1,54 @@
1/**
2 * @defgroup Route Route
3 * @ingroup Elementary
4 *
5 * For displaying a route on the map widget.
6 *
7 * @{
8 */
9
10/**
11 * Add a new route object to the parent's canvas
12 *
13 * @param parent The parent object
14 * @return The new object or NULL if it cannot be created
15 *
16 * @ingroup Route
17 */
18EAPI Evas_Object *elm_route_add(Evas_Object *parent);
19
20#ifdef ELM_EMAP
21EAPI void elm_route_emap_set(Evas_Object *obj, EMap_Route *emap);
22#endif
23
24/**
25 * Get the minimum and maximum values along the longitude.
26 *
27 * @param obj The route object.
28 * @param min Pointer to store the minimum value.
29 * @param max Pointer to store the maximum value.
30 *
31 * @note If only one value is needed, the other pointer can be passed
32 * as @c NULL.
33 *
34 * @ingroup Route
35 */
36EAPI void elm_route_longitude_min_max_get(const Evas_Object *obj, double *min, double *max);
37
38/**
39 * Get the minimum and maximum values along the latitude.
40 *
41 * @param obj The route object.
42 * @param min Pointer to store the minimum value.
43 * @param max Pointer to store the maximum value.
44 *
45 * @note If only one value is needed, the other pointer can be passed
46 * as @c NULL.
47 *
48 * @ingroup Route
49 */
50EAPI void elm_route_latitude_min_max_get(const Evas_Object *obj, double *min, double *max);
51
52/**
53 * @}
54 */
diff --git a/libraries/elementary/src/lib/elm_scale.h b/libraries/elementary/src/lib/elm_scale.h
new file mode 100644
index 0000000..4332e73
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_scale.h
@@ -0,0 +1,36 @@
1/**
2 * @defgroup Scaling Widget Scaling
3 * @ingroup Elementary
4 *
5 * Different widgets can be scaled independently. These functions
6 * allow you to manipulate this scaling on a per-widget basis. The
7 * object and all its children get their scaling factors multiplied
8 * by the scale factor set. This is multiplicative, in that if a
9 * child also has a scale size set it is in turn multiplied by its
10 * parent's scale size. @c 1.0 means “don't scale”, @c 2.0 is
11 * double size, @c 0.5 is half, etc.
12 *
13 * @ref general_functions_example_page "This" example contemplates
14 * some of these functions.
15 */
16
17/**
18 * Set the scaling factor for a given Elementary object
19 *
20 * @param obj The Elementary to operate on
21 * @param scale Scale factor (from @c 0.0 up, with @c 1.0 meaning
22 * no scaling)
23 *
24 * @ingroup Scaling
25 */
26EAPI void elm_object_scale_set(Evas_Object *obj, double scale);
27
28/**
29 * Get the scaling factor for a given Elementary object
30 *
31 * @param obj The object
32 * @return The scaling factor set by elm_object_scale_set()
33 *
34 * @ingroup Scaling
35 */
36EAPI double elm_object_scale_get(const Evas_Object *obj);
diff --git a/libraries/elementary/src/lib/elm_scroll.h b/libraries/elementary/src/lib/elm_scroll.h
new file mode 100644
index 0000000..51a2d4f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_scroll.h
@@ -0,0 +1,114 @@
1/**
2 * @defgroup Scrollhints Scrollhints
3 * @ingroup Elementary
4 *
5 * Objects when inside a scroller can scroll, but this may not always be
6 * desirable in certain situations. This allows an object to hint to itself
7 * and parents to "not scroll" in one of 2 ways. If any child object of a
8 * scroller has pushed a scroll freeze or hold then it affects all parent
9 * scrollers until all children have released them.
10 *
11 * 1. To hold on scrolling. This means just flicking and dragging may no
12 * longer scroll, but pressing/dragging near an edge of the scroller will
13 * still scroll. This is automatically used by the entry object when
14 * selecting text.
15 *
16 * 2. To totally freeze scrolling. This means it stops. until
17 * popped/released.
18 *
19 * @{
20 */
21
22/**
23 * Push the scroll hold by 1
24 *
25 * This increments the scroll hold count by one. If it is more than 0 it will
26 * take effect on the parents of the indicated object.
27 *
28 * @param obj The object
29 * @ingroup Scrollhints
30 */
31EAPI void elm_object_scroll_hold_push(Evas_Object *obj);
32
33/**
34 * Pop the scroll hold by 1
35 *
36 * This decrements the scroll hold count by one. If it is more than 0 it will
37 * take effect on the parents of the indicated object.
38 *
39 * @param obj The object
40 * @ingroup Scrollhints
41 */
42EAPI void elm_object_scroll_hold_pop(Evas_Object *obj);
43
44/**
45 * Push the scroll freeze by 1
46 *
47 * This increments the scroll freeze count by one. If it is more
48 * than 0 it will take effect on the parents of the indicated
49 * object.
50 *
51 * @param obj The object
52 * @ingroup Scrollhints
53 */
54EAPI void elm_object_scroll_freeze_push(Evas_Object *obj);
55
56/**
57 * Pop the scroll freeze by 1
58 *
59 * This decrements the scroll freeze count by one. If it is more
60 * than 0 it will take effect on the parents of the indicated
61 * object.
62 *
63 * @param obj The object
64 * @ingroup Scrollhints
65 */
66EAPI void elm_object_scroll_freeze_pop(Evas_Object *obj);
67
68/**
69 * Lock the scrolling of the given widget (and thus all parents)
70 *
71 * This locks the given object from scrolling in the X axis (and implicitly
72 * also locks all parent scrollers too from doing the same).
73 *
74 * @param obj The object
75 * @param lock The lock state (1 == locked, 0 == unlocked)
76 * @ingroup Scrollhints
77 */
78EAPI void elm_object_scroll_lock_x_set(Evas_Object *obj, Eina_Bool lock);
79
80/**
81 * Lock the scrolling of the given widget (and thus all parents)
82 *
83 * This locks the given object from scrolling in the Y axis (and implicitly
84 * also locks all parent scrollers too from doing the same).
85 *
86 * @param obj The object
87 * @param lock The lock state (1 == locked, 0 == unlocked)
88 * @ingroup Scrollhints
89 */
90EAPI void elm_object_scroll_lock_y_set(Evas_Object *obj, Eina_Bool lock);
91
92/**
93 * Get the scrolling lock of the given widget
94 *
95 * This gets the lock for X axis scrolling.
96 *
97 * @param obj The object
98 * @ingroup Scrollhints
99 */
100EAPI Eina_Bool elm_object_scroll_lock_x_get(const Evas_Object *obj);
101
102/**
103 * Get the scrolling lock of the given widget
104 *
105 * This gets the lock for Y axis scrolling.
106 *
107 * @param obj The object
108 * @ingroup Scrollhints
109 */
110EAPI Eina_Bool elm_object_scroll_lock_y_get(const Evas_Object *obj);
111
112/**
113 * @}
114 */
diff --git a/libraries/elementary/src/lib/elm_scroller.c b/libraries/elementary/src/lib/elm_scroller.c
new file mode 100644
index 0000000..49959b2
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_scroller.c
@@ -0,0 +1,765 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4
5typedef struct _Widget_Data Widget_Data;
6
7struct _Widget_Data
8{
9 Evas_Object *scr;
10 Evas_Object *content;
11 const char *widget_name, *widget_base;
12 Eina_Bool min_w : 1;
13 Eina_Bool min_h : 1;
14 double pagerel_h, pagerel_v;
15 Evas_Coord pagesize_h, pagesize_v;
16};
17
18static const char *widtype = NULL;
19static void _del_hook(Evas_Object *obj);
20static void _theme_hook(Evas_Object *obj);
21static void _show_region_hook(void *data, Evas_Object *obj);
22static void _sizing_eval(Evas_Object *obj);
23static void _sub_del(void *data, Evas_Object *obj, void *event_info);
24static void _on_focus_hook(void *data, Evas_Object *obj);
25static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
26 Evas_Callback_Type type, void *event_info);
27
28
29static const char SIG_SCROLL[] = "scroll";
30static const char SIG_SCROLL_ANIM_START[] = "scroll,anim,start";
31static const char SIG_SCROLL_ANIM_STOP[] = "scroll,anim,stop";
32static const char SIG_SCROLL_DRAG_START[] = "scroll,drag,start";
33static const char SIG_SCROLL_DRAG_STOP[] = "scroll,drag,stop";
34static const char SIG_EDGE_LEFT[] = "edge,left";
35static const char SIG_EDGE_RIGHT[] = "edge,right";
36static const char SIG_EDGE_TOP[] = "edge,top";
37static const char SIG_EDGE_BOTTOM[] = "edge,bottom";
38static const Evas_Smart_Cb_Description _signals[] = {
39 {SIG_SCROLL, ""},
40 {SIG_SCROLL_ANIM_START, ""},
41 {SIG_SCROLL_ANIM_STOP, ""},
42 {SIG_SCROLL_DRAG_START, ""},
43 {SIG_SCROLL_DRAG_STOP, ""},
44 {SIG_EDGE_LEFT, ""},
45 {SIG_EDGE_RIGHT, ""},
46 {SIG_EDGE_TOP, ""},
47 {SIG_EDGE_BOTTOM, ""},
48 {NULL, NULL}
49};
50
51static Eina_Bool
52_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
53{
54 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
55 Evas_Event_Key_Down *ev = event_info;
56 Widget_Data *wd = elm_widget_data_get(obj);
57 if (!wd) return EINA_FALSE;
58 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
59 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
60
61 Evas_Coord x = 0;
62 Evas_Coord y = 0;
63 Evas_Coord step_x = 0;
64 Evas_Coord step_y = 0;
65 Evas_Coord max_x = 0;
66 Evas_Coord max_y = 0;
67 Evas_Coord v_w = 0;
68 Evas_Coord v_h = 0;
69 Evas_Coord page_x = 0;
70 Evas_Coord page_y = 0;
71
72 elm_smart_scroller_child_pos_get(wd->scr, &x, &y);
73 elm_smart_scroller_step_size_get(wd->scr, &step_x, &step_y);
74 elm_smart_scroller_page_size_get(wd->scr, &page_x, &page_y);
75 elm_smart_scroller_child_viewport_size_get(wd->scr, &v_w, &v_h);
76 elm_scroller_child_size_get(obj, &max_x, &max_y);
77
78 if ((!strcmp(ev->keyname, "Left")) ||
79 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
80 {
81 x -= step_x;
82 }
83 else if ((!strcmp(ev->keyname, "Right")) ||
84 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
85 {
86 x += step_x;
87 }
88 else if ((!strcmp(ev->keyname, "Up")) ||
89 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
90 {
91 y -= step_y;
92 }
93 else if ((!strcmp(ev->keyname, "Down")) ||
94 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
95 {
96 y += step_y;
97 }
98 else if ((!strcmp(ev->keyname, "Home")) ||
99 ((!strcmp(ev->keyname, "KP_Home")) && (!ev->string)))
100 {
101 y = 0;
102 }
103 else if ((!strcmp(ev->keyname, "End")) ||
104 ((!strcmp(ev->keyname, "KP_End")) && (!ev->string)))
105 {
106 y = max_y - v_h;
107 }
108 else if ((!strcmp(ev->keyname, "Prior")) ||
109 ((!strcmp(ev->keyname, "KP_Prior")) && (!ev->string)))
110 {
111 if (page_y < 0)
112 y -= -(page_y * v_h) / 100;
113 else
114 y -= page_y;
115 }
116 else if ((!strcmp(ev->keyname, "Next")) ||
117 ((!strcmp(ev->keyname, "KP_Next")) && (!ev->string)))
118 {
119 if (page_y < 0)
120 y += -(page_y * v_h) / 100;
121 else
122 y += page_y;
123 }
124 else return EINA_FALSE;
125
126 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
127 elm_smart_scroller_child_pos_set(wd->scr, x, y);
128 return EINA_TRUE;
129}
130
131static void
132_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
133{
134 Widget_Data *wd = elm_widget_data_get(obj);
135 if (!wd) return;
136 if (elm_widget_focus_get(obj))
137 {
138 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,focus", "elm");
139 evas_object_focus_set(wd->scr, EINA_TRUE);
140 }
141 else
142 {
143 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr), "elm,action,unfocus", "elm");
144 evas_object_focus_set(wd->scr, EINA_FALSE);
145 }
146}
147
148static void
149_del_hook(Evas_Object *obj)
150{
151 Widget_Data *wd = elm_widget_data_get(obj);
152 if (!wd) return;
153 free(wd);
154}
155
156static void
157_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
158{
159 Widget_Data *wd = elm_widget_data_get(obj);
160 if (!wd) return;
161 if (wd->scr)
162 elm_smart_scroller_mirrored_set(wd->scr, mirrored);
163}
164
165static void
166_theme_hook(Evas_Object *obj)
167{
168 Widget_Data *wd = elm_widget_data_get(obj);
169 if (!wd) return;
170 _elm_widget_mirrored_reload(obj);
171 if (wd->scr)
172 {
173 Evas_Object *edj;
174 const char *str;
175
176 _mirrored_set(obj, elm_widget_mirrored_get(obj));
177 elm_smart_scroller_object_theme_set(obj, wd->scr,
178 wd->widget_name, wd->widget_base,
179 elm_widget_style_get(obj));
180 // edje_object_scale_set(wd->scr, elm_widget_scale_get(obj) * _elm_config->scale);
181 edj = elm_smart_scroller_edje_object_get(wd->scr);
182 str = edje_object_data_get(edj, "focus_highlight");
183 if ((str) && (!strcmp(str, "on")))
184 elm_widget_highlight_in_theme_set(obj, EINA_TRUE);
185 else
186 elm_widget_highlight_in_theme_set(obj, EINA_FALSE);
187 }
188 _sizing_eval(obj);
189}
190
191static Eina_Bool
192_elm_scroller_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
193{
194 Widget_Data *wd = elm_widget_data_get(obj);
195 Evas_Object *cur;
196
197 if ((!wd) || (!wd->content))
198 return EINA_FALSE;
199
200 cur = wd->content;
201
202 /* Try Focus cycle in subitem */
203 if (elm_widget_focus_get(obj))
204 {
205 if ((elm_widget_can_focus_get(cur)) || (elm_widget_child_can_focus_get(cur)))
206 return elm_widget_focus_next_get(cur, dir, next);
207 }
208
209 /* Return */
210 *next = (Evas_Object *)obj;
211 return !elm_widget_focus_get(obj);
212}
213
214static void
215_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
216{
217 Widget_Data *wd = elm_widget_data_get(obj);
218 if (!wd) return;
219 edje_object_signal_emit(elm_smart_scroller_edje_object_get(wd->scr),
220 emission, source);
221}
222
223static void
224_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
225{
226 Widget_Data *wd = elm_widget_data_get(obj);
227 if (!wd) return;
228 edje_object_signal_callback_add(elm_smart_scroller_edje_object_get(wd->scr),
229 emission, source, func_cb, data);
230}
231
232static void
233_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
234{
235 Widget_Data *wd = elm_widget_data_get(obj);
236 edje_object_signal_callback_del_full(
237 elm_smart_scroller_edje_object_get(wd->scr), emission, source,
238 func_cb, data);
239}
240
241static void
242_show_region_hook(void *data, Evas_Object *obj)
243{
244 Widget_Data *wd = elm_widget_data_get(data);
245 Evas_Coord x, y, w, h;
246 if (!wd) return;
247 elm_widget_show_region_get(obj, &x, &y, &w, &h);
248 if (wd->scr)
249 elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
250}
251
252static void
253_focus_region_hook(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
254{
255 Widget_Data *wd = elm_widget_data_get(obj);
256 if (wd->scr)
257 elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
258}
259
260static void
261_sizing_eval(Evas_Object *obj)
262{
263 Widget_Data *wd = elm_widget_data_get(obj);
264 Evas_Coord vw = 0, vh = 0, minw = 0, minh = 0, maxw = 0, maxh = 0, w, h, vmw, vmh;
265 double xw = 0.0, yw = 0.0;
266
267 if (!wd) return;
268 if (wd->content)
269 {
270 evas_object_size_hint_min_get(wd->content, &minw, &minh);
271 evas_object_size_hint_max_get(wd->content, &maxw, &maxh);
272 evas_object_size_hint_weight_get(wd->content, &xw, &yw);
273 }
274 if (wd->scr)
275 {
276 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
277 if (xw > 0.0)
278 {
279 if ((minw > 0) && (vw < minw)) vw = minw;
280 else if ((maxw > 0) && (vw > maxw)) vw = maxw;
281 }
282 else if (minw > 0) vw = minw;
283 if (yw > 0.0)
284 {
285 if ((minh > 0) && (vh < minh)) vh = minh;
286 else if ((maxh > 0) && (vh > maxh)) vh = maxh;
287 }
288 else if (minh > 0) vh = minh;
289 if (wd->content) evas_object_resize(wd->content, vw, vh);
290 w = -1;
291 h = -1;
292 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &vmw, &vmh);
293 if (wd->min_w) w = vmw + minw;
294 if (wd->min_h) h = vmh + minh;
295 evas_object_size_hint_max_get(obj, &maxw, &maxh);
296 if ((maxw > 0) && (w > maxw)) w = maxw;
297 if ((maxh > 0) && (h > maxh)) h = maxh;
298 evas_object_size_hint_min_set(obj, w, h);
299 }
300}
301
302static void
303_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
304{
305 _sizing_eval(data);
306}
307
308static void
309_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
310{
311 Widget_Data *wd = elm_widget_data_get(obj);
312 Evas_Object *sub = event_info;
313
314 if (!wd) return;
315 if (sub == wd->content)
316 {
317 elm_widget_on_show_region_hook_set(wd->content, NULL, NULL);
318 evas_object_event_callback_del_full (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
319 _changed_size_hints, obj);
320 wd->content = NULL;
321 _sizing_eval(obj);
322 }
323 else if (sub == wd->scr)
324 wd->scr = NULL;
325}
326
327static void
328_hold_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
329{
330 Widget_Data *wd = elm_widget_data_get(obj);
331
332 if (!wd) return;
333 if (wd->scr)
334 elm_smart_scroller_hold_set(wd->scr, 1);
335}
336
337static void
338_hold_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
339{
340 Widget_Data *wd = elm_widget_data_get(obj);
341
342 if (!wd) return;
343 if (wd->scr)
344 elm_smart_scroller_hold_set(wd->scr, 0);
345}
346
347static void
348_freeze_on(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
349{
350 Widget_Data *wd = elm_widget_data_get(obj);
351
352 if (!wd) return;
353 if (wd->scr)
354 elm_smart_scroller_freeze_set(wd->scr, 1);
355}
356
357static void
358_freeze_off(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
359{
360 Widget_Data *wd = elm_widget_data_get(obj);
361
362 if (!wd) return;
363 if (wd->scr)
364 elm_smart_scroller_freeze_set(wd->scr, 0);
365}
366
367static void
368_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
369{
370 _sizing_eval(data);
371}
372
373static void
374_edge_left(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
375{
376 evas_object_smart_callback_call(data, SIG_EDGE_LEFT, NULL);
377}
378
379static void
380_edge_right(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
381{
382 evas_object_smart_callback_call(data, SIG_EDGE_RIGHT, NULL);
383}
384
385static void
386_edge_top(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
387{
388 evas_object_smart_callback_call(data, SIG_EDGE_TOP, NULL);
389}
390
391static void
392_edge_bottom(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
393{
394 evas_object_smart_callback_call(data, SIG_EDGE_BOTTOM, NULL);
395}
396
397static void
398_scroll(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
399{
400 evas_object_smart_callback_call(data, SIG_SCROLL, NULL);
401}
402
403static void
404_scroll_anim_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
405{
406 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_START, NULL);
407}
408
409static void
410_scroll_anim_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
411{
412 evas_object_smart_callback_call(data, SIG_SCROLL_ANIM_STOP, NULL);
413}
414
415static void
416_scroll_drag_start(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
417{
418 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_START, NULL);
419}
420
421static void
422_scroll_drag_stop(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
423{
424 evas_object_smart_callback_call(data, SIG_SCROLL_DRAG_STOP, NULL);
425}
426
427Evas_Object *
428_elm_scroller_edje_object_get(Evas_Object *obj)
429{
430 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
431 Widget_Data *wd = elm_widget_data_get(obj);
432 if (!wd) return NULL;
433 return elm_smart_scroller_edje_object_get(wd->scr);
434}
435
436static void
437_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
438{
439 ELM_CHECK_WIDTYPE(obj, widtype);
440 Widget_Data *wd;
441 if (part && strcmp(part, "default")) return;
442 wd = elm_widget_data_get(obj);
443 if (!wd) return;
444 if (wd->content == content) return;
445 if (wd->content) evas_object_del(wd->content);
446 wd->content = content;
447 if (content)
448 {
449 elm_widget_on_show_region_hook_set(content, _show_region_hook, obj);
450 elm_widget_sub_object_add(obj, content);
451 if (wd->scr)
452 elm_smart_scroller_child_set(wd->scr, content);
453 evas_object_event_callback_add(content,
454 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
455 _changed_size_hints, obj);
456 }
457 _sizing_eval(obj);
458}
459
460static Evas_Object *
461_content_get_hook(const Evas_Object *obj, const char *part)
462{
463 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
464 Widget_Data *wd;
465 if (part && strcmp(part, "default")) return NULL;
466 wd = elm_widget_data_get(obj);
467 if (!wd) return NULL;
468 return wd->content;
469}
470
471static Evas_Object *
472_content_unset_hook(Evas_Object *obj, const char *part)
473{
474 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
475 Widget_Data *wd;
476 Evas_Object *content;
477 if (part && strcmp(part, "default")) return NULL;
478 wd = elm_widget_data_get(obj);
479 if (!wd) return NULL;
480 if (!wd->content) return NULL;
481 content = wd->content;
482 elm_widget_sub_object_del(obj, wd->content);
483 evas_object_event_callback_del_full(wd->content,
484 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
485 _changed_size_hints, obj);
486 edje_object_part_unswallow(elm_smart_scroller_edje_object_get(wd->scr),
487 wd->content);
488 wd->content = NULL;
489 return content;
490}
491
492EAPI Evas_Object *
493elm_scroller_add(Evas_Object *parent)
494{
495 Evas_Object *obj;
496 Evas *e;
497 Widget_Data *wd;
498 Evas_Coord minw, minh;
499
500 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
501
502 ELM_SET_WIDTYPE(widtype, "scroller");
503 elm_widget_type_set(obj, "scroller");
504 elm_widget_sub_object_add(parent, obj);
505 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
506 elm_widget_data_set(obj, wd);
507 elm_widget_del_hook_set(obj, _del_hook);
508 elm_widget_theme_hook_set(obj, _theme_hook);
509 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
510 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
511 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
512 elm_widget_focus_next_hook_set(obj, _elm_scroller_focus_next_hook);
513 elm_widget_can_focus_set(obj, EINA_TRUE);
514 elm_widget_event_hook_set(obj, _event_hook);
515 elm_widget_focus_region_hook_set(obj, _focus_region_hook);
516 elm_widget_content_set_hook_set(obj, _content_set_hook);
517 elm_widget_content_get_hook_set(obj, _content_get_hook);
518 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
519
520 wd->widget_name = eina_stringshare_add("scroller");
521 wd->widget_base = eina_stringshare_add("base");
522
523 wd->scr = elm_smart_scroller_add(e);
524 elm_smart_scroller_widget_set(wd->scr, obj);
525 _theme_hook(obj);
526 elm_widget_resize_object_set(obj, wd->scr);
527 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
528 _changed_size_hints, obj);
529
530 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr), &minw, &minh);
531 evas_object_size_hint_min_set(obj, minw, minh);
532 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, _resize, obj);
533
534 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
535 evas_object_smart_callback_add(obj, "scroll-hold-on", _hold_on, obj);
536 evas_object_smart_callback_add(obj, "scroll-hold-off", _hold_off, obj);
537 evas_object_smart_callback_add(obj, "scroll-freeze-on", _freeze_on, obj);
538 evas_object_smart_callback_add(obj, "scroll-freeze-off", _freeze_off, obj);
539
540 evas_object_smart_callback_add(wd->scr, "edge,left", _edge_left, obj);
541 evas_object_smart_callback_add(wd->scr, "edge,right", _edge_right, obj);
542 evas_object_smart_callback_add(wd->scr, "edge,top", _edge_top, obj);
543 evas_object_smart_callback_add(wd->scr, "edge,bottom", _edge_bottom, obj);
544 evas_object_smart_callback_add(wd->scr, "scroll", _scroll, obj);
545 evas_object_smart_callback_add(wd->scr, "animate,start", _scroll_anim_start, obj);
546 evas_object_smart_callback_add(wd->scr, "animate,stop", _scroll_anim_stop, obj);
547 evas_object_smart_callback_add(wd->scr, "drag,start", _scroll_drag_start, obj);
548 evas_object_smart_callback_add(wd->scr, "drag,stop", _scroll_drag_stop, obj);
549
550 _sizing_eval(obj);
551
552 // TODO: convert Elementary to subclassing of Evas_Smart_Class
553 // TODO: and save some bytes, making descriptions per-class and not instance!
554 evas_object_smart_callbacks_descriptions_set(obj, _signals);
555 _mirrored_set(obj, elm_widget_mirrored_get(obj));
556 return obj;
557}
558
559EAPI void
560elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base)
561{
562 ELM_CHECK_WIDTYPE(obj, widtype);
563 Widget_Data *wd = elm_widget_data_get(obj);
564 if (!wd) return;
565 EINA_SAFETY_ON_NULL_RETURN(widget);
566 EINA_SAFETY_ON_NULL_RETURN(base);
567 if (eina_stringshare_replace(&wd->widget_name, widget) |
568 eina_stringshare_replace(&wd->widget_base, base))
569 _theme_hook(obj);
570}
571
572EAPI void
573elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h)
574{
575 ELM_CHECK_WIDTYPE(obj, widtype);
576 Widget_Data *wd = elm_widget_data_get(obj);
577 if (!wd) return;
578 wd->min_w = w;
579 wd->min_h = h;
580 _sizing_eval(obj);
581}
582
583EAPI void
584elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
585{
586 ELM_CHECK_WIDTYPE(obj, widtype);
587 Widget_Data *wd = elm_widget_data_get(obj);
588 if ((!wd) || (!wd->scr)) return;
589 elm_smart_scroller_child_region_show(wd->scr, x, y, w, h);
590}
591
592EAPI void
593elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v)
594{
595 ELM_CHECK_WIDTYPE(obj, widtype);
596 Widget_Data *wd = elm_widget_data_get(obj);
597 if ((!wd) || (!wd->scr)) return;
598 if ((policy_h >= ELM_SCROLLER_POLICY_LAST) ||
599 (policy_v >= ELM_SCROLLER_POLICY_LAST))
600 return;
601 elm_smart_scroller_policy_set(wd->scr, policy_h, policy_v);
602}
603
604EAPI void
605elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v)
606{
607 ELM_CHECK_WIDTYPE(obj, widtype);
608 Widget_Data *wd = elm_widget_data_get(obj);
609 if ((!wd) || (!wd->scr)) return;
610 elm_smart_scroller_policy_get(wd->scr,
611 (Elm_Smart_Scroller_Policy *) policy_h,
612 (Elm_Smart_Scroller_Policy *) policy_v);
613}
614
615EAPI void
616elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
617{
618 ELM_CHECK_WIDTYPE(obj, widtype);
619 Widget_Data *wd = elm_widget_data_get(obj);
620 if ((!wd) || (!wd->scr)) return;
621 if ((x) || (y)) elm_smart_scroller_child_pos_get(wd->scr, x, y);
622 if ((w) || (h)) elm_smart_scroller_child_viewport_size_get(wd->scr, w, h);
623}
624
625EAPI void
626elm_scroller_child_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
627{
628 ELM_CHECK_WIDTYPE(obj, widtype);
629 Widget_Data *wd = elm_widget_data_get(obj);
630 if (!wd) return;
631 evas_object_geometry_get(wd->content, NULL, NULL, w, h);
632}
633
634EAPI void
635elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce)
636{
637 ELM_CHECK_WIDTYPE(obj, widtype);
638 Widget_Data *wd = elm_widget_data_get(obj);
639 if ((!wd) || (!wd->scr)) return;
640 elm_smart_scroller_bounce_allow_set(wd->scr, h_bounce, v_bounce);
641}
642
643EAPI void
644elm_scroller_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce)
645{
646 ELM_CHECK_WIDTYPE(obj, widtype);
647 Widget_Data *wd = elm_widget_data_get(obj);
648 if (!wd) return;
649 elm_smart_scroller_bounce_allow_get(wd->scr, h_bounce, v_bounce);
650}
651
652EAPI void
653elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel)
654{
655 ELM_CHECK_WIDTYPE(obj, widtype);
656 Widget_Data *wd = elm_widget_data_get(obj);
657 if (!wd) return;
658 wd->pagerel_h = h_pagerel;
659 wd->pagerel_v = v_pagerel;
660 if (wd->scr)
661 elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v,
662 wd->pagesize_h, wd->pagesize_v);
663}
664
665EAPI void
666elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize)
667{
668 ELM_CHECK_WIDTYPE(obj, widtype);
669 Widget_Data *wd = elm_widget_data_get(obj);
670 if (!wd) return;
671 wd->pagesize_h = h_pagesize;
672 wd->pagesize_v = v_pagesize;
673 if (wd->scr)
674 elm_smart_scroller_paging_set(wd->scr, wd->pagerel_h, wd->pagerel_v,
675 wd->pagesize_h, wd->pagesize_v);
676}
677
678EAPI void
679elm_scroller_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
680{
681 ELM_CHECK_WIDTYPE(obj, widtype);
682 Widget_Data *wd = elm_widget_data_get(obj);
683 if (!wd) return;
684 if (wd->scr)
685 elm_smart_scroller_current_page_get(wd->scr, h_pagenumber, v_pagenumber);
686}
687
688EAPI void
689elm_scroller_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber)
690{
691 ELM_CHECK_WIDTYPE(obj, widtype);
692 Widget_Data *wd = elm_widget_data_get(obj);
693 if (!wd) return;
694 if (wd->scr)
695 elm_smart_scroller_last_page_get(wd->scr, h_pagenumber, v_pagenumber);
696}
697
698EAPI void
699elm_scroller_page_show(Evas_Object *obj, int h_pagenumber, int v_pagenumber)
700{
701 ELM_CHECK_WIDTYPE(obj, widtype);
702 Widget_Data *wd = elm_widget_data_get(obj);
703 if (!wd) return;
704 if (wd->scr)
705 elm_smart_scroller_page_show(wd->scr, h_pagenumber, v_pagenumber);
706}
707
708EAPI void
709elm_scroller_page_bring_in(Evas_Object *obj, int h_pagenumber, int v_pagenumber)
710{
711 ELM_CHECK_WIDTYPE(obj, widtype);
712 Widget_Data *wd = elm_widget_data_get(obj);
713 if (!wd) return;
714 if (wd->scr)
715 elm_smart_scroller_page_bring_in(wd->scr, h_pagenumber, v_pagenumber);
716}
717
718EAPI void
719elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
720{
721 ELM_CHECK_WIDTYPE(obj, widtype);
722 Widget_Data *wd = elm_widget_data_get(obj);
723 if ((!wd) || (!wd->scr)) return;
724 elm_smart_scroller_region_bring_in(wd->scr, x, y, w, h);
725}
726
727EAPI void
728elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation)
729{
730 ELM_CHECK_WIDTYPE(obj, widtype);
731 Widget_Data *wd = elm_widget_data_get(obj);
732 if (!wd) return;
733
734 evas_object_propagate_events_set(wd->scr, propagation);
735}
736
737EAPI Eina_Bool
738elm_scroller_propagate_events_get(const Evas_Object *obj)
739{
740 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
741 Widget_Data *wd = elm_widget_data_get(obj);
742 if (!wd) return EINA_FALSE;
743
744 return evas_object_propagate_events_get(wd->scr);
745}
746
747EAPI void
748elm_scroller_gravity_set(Evas_Object *obj, double x, double y)
749{
750 ELM_CHECK_WIDTYPE(obj, widtype);
751 Widget_Data *wd = elm_widget_data_get(obj);
752 if (!wd) return;
753
754 elm_smart_scroller_gravity_set(wd->scr, x, y);
755}
756
757EAPI void
758elm_scroller_gravity_get(const Evas_Object *obj, double *x, double *y)
759{
760 ELM_CHECK_WIDTYPE(obj, widtype);
761 Widget_Data *wd = elm_widget_data_get(obj);
762 if (!wd) return;
763
764 elm_smart_scroller_gravity_get(wd->scr, x, y);
765}
diff --git a/libraries/elementary/src/lib/elm_scroller.h b/libraries/elementary/src/lib/elm_scroller.h
new file mode 100644
index 0000000..b1ad844
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_scroller.h
@@ -0,0 +1,423 @@
1/**
2 * @defgroup Scroller Scroller
3 * @ingroup Elementary
4 *
5 * A scroller holds a single object and "scrolls it around". This means that
6 * it allows the user to use a scrollbar (or a finger) to drag the viewable
7 * region around, allowing to move through a much larger object that is
8 * contained in the scroller. The scroller will always have a small minimum
9 * size by default as it won't be limited by the contents of the scroller.
10 *
11 * Signals that you can add callbacks for are:
12 * @li "edge,left" - the left edge of the content has been reached
13 * @li "edge,right" - the right edge of the content has been reached
14 * @li "edge,top" - the top edge of the content has been reached
15 * @li "edge,bottom" - the bottom edge of the content has been reached
16 * @li "scroll" - the content has been scrolled (moved)
17 * @li "scroll,anim,start" - scrolling animation has started
18 * @li "scroll,anim,stop" - scrolling animation has stopped
19 * @li "scroll,drag,start" - dragging the contents around has started
20 * @li "scroll,drag,stop" - dragging the contents around has stopped
21 * @note The "scroll,anim,*" and "scroll,drag,*" signals are only emitted by
22 * user intervention.
23 *
24 * @note When Elementary is in embedded mode the scrollbars will not be
25 * draggable, they appear merely as indicators of how much has been scrolled.
26 * @note When Elementary is in desktop mode the thumbscroll(a.k.a.
27 * fingerscroll) won't work.
28 *
29 * Default content parts of the scroller widget that you can use for are:
30 * @li "default" - A content of the scroller
31 *
32 * Supported elm_object common APIs.
33 * @li @ref elm_object_signal_emit
34 * @li @ref elm_object_signal_callback_add
35 * @li @ref elm_object_signal_callback_del
36 * @li @ref elm_object_part_content_set
37 * @li @ref elm_object_part_content_get
38 * @li @ref elm_object_part_content_unset
39 *
40 * In @ref tutorial_scroller you'll find an example of how to use most of
41 * this API.
42 * @{
43 */
44
45/**
46 * @brief Type that controls when scrollbars should appear.
47 *
48 * @see elm_scroller_policy_set()
49 */
50typedef enum
51{
52 ELM_SCROLLER_POLICY_AUTO = 0, /**< Show scrollbars as needed */
53 ELM_SCROLLER_POLICY_ON, /**< Always show scrollbars */
54 ELM_SCROLLER_POLICY_OFF, /**< Never show scrollbars */
55 ELM_SCROLLER_POLICY_LAST
56} Elm_Scroller_Policy;
57
58/**
59 * @brief Add a new scroller to the parent
60 *
61 * @param parent The parent object
62 * @return The new object or NULL if it cannot be created
63 *
64 * @ingroup Scroller
65 */
66EAPI Evas_Object *elm_scroller_add(Evas_Object *parent);
67
68/**
69 * @brief Set custom theme elements for the scroller
70 *
71 * @param obj The scroller object
72 * @param widget The widget name to use (default is "scroller")
73 * @param base The base name to use (default is "base")
74 *
75 * @ingroup Scroller
76 */
77EAPI void elm_scroller_custom_widget_base_theme_set(Evas_Object *obj, const char *widget, const char *base);
78
79/**
80 * @brief Make the scroller minimum size limited to the minimum size of the content
81 *
82 * @param obj The scroller object
83 * @param w Enable limiting minimum size horizontally
84 * @param h Enable limiting minimum size vertically
85 *
86 * By default the scroller will be as small as its design allows,
87 * irrespective of its content. This will make the scroller minimum size the
88 * right size horizontally and/or vertically to perfectly fit its content in
89 * that direction.
90 *
91 * @ingroup Scroller
92 */
93EAPI void elm_scroller_content_min_limit(Evas_Object *obj, Eina_Bool w, Eina_Bool h);
94
95/**
96 * @brief Show a specific virtual region within the scroller content object
97 *
98 * @param obj The scroller object
99 * @param x X coordinate of the region
100 * @param y Y coordinate of the region
101 * @param w Width of the region
102 * @param h Height of the region
103 *
104 * This will ensure all (or part if it does not fit) of the designated
105 * region in the virtual content object (0, 0 starting at the top-left of the
106 * virtual content object) is shown within the scroller.
107 *
108 * @ingroup Scroller
109 */
110EAPI void elm_scroller_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
111
112/**
113 * @brief Set the scrollbar visibility policy
114 *
115 * @param obj The scroller object
116 * @param policy_h Horizontal scrollbar policy
117 * @param policy_v Vertical scrollbar policy
118 *
119 * This sets the scrollbar visibility policy for the given scroller.
120 * ELM_SCROLLER_POLICY_AUTO means the scrollbar is made visible if it is
121 * needed, and otherwise kept hidden. ELM_SCROLLER_POLICY_ON turns it on all
122 * the time, and ELM_SCROLLER_POLICY_OFF always keeps it off. This applies
123 * respectively for the horizontal and vertical scrollbars.
124 *
125 * @ingroup Scroller
126 */
127EAPI void elm_scroller_policy_set(Evas_Object *obj, Elm_Scroller_Policy policy_h, Elm_Scroller_Policy policy_v);
128
129/**
130 * @brief Gets scrollbar visibility policy
131 *
132 * @param obj The scroller object
133 * @param policy_h Horizontal scrollbar policy
134 * @param policy_v Vertical scrollbar policy
135 *
136 * @see elm_scroller_policy_set()
137 *
138 * @ingroup Scroller
139 */
140EAPI void elm_scroller_policy_get(const Evas_Object *obj, Elm_Scroller_Policy *policy_h, Elm_Scroller_Policy *policy_v);
141
142/**
143 * @brief Get the currently visible content region
144 *
145 * @param obj The scroller object
146 * @param x X coordinate of the region
147 * @param y Y coordinate of the region
148 * @param w Width of the region
149 * @param h Height of the region
150 *
151 * This gets the current region in the content object that is visible through
152 * the scroller. The region co-ordinates are returned in the @p x, @p y, @p
153 * w, @p h values pointed to.
154 *
155 * @note All coordinates are relative to the content.
156 *
157 * @see elm_scroller_region_show()
158 *
159 * @ingroup Scroller
160 */
161EAPI void elm_scroller_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
162
163/**
164 * @brief Get the size of the content object
165 *
166 * @param obj The scroller object
167 * @param w Width of the content object.
168 * @param h Height of the content object.
169 *
170 * This gets the size of the content object of the scroller.
171 *
172 * @ingroup Scroller
173 */
174EAPI void elm_scroller_child_size_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
175
176/**
177 * @brief Set bouncing behavior
178 *
179 * @param obj The scroller object
180 * @param h_bounce Allow bounce horizontally
181 * @param v_bounce Allow bounce vertically
182 *
183 * When scrolling, the scroller may "bounce" when reaching an edge of the
184 * content object. This is a visual way to indicate the end has been reached.
185 * This is enabled by default for both axis. This API will set if it is enabled
186 * for the given axis with the boolean parameters for each axis.
187 *
188 * @ingroup Scroller
189 */
190EAPI void elm_scroller_bounce_set(Evas_Object *obj, Eina_Bool h_bounce, Eina_Bool v_bounce);
191
192/**
193 * @brief Get the bounce behaviour
194 *
195 * @param obj The Scroller object
196 * @param h_bounce Will the scroller bounce horizontally or not
197 * @param v_bounce Will the scroller bounce vertically or not
198 *
199 * @see elm_scroller_bounce_set()
200 *
201 * @ingroup Scroller
202 */
203EAPI void elm_scroller_bounce_get(const Evas_Object *obj, Eina_Bool *h_bounce, Eina_Bool *v_bounce);
204
205/**
206 * @brief Set scroll page size relative to viewport size.
207 *
208 * @param obj The scroller object
209 * @param h_pagerel The horizontal page relative size
210 * @param v_pagerel The vertical page relative size
211 *
212 * The scroller is capable of limiting scrolling by the user to "pages". That
213 * is to jump by and only show a "whole page" at a time as if the continuous
214 * area of the scroller content is split into page sized pieces. This sets
215 * the size of a page relative to the viewport of the scroller. 1.0 is "1
216 * viewport" is size (horizontally or vertically). 0.0 turns it off in that
217 * axis. This is mutually exclusive with page size
218 * (see elm_scroller_page_size_set() for more information). Likewise 0.5
219 * is "half a viewport". Sane usable values are normally between 0.0 and 1.0
220 * including 1.0. If you only want 1 axis to be page "limited", use 0.0 for
221 * the other axis.
222 *
223 * @ingroup Scroller
224 */
225EAPI void elm_scroller_page_relative_set(Evas_Object *obj, double h_pagerel, double v_pagerel);
226
227/**
228 * @brief Set scroll page size.
229 *
230 * @param obj The scroller object
231 * @param h_pagesize The horizontal page size
232 * @param v_pagesize The vertical page size
233 *
234 * This sets the page size to an absolute fixed value, with 0 turning it off
235 * for that axis.
236 *
237 * @see elm_scroller_page_relative_set()
238 *
239 * @ingroup Scroller
240 */
241EAPI void elm_scroller_page_size_set(Evas_Object *obj, Evas_Coord h_pagesize, Evas_Coord v_pagesize);
242
243/**
244 * @brief Get scroll current page number.
245 *
246 * @param obj The scroller object
247 * @param h_pagenumber The horizontal page number
248 * @param v_pagenumber The vertical page number
249 *
250 * The page number starts from 0. 0 is the first page.
251 * Current page means the page which meets the top-left of the viewport.
252 * If there are two or more pages in the viewport, it returns the number of the page
253 * which meets the top-left of the viewport.
254 *
255 * @see elm_scroller_last_page_get()
256 * @see elm_scroller_page_show()
257 * @see elm_scroller_page_bring_in()
258 *
259 * @ingroup Scroller
260 */
261EAPI void elm_scroller_current_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
262
263/**
264 * @brief Get scroll last page number.
265 *
266 * @param obj The scroller object
267 * @param h_pagenumber The horizontal page number
268 * @param v_pagenumber The vertical page number
269 *
270 * The page number starts from 0. 0 is the first page.
271 * This returns the last page number among the pages.
272 *
273 * @see elm_scroller_current_page_get()
274 * @see elm_scroller_page_show()
275 * @see elm_scroller_page_bring_in()
276 *
277 * @ingroup Scroller
278 */
279EAPI void elm_scroller_last_page_get(const Evas_Object *obj, int *h_pagenumber, int *v_pagenumber);
280
281/**
282 * Show a specific virtual region within the scroller content object by page number.
283 *
284 * @param obj The scroller object
285 * @param h_pagenumber The horizontal page number
286 * @param v_pagenumber The vertical page number
287 *
288 * 0, 0 of the indicated page is located at the top-left of the viewport.
289 * This will jump to the page directly without animation.
290 *
291 * Example of usage:
292 *
293 * @code
294 * sc = elm_scroller_add(win);
295 * elm_object_content_set(sc, content);
296 * elm_scroller_page_relative_set(sc, 1, 0);
297 * elm_scroller_current_page_get(sc, &h_page, &v_page);
298 * elm_scroller_page_show(sc, h_page + 1, v_page);
299 * @endcode
300 *
301 * @see elm_scroller_page_bring_in()
302 *
303 * @ingroup Scroller
304 */
305EAPI void elm_scroller_page_show(Evas_Object *obj, int h_pagenumber, int v_pagenumber);
306
307/**
308 * Show a specific virtual region within the scroller content object by page number.
309 *
310 * @param obj The scroller object
311 * @param h_pagenumber The horizontal page number
312 * @param v_pagenumber The vertical page number
313 *
314 * 0, 0 of the indicated page is located at the top-left of the viewport.
315 * This will slide to the page with animation.
316 *
317 * Example of usage:
318 *
319 * @code
320 * sc = elm_scroller_add(win);
321 * elm_object_content_set(sc, content);
322 * elm_scroller_page_relative_set(sc, 1, 0);
323 * elm_scroller_last_page_get(sc, &h_page, &v_page);
324 * elm_scroller_page_bring_in(sc, h_page, v_page);
325 * @endcode
326 *
327 * @see elm_scroller_page_show()
328 *
329 * @ingroup Scroller
330 */
331EAPI void elm_scroller_page_bring_in(Evas_Object *obj, int h_pagenumber, int v_pagenumber);
332
333/**
334 * @brief Show a specific virtual region within the scroller content object.
335 *
336 * @param obj The scroller object
337 * @param x X coordinate of the region
338 * @param y Y coordinate of the region
339 * @param w Width of the region
340 * @param h Height of the region
341 *
342 * This will ensure all (or part if it does not fit) of the designated
343 * region in the virtual content object (0, 0 starting at the top-left of the
344 * virtual content object) is shown within the scroller. Unlike
345 * elm_scroller_region_show(), this allow the scroller to "smoothly slide"
346 * to this location (if configuration in general calls for transitions). It
347 * may not jump immediately to the new location and make take a while and
348 * show other content along the way.
349 *
350 * @see elm_scroller_region_show()
351 *
352 * @ingroup Scroller
353 */
354EAPI void elm_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
355
356/**
357 * @brief Set event propagation on a scroller
358 *
359 * @param obj The scroller object
360 * @param propagation If propagation is enabled or not
361 *
362 * This enables or disabled event propagation from the scroller content to
363 * the scroller and its parent. By default event propagation is disabled.
364 *
365 * @ingroup Scroller
366 */
367EAPI void elm_scroller_propagate_events_set(Evas_Object *obj, Eina_Bool propagation);
368
369/**
370 * @brief Get event propagation for a scroller
371 *
372 * @param obj The scroller object
373 * @return The propagation state
374 *
375 * This gets the event propagation for a scroller.
376 *
377 * @see elm_scroller_propagate_events_set()
378 *
379 * @ingroup Scroller
380 */
381EAPI Eina_Bool elm_scroller_propagate_events_get(const Evas_Object *obj);
382
383/**
384 * @brief Set scrolling gravity on a scroller
385 *
386 * @param obj The scroller object
387 * @param x The scrolling horizontal gravity
388 * @param y The scrolling vertical gravity
389 *
390 * The gravity, defines how the scroller will adjust its view
391 * when the size of the scroller contents increase.
392 *
393 * The scroller will adjust the view to glue itself as follows.
394 *
395 * x=0.0, for showing the left most region of the content.
396 * x=1.0, for showing the right most region of the content.
397 * y=0.0, for showing the bottom most region of the content.
398 * y=1.0, for showing the top most region of the content.
399 *
400 * Default values for x and y are 0.0
401 *
402 * @ingroup Scroller
403 */
404EAPI void elm_scroller_gravity_set(Evas_Object *obj, double x, double y);
405
406/**
407 * @brief Get scrolling gravity values for a scroller
408 *
409 * @param obj The scroller object
410 * @param x The scrolling horizontal gravity
411 * @param y The scrolling vertical gravity
412 *
413 * This gets gravity values for a scroller.
414 *
415 * @see elm_scroller_gravity_set()
416 *
417 * @ingroup Scroller
418 */
419EAPI void elm_scroller_gravity_get(const Evas_Object *obj, double *x, double *y);
420
421/**
422 * @}
423 */
diff --git a/libraries/elementary/src/lib/elm_segment_control.c b/libraries/elementary/src/lib/elm_segment_control.c
new file mode 100644
index 0000000..6ff6411
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_segment_control.c
@@ -0,0 +1,742 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Segment_Item Elm_Segment_Item;
6
7struct _Widget_Data
8{
9 Evas_Object *obj;
10 Evas_Object *base;
11 Eina_List *seg_items;
12 int item_count;
13 Elm_Segment_Item *selected_item;
14 int item_width;
15};
16
17struct _Elm_Segment_Item
18{
19 ELM_WIDGET_ITEM;
20 Evas_Object *icon;
21 const char *label;
22 int seg_index;
23};
24
25static const char *widtype = NULL;
26static void _sizing_eval(Evas_Object *obj);
27static void _del_hook(Evas_Object *obj);
28static void _theme_hook(Evas_Object *obj);
29static void _disable_hook(Evas_Object *obj);
30static void _item_free(Elm_Segment_Item *it);
31static void _segment_off(Elm_Segment_Item *it);
32static void _segment_on(Elm_Segment_Item *it);
33static void _position_items(Widget_Data *wd);
34static void _on_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj
35 __UNUSED__, void *event_info __UNUSED__);
36static void _mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj
37 __UNUSED__, void *event_info __UNUSED__);
38static void _mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj
39 __UNUSED__, void *event_info __UNUSED__);
40static void _swallow_item_objects(Elm_Segment_Item *it);
41static void _update_list(Widget_Data *wd);
42static Elm_Segment_Item * _item_find(const Evas_Object *obj, int index);
43static Elm_Segment_Item* _item_new(Evas_Object *obj, Evas_Object *icon,
44 const char *label);
45
46static const char SIG_CHANGED[] = "changed";
47
48static const Evas_Smart_Cb_Description _signals[] = {
49 {SIG_CHANGED, ""},
50 {NULL, NULL}
51};
52
53static void
54_sizing_eval(Evas_Object *obj)
55{
56 Widget_Data *wd;
57 Evas_Coord minw = -1, minh = -1;
58 Evas_Coord w, h;
59
60 wd = elm_widget_data_get(obj);
61 if (!wd) return;
62
63 elm_coords_finger_size_adjust(wd->item_count, &minw, 1, &minh);
64 edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
65 elm_coords_finger_size_adjust(wd->item_count, &minw, 1, &minh);
66
67 evas_object_size_hint_min_get(obj, &w, &h);
68 if (w > minw) minw = w;
69 if (h > minh) minh = h;
70 evas_object_size_hint_min_set(obj, minw, minh);
71}
72
73static void
74_del_hook(Evas_Object *obj)
75{
76 Elm_Segment_Item *it;
77 Widget_Data *wd;
78
79 wd = elm_widget_data_get(obj);
80 if (!wd) return;
81
82 EINA_LIST_FREE(wd->seg_items, it)
83 {
84 _item_free(it);
85 elm_widget_item_free(it);
86 }
87
88 free(wd);
89}
90
91static void
92_theme_hook(Evas_Object *obj)
93{
94 Eina_List *l;
95 Eina_Bool rtl;
96 Elm_Segment_Item *it;
97 Widget_Data *wd;
98
99 wd = elm_widget_data_get(obj);
100 if (!wd) return;
101
102 _elm_widget_mirrored_reload(obj);
103 rtl = elm_widget_mirrored_get(obj);
104 edje_object_mirrored_set(wd->base, rtl);
105
106 _elm_theme_object_set(obj, wd->base, "segment_control", "base",
107 elm_widget_style_get(obj));
108 edje_object_scale_set(wd->base, elm_widget_scale_get(wd->base)
109 *_elm_config->scale);
110
111 EINA_LIST_FOREACH(wd->seg_items, l, it)
112 {
113 _elm_theme_object_set(obj, VIEW(it), "segment_control",
114 "item", elm_widget_style_get(obj));
115 edje_object_scale_set(VIEW(it), elm_widget_scale_get(VIEW(it))
116 *_elm_config->scale);
117 edje_object_mirrored_set(VIEW(it), rtl);
118 }
119
120 _update_list(wd);
121}
122
123static void
124_disable_hook(Evas_Object *obj)
125{
126 Widget_Data *wd;
127
128 wd = elm_widget_data_get(obj);
129 if (!wd) return;
130 _update_list(wd);
131}
132
133// TODO: Elm_widget elm_widget_focus_list_next_get supports only Elm_widget list,
134// Not the Elm_Widget_item. Focus switching with in widget not supported until
135// it is supported in elm_widget
136#if 0
137static void *
138_elm_list_data_get(const Eina_List *list)
139{
140 Elm_Segment_Item *it = eina_list_data_get(list);
141
142 if (it) return NULL;
143
144 edje_object_signal_emit(VIEW(it), "elm,state,segment,selected", "elm");
145 return VIEW(it);
146}
147
148static Eina_Bool
149_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir,
150 Evas_Object **next)
151{
152 static int count=0;
153 Widget_Data *;
154 const Eina_List *items;
155 void *(*list_data_get) (const Eina_List *list);
156
157 wd = elm_widget_data_get(obj);
158 if ((!wd)) return EINA_FALSE;
159
160 /* Focus chain */
161 /* TODO: Change this to use other chain */
162 if ((items = elm_widget_focus_custom_chain_get(obj)))
163 list_data_get = eina_list_data_get;
164 else
165 {
166 items = wd->seg_items;
167 list_data_get = _elm_list_data_get;
168 if (!items) return EINA_FALSE;
169 }
170 return elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
171}
172#endif
173
174static void
175_item_free(Elm_Segment_Item *it)
176{
177 Widget_Data *wd;
178
179 if (!it) return;
180
181 wd = elm_widget_item_data_get(it);
182 if (!wd) return;
183
184 if (wd->selected_item == it) wd->selected_item = NULL;
185 if (wd->seg_items) wd->seg_items = eina_list_remove(wd->seg_items, it);
186
187 if (it->icon) evas_object_del(it->icon);
188 if (it->label) eina_stringshare_del(it->label);
189}
190
191static void
192_segment_off(Elm_Segment_Item *it)
193{
194 Widget_Data *wd;
195
196 if (!it) return;
197
198 wd = elm_widget_item_data_get(it);
199 if (!wd) return;
200
201 edje_object_signal_emit(VIEW(it), "elm,state,segment,normal", "elm");
202
203 if (wd->selected_item == it) wd->selected_item = NULL;
204}
205
206static void
207_segment_on(Elm_Segment_Item *it)
208{
209 Widget_Data *wd;
210
211 if (!it) return;
212
213 wd = elm_widget_item_data_get(it);
214 if (!wd) return;
215 if (it == wd->selected_item) return;
216
217 if (wd->selected_item) _segment_off(wd->selected_item);
218
219 edje_object_signal_emit(VIEW(it), "elm,state,segment,selected", "elm");
220
221 wd->selected_item = it;
222 evas_object_smart_callback_call(wd->obj, SIG_CHANGED, it);
223}
224
225static void
226_position_items(Widget_Data *wd)
227{
228 Eina_List *l;
229 Elm_Segment_Item *it;
230 Eina_Bool rtl;
231 int bx, by, bw, bh, pos;
232
233 wd->item_count = eina_list_count(wd->seg_items);
234 if (wd->item_count <= 0) return;
235
236 evas_object_geometry_get(wd->base, &bx, &by, &bw, &bh);
237 wd->item_width = bw / wd->item_count;
238 rtl = elm_widget_mirrored_get(wd->obj);
239
240 if (rtl)
241 pos = bx + bw - wd->item_width;
242 else
243 pos = bx;
244
245 EINA_LIST_FOREACH(wd->seg_items, l, it)
246 {
247 evas_object_move(VIEW(it), pos, by);
248 evas_object_resize(VIEW(it), wd->item_width, bh);
249 if (rtl)
250 pos -= wd->item_width;
251 else
252 pos += wd->item_width;
253 }
254 _sizing_eval(wd->obj);
255}
256
257static void
258_on_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
259 void *event_info __UNUSED__)
260{
261 Widget_Data *wd;
262
263 wd = elm_widget_data_get(data);
264 if (!wd) return;
265
266 _position_items(wd);
267
268}
269
270static void
271_mouse_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
272 void *event_info)
273{
274 Widget_Data *wd;
275 Elm_Segment_Item *it;
276 Evas_Event_Mouse_Up *ev;
277 Evas_Coord x, y, w, h;
278
279 it = data;
280 if (!it) return;
281
282 wd = elm_widget_item_data_get(it);
283 if (!wd) return;
284
285 if (elm_widget_disabled_get(wd->obj)) return;
286
287 if (it == wd->selected_item) return;
288
289 ev = event_info;
290 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
291
292 if ((ev->canvas.x >= x) && (ev->output.x <= (x + w)) && (ev->canvas.y >= y)
293 && (ev->canvas.y <= (y + h)))
294 _segment_on(it);
295 else
296 edje_object_signal_emit(VIEW(it), "elm,state,segment,normal", "elm");
297}
298
299static void
300_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__,
301 void *event_info __UNUSED__)
302{
303 Widget_Data *wd;
304 Elm_Segment_Item *it;
305
306 it = data;
307 if (!it) return;
308
309 wd = elm_widget_item_data_get(it);
310 if (!wd) return;
311
312 if (elm_widget_disabled_get(wd->obj)) return;
313
314 if (it == wd->selected_item) return;
315
316 edje_object_signal_emit(VIEW(it), "elm,state,segment,pressed", "elm");
317}
318
319static void
320_swallow_item_objects(Elm_Segment_Item *it)
321{
322 if (!it) return;
323
324 if (it->icon)
325 {
326 edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
327 edje_object_signal_emit(VIEW(it), "elm,state,icon,visible", "elm");
328 }
329 else
330 edje_object_signal_emit(VIEW(it), "elm,state,icon,hidden", "elm");
331
332 if (it->label)
333 {
334 edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
335 edje_object_signal_emit(VIEW(it), "elm,state,text,visible", "elm");
336 }
337 else
338 edje_object_signal_emit(VIEW(it), "elm,state,text,hidden", "elm");
339 edje_object_message_signal_process(VIEW(it));
340}
341
342static void
343_update_list(Widget_Data *wd)
344{
345 Eina_List *l;
346 Elm_Segment_Item *it;
347 Eina_Bool rtl;
348 int idx = 0;
349
350 _position_items(wd);
351
352 if (wd->item_count == 1)
353 {
354 it = eina_list_nth(wd->seg_items, 0);
355 it->seg_index = 0;
356
357 //Set the segment type
358 edje_object_signal_emit(VIEW(it),
359 "elm,type,segment,single", "elm");
360
361 //Set the segment state
362 if (wd->selected_item == it)
363 edje_object_signal_emit(VIEW(it),
364 "elm,state,segment,selected", "elm");
365 else
366 edje_object_signal_emit(VIEW(it),
367 "elm,state,segment,normal", "elm");
368
369 if (elm_widget_disabled_get(wd->obj))
370 edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
371 else
372 edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
373
374 _swallow_item_objects(it);
375 return;
376 }
377
378 rtl = elm_widget_mirrored_get(wd->obj);
379 EINA_LIST_FOREACH(wd->seg_items, l, it)
380 {
381 it->seg_index = idx;
382
383 //Set the segment type
384 if (idx == 0)
385 {
386 if (rtl)
387 edje_object_signal_emit(VIEW(it),
388 "elm,type,segment,right", "elm");
389 else
390 edje_object_signal_emit(VIEW(it),
391 "elm,type,segment,left", "elm");
392 }
393 else if (idx == (wd->item_count - 1))
394 {
395 if (rtl)
396 edje_object_signal_emit(VIEW(it),
397 "elm,type,segment,left", "elm");
398 else
399 edje_object_signal_emit(VIEW(it),
400 "elm,type,segment,right", "elm");
401 }
402 else
403 edje_object_signal_emit(VIEW(it),
404 "elm,type,segment,middle", "elm");
405
406 //Set the segment state
407 if (wd->selected_item == it)
408 edje_object_signal_emit(VIEW(it),
409 "elm,state,segment,selected", "elm");
410 else
411 edje_object_signal_emit(VIEW(it),
412 "elm,state,segment,normal", "elm");
413
414 if (elm_widget_disabled_get(wd->obj))
415 edje_object_signal_emit(VIEW(it), "elm,state,disabled", "elm");
416 else
417 edje_object_signal_emit(VIEW(it), "elm,state,enabled", "elm");
418
419 _swallow_item_objects(it);
420 idx++;
421 }
422}
423
424static Elm_Segment_Item *
425_item_find(const Evas_Object *obj, int idx)
426{
427 Widget_Data *wd;
428 Elm_Segment_Item *it;
429
430 wd = elm_widget_data_get(obj);
431 if (!wd) return NULL;
432
433 it = eina_list_nth(wd->seg_items, idx);
434 return it;
435}
436
437static void
438_item_text_set_hook(Elm_Object_Item *it, const char *part, const char *label)
439{
440 Widget_Data *wd;
441 Elm_Segment_Item *item;
442
443 if (part && strcmp(part, "default")) return;
444
445 item = (Elm_Segment_Item *)it;
446 wd = elm_widget_item_data_get(item);
447 if (!wd) return;
448
449 eina_stringshare_replace(&item->label, label);
450 if (item->label)
451 edje_object_signal_emit(VIEW(item), "elm,state,text,visible", "elm");
452 else
453 edje_object_signal_emit(VIEW(item), "elm,state,text,hidden", "elm");
454 edje_object_message_signal_process(VIEW(item));
455 //label can be NULL also.
456 edje_object_part_text_escaped_set(VIEW(item), "elm.text", item->label);
457}
458
459static const char *
460_item_text_get_hook(const Elm_Object_Item *it, const char *part)
461{
462 if (part && strcmp(part, "default")) return NULL;
463 return ((Elm_Segment_Item *)it)->label;
464}
465
466static void
467_item_content_set_hook(Elm_Object_Item *it,
468 const char *part,
469 Evas_Object *content)
470{
471 Elm_Segment_Item *item;
472 if (part && strcmp(part, "icon")) return;
473
474 item = (Elm_Segment_Item *)it;
475 if (content == item->icon) return;
476
477 //Remove the existing icon
478 if (item->icon) evas_object_del(item->icon);
479 item->icon = content;
480 if (item->icon)
481 {
482 elm_widget_sub_object_add(VIEW(item), item->icon);
483 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
484 edje_object_signal_emit(VIEW(item), "elm,state,icon,visible", "elm");
485 }
486 else
487 edje_object_signal_emit(VIEW(item), "elm,state,icon,hidden", "elm");
488}
489
490static Evas_Object *
491_item_content_get_hook(const Elm_Object_Item *it, const char *part)
492{
493 if (part && strcmp(part, "icon")) return NULL;
494 return ((Elm_Segment_Item *)it)->icon;
495}
496
497static Eina_Bool
498_item_del_pre_hook(Elm_Object_Item *it)
499{
500 Widget_Data *wd;
501 Elm_Segment_Item *item = (Elm_Segment_Item *)it;
502
503 wd = elm_widget_item_data_get(item);
504 if (!wd) return EINA_FALSE;
505
506 _item_free(item);
507 _update_list(wd);
508
509 return EINA_TRUE;
510}
511
512static Elm_Segment_Item*
513_item_new(Evas_Object *obj, Evas_Object *icon, const char *label)
514{
515 Elm_Segment_Item *it;
516 Widget_Data *wd;
517
518 wd = elm_widget_data_get(obj);
519 if (!wd) return NULL;
520
521 it = elm_widget_item_new(obj, Elm_Segment_Item);
522 if (!it) return NULL;
523 elm_widget_item_data_set(it, wd);
524 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
525 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
526 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
527 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
528 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
529
530 VIEW(it) = edje_object_add(evas_object_evas_get(obj));
531 edje_object_scale_set(VIEW(it), elm_widget_scale_get(VIEW(it))
532 *_elm_config->scale);
533 evas_object_smart_member_add(VIEW(it), obj);
534 elm_widget_sub_object_add(obj, VIEW(it));
535 _elm_theme_object_set(obj, VIEW(it), "segment_control", "item",
536 elm_object_style_get(obj));
537 edje_object_mirrored_set(VIEW(it),
538 elm_widget_mirrored_get(WIDGET(it)));
539
540 if (label)
541 eina_stringshare_replace(&it->label, label);
542 if (it->label)
543 edje_object_signal_emit(VIEW(it), "elm,state,text,visible", "elm");
544 else
545 edje_object_signal_emit(VIEW(it), "elm,state,text,hidden", "elm");
546 edje_object_message_signal_process(VIEW(it));
547 edje_object_part_text_escaped_set(VIEW(it), "elm.text", label);
548
549 it->icon = icon;
550 if (it->icon) elm_widget_sub_object_add(VIEW(it), it->icon);
551 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
552 _mouse_down, it);
553 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
554 _mouse_up, it);
555 evas_object_show(VIEW(it));
556
557 return it;
558}
559
560EAPI Evas_Object *
561elm_segment_control_add(Evas_Object *parent)
562{
563 Evas_Object *obj;
564 Evas *e;
565 Widget_Data *wd;
566
567 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
568
569 ELM_SET_WIDTYPE(widtype, "segment_control");
570 elm_widget_type_set(obj, "segment_control");
571 elm_widget_sub_object_add(parent, obj);
572 elm_widget_data_set(obj, wd);
573 elm_widget_del_hook_set(obj, _del_hook);
574 elm_widget_theme_hook_set(obj, _theme_hook);
575 elm_widget_disable_hook_set(obj, _disable_hook);
576
577 // TODO: Focus switch support to Elm_widget_Item not supported yet.
578#if 0
579 elm_widget_focus_next_hook_set(obj, _focus_next_hook);
580#endif
581
582 wd->obj = obj;
583
584 wd->base = edje_object_add(e);
585 edje_object_scale_set(wd->base, elm_widget_scale_get(wd->base)
586 *_elm_config->scale);
587 _elm_theme_object_set(obj, wd->base, "segment_control", "base", "default");
588 elm_widget_resize_object_set(obj, wd->base);
589
590 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
591 _on_move_resize, obj);
592 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
593 _on_move_resize, obj);
594
595 evas_object_smart_callbacks_descriptions_set(obj, _signals);
596
597 return obj;
598}
599
600EAPI Elm_Object_Item *
601elm_segment_control_item_add(Evas_Object *obj, Evas_Object *icon,
602 const char *label)
603{
604 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
605 Elm_Segment_Item *it;
606 Widget_Data *wd;
607
608 wd = elm_widget_data_get(obj);
609 if (!wd) return NULL;
610
611 it = _item_new(obj, icon, label);
612 if (!it) return NULL;
613
614 wd->seg_items = eina_list_append(wd->seg_items, it);
615 _update_list(wd);
616
617 return (Elm_Object_Item *)it;
618}
619
620EAPI Elm_Object_Item *
621elm_segment_control_item_insert_at(Evas_Object *obj, Evas_Object *icon,
622 const char *label, int idx)
623{
624 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
625 Elm_Segment_Item *it, *it_rel;
626 Widget_Data *wd;
627
628 wd = elm_widget_data_get(obj);
629 if (!wd) return NULL;
630 if (idx < 0) idx = 0;
631
632 it = _item_new(obj, icon, label);
633 if (!it) return NULL;
634
635 it_rel = _item_find(obj, idx);
636 if (it_rel)
637 wd->seg_items = eina_list_prepend_relative(wd->seg_items, it, it_rel);
638 else
639 wd->seg_items = eina_list_append(wd->seg_items, it);
640
641 _update_list(wd);
642 return (Elm_Object_Item *)it;
643}
644
645EAPI void
646elm_segment_control_item_del_at(Evas_Object *obj, int idx)
647{
648 ELM_CHECK_WIDTYPE(obj, widtype);
649 Elm_Segment_Item *it;
650 Widget_Data *wd;
651
652 wd = elm_widget_data_get(obj);
653 if (!wd) return;
654
655 it = _item_find(obj, idx);
656 if (!it) return;
657 elm_object_item_del((Elm_Object_Item *)it);
658}
659
660EAPI const char*
661elm_segment_control_item_label_get(const Evas_Object *obj, int idx)
662{
663 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
664 Elm_Segment_Item *it = _item_find(obj, idx);
665 if (it) return it->label;
666 return NULL;
667}
668
669EAPI Evas_Object *
670elm_segment_control_item_icon_get(const Evas_Object *obj, int idx)
671{
672 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
673 Elm_Segment_Item *it = _item_find(obj, idx);
674 if (it) return it->icon;
675 return NULL;
676}
677
678EAPI int
679elm_segment_control_item_count_get(const Evas_Object *obj)
680{
681 ELM_CHECK_WIDTYPE(obj, widtype) 0;
682 Widget_Data *wd;
683
684 wd = elm_widget_data_get(obj);
685 if (!wd) return 0;
686
687 return eina_list_count(wd->seg_items);
688}
689
690EAPI Evas_Object*
691elm_segment_control_item_object_get(const Elm_Object_Item *it)
692{
693 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
694 return VIEW(it);
695}
696
697EAPI Elm_Object_Item*
698elm_segment_control_item_selected_get(const Evas_Object *obj)
699{
700 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
701 Widget_Data *wd = elm_widget_data_get(obj);
702 if (!wd) return NULL;
703 return (Elm_Object_Item *) wd->selected_item;
704}
705
706EAPI void
707elm_segment_control_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
708{
709 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
710 Widget_Data *wd;
711 Elm_Segment_Item *item = (Elm_Segment_Item *)it;
712
713 wd = elm_widget_item_data_get(item);
714 if (!wd) return;
715
716 if (item == wd->selected_item)
717 {
718 //already in selected state.
719 if (selected) return;
720
721 //unselect case
722 _segment_off(item);
723 }
724 else if (selected)
725 _segment_on(item);
726
727 return;
728}
729
730EAPI Elm_Object_Item *
731elm_segment_control_item_get(const Evas_Object *obj, int idx)
732{
733 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
734 return (Elm_Object_Item *) _item_find(obj, idx);
735}
736
737EAPI int
738elm_segment_control_item_index_get(const Elm_Object_Item *it)
739{
740 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, -1);
741 return ((Elm_Segment_Item *)it)->seg_index;
742}
diff --git a/libraries/elementary/src/lib/elm_segment_control.h b/libraries/elementary/src/lib/elm_segment_control.h
new file mode 100644
index 0000000..02cb7ed
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_segment_control.h
@@ -0,0 +1,290 @@
1/**
2 * @defgroup SegmentControl SegmentControl
3 * @ingroup Elementary
4 *
5 * @image html img/widget/segment_control/preview-00.png
6 * @image latex img/widget/segment_control/preview-00.eps width=\textwidth
7 *
8 * @image html img/segment_control.png
9 * @image latex img/segment_control.eps width=\textwidth
10 *
11 * Segment control widget is a horizontal control made of multiple segment
12 * items, each segment item functioning similar to discrete two state button.
13 * A segment control groups the items together and provides compact
14 * single button with multiple equal size segments.
15 *
16 * Segment item size is determined by base widget
17 * size and the number of items added.
18 * Only one segment item can be at selected state. A segment item can display
19 * combination of Text and any Evas_Object like Images or other widget.
20 *
21 * Smart callbacks one can listen to:
22 * - "changed" - When the user clicks on a segment item which is not
23 * previously selected and get selected. The event_info parameter is the
24 * segment item pointer.
25 *
26 * Available styles for it:
27 * - @c "default"
28 *
29 * Default content parts of the segment control items that you can use for are:
30 * @li "icon" - An icon in a segment control item
31 *
32 * Default text parts of the segment control items that you can use for are:
33 * @li "default" - Title label in a segment control item
34 *
35 * Supported elm_object common APIs.
36 * @li elm_object_disabled_set
37 * @li elm_object_disabled_get
38 *
39 * Supported elm_object_item common APIs.
40 * @li @ref elm_object_item_part_text_set
41 * @li @ref elm_object_item_part_text_get
42 * @li @ref elm_object_item_part_content_set
43 * @li @ref elm_object_item_part_content_get
44 *
45 * Here is an example on its usage:
46 * @li @ref segment_control_example
47 *
48 */
49
50/**
51 * @addtogroup SegmentControl
52 * @{
53 */
54
55/**
56 * Add a new segment control widget to the given parent Elementary
57 * (container) object.
58 *
59 * @param parent The parent object.
60 * @return a new segment control widget handle or @c NULL, on errors.
61 *
62 * This function inserts a new segment control widget on the canvas.
63 *
64 * @ingroup SegmentControl
65 */
66EAPI Evas_Object *elm_segment_control_add(Evas_Object *parent);
67
68/**
69 * Append a new item to the segment control object.
70 *
71 * @param obj The segment control object.
72 * @param icon The icon object to use for the left side of the item. An
73 * icon can be any Evas object, but usually it is an icon created
74 * with elm_icon_add().
75 * @param label The label of the item.
76 * Note that, NULL is different from empty string "".
77 * @return The created item or @c NULL upon failure.
78 *
79 * A new item will be created and appended to the segment control, i.e., will
80 * be set as @b last item.
81 *
82 * If it should be inserted at another position,
83 * elm_segment_control_item_insert_at() should be used instead.
84 *
85 * Items created with this function can be deleted with function
86 * elm_object_item_del() or elm_object_item_del_at().
87 *
88 * @note @p label set to @c NULL is different from empty string "".
89 * If an item
90 * only has icon, it will be displayed bigger and centered. If it has
91 * icon and label, even that an empty string, icon will be smaller and
92 * positioned at left.
93 *
94 * Simple example:
95 * @code
96 * sc = elm_segment_control_add(win);
97 * ic = elm_icon_add(win);
98 * elm_icon_file_set(ic, "path/to/image", NULL);
99 * elm_icon_resizable_set(ic, EINA_TRUE, EINA_TRUE);
100 * elm_segment_control_item_add(sc, ic, "label");
101 * evas_object_show(sc);
102 * @endcode
103 *
104 * @see elm_segment_control_item_insert_at()
105 * @see elm_object_item_del()
106 *
107 * @ingroup SegmentControl
108 */
109EAPI Elm_Object_Item *elm_segment_control_item_add(Evas_Object *obj, Evas_Object *icon, const char *label);
110
111/**
112 * Insert a new item to the segment control object at specified position.
113 *
114 * @param obj The segment control object.
115 * @param icon The icon object to use for the left side of the item. An
116 * icon can be any Evas object, but usually it is an icon created
117 * with elm_icon_add().
118 * @param label The label of the item.
119 * @param index Item position. Value should be between 0 and items count.
120 * @return The created item or @c NULL upon failure.
121
122 * Index values must be between @c 0, when item will be prepended to
123 * segment control, and items count, that can be get with
124 * elm_segment_control_item_count_get(), case when item will be appended
125 * to segment control, just like elm_segment_control_item_add().
126 *
127 * Items created with this function can be deleted with function
128 * elm_object_item_del() or elm_segment_control_item_del_at().
129 *
130 * @note @p label set to @c NULL is different from empty string "".
131 * If an item
132 * only has icon, it will be displayed bigger and centered. If it has
133 * icon and label, even that an empty string, icon will be smaller and
134 * positioned at left.
135 *
136 * @see elm_segment_control_item_add()
137 * @see elm_segment_control_item_count_get()
138 * @see elm_object_item_del()
139 *
140 * @ingroup SegmentControl
141 */
142EAPI Elm_Object_Item *elm_segment_control_item_insert_at(Evas_Object *obj, Evas_Object *icon, const char *label, int index);
143
144/**
145 * Remove a segment control item at given index from its parent,
146 * deleting it.
147 *
148 * @param obj The segment control object.
149 * @param index The position of the segment control item to be deleted.
150 *
151 * Items can be added with elm_segment_control_item_add() or
152 * elm_segment_control_item_insert_at().
153 *
154 * @ingroup SegmentControl
155 */
156EAPI void elm_segment_control_item_del_at(Evas_Object *obj, int index);
157
158/**
159 * Get the Segment items count from segment control.
160 *
161 * @param obj The segment control object.
162 * @return Segment items count.
163 *
164 * It will just return the number of items added to segment control @p obj.
165 *
166 * @ingroup SegmentControl
167 */
168EAPI int elm_segment_control_item_count_get(const Evas_Object *obj);
169
170/**
171 * Get the item placed at specified index.
172 *
173 * @param obj The segment control object.
174 * @param index The index of the segment item.
175 * @return The segment control item or @c NULL on failure.
176 *
177 * Index is the position of an item in segment control widget. Its
178 * range is from @c 0 to <tt> count - 1 </tt>.
179 * Count is the number of items, that can be get with
180 * elm_segment_control_item_count_get().
181 *
182 * @ingroup SegmentControl
183 */
184EAPI Elm_Object_Item *elm_segment_control_item_get(const Evas_Object *obj, int index);
185
186/**
187 * Get the label of item.
188 *
189 * @param obj The segment control object.
190 * @param index The index of the segment item.
191 * @return The label of the item at @p index.
192 *
193 * The return value is a pointer to the label associated to the item when
194 * it was created, with function elm_segment_control_item_add(), or later
195 * with function elm_object_item_text_set. If no label
196 * was passed as argument, it will return @c NULL.
197 *
198 * @see elm_object_item_text_set() for more details.
199 * @see elm_segment_control_item_add()
200 *
201 * @ingroup SegmentControl
202 */
203EAPI const char *elm_segment_control_item_label_get(const Evas_Object *obj, int index);
204
205/**
206 * Get the icon associated to the item.
207 *
208 * @param obj The segment control object.
209 * @param index The index of the segment item.
210 * @return The left side icon associated to the item at @p index.
211 *
212 * The return value is a pointer to the icon associated to the item when
213 * it was created, with function elm_segment_control_item_add(), or later
214 * with function elm_object_item_part_content_set(). If no icon
215 * was passed as argument, it will return @c NULL.
216 *
217 * @see elm_segment_control_item_add()
218 * @see elm_object_item_part_content_set()
219 *
220 * @ingroup SegmentControl
221 */
222EAPI Evas_Object *elm_segment_control_item_icon_get(const Evas_Object *obj, int index);
223
224/**
225 * Get the index of an item.
226 *
227 * @param it The segment control item.
228 * @return The position of item in segment control widget.
229 *
230 * Index is the position of an item in segment control widget. Its
231 * range is from @c 0 to <tt> count - 1 </tt>.
232 * Count is the number of items, that can be get with
233 * elm_segment_control_item_count_get().
234 *
235 * @ingroup SegmentControl
236 */
237EAPI int elm_segment_control_item_index_get(const Elm_Object_Item *it);
238
239/**
240 * Get the base object of the item.
241 *
242 * @param it The segment control item.
243 * @return The base object associated with @p it.
244 *
245 * Base object is the @c Evas_Object that represents that item.
246 *
247 * @ingroup SegmentControl
248 */
249EAPI Evas_Object *elm_segment_control_item_object_get(const Elm_Object_Item *it);
250
251/**
252 * Get the selected item.
253 *
254 * @param obj The segment control object.
255 * @return The selected item or @c NULL if none of segment items is
256 * selected.
257 *
258 * The selected item can be unselected with function
259 * elm_segment_control_item_selected_set().
260 *
261 * The selected item always will be highlighted on segment control.
262 *
263 * @ingroup SegmentControl
264 */
265EAPI Elm_Object_Item *elm_segment_control_item_selected_get(const Evas_Object *obj);
266
267/**
268 * Set the selected state of an item.
269 *
270 * @param it The segment control item
271 * @param select The selected state
272 *
273 * This sets the selected state of the given item @p it.
274 * @c EINA_TRUE for selected, @c EINA_FALSE for not selected.
275 *
276 * If a new item is selected the previously selected will be unselected.
277 * Selected item can be got with function
278 * elm_segment_control_item_selected_get().
279 *
280 * The selected item always will be highlighted on segment control.
281 *
282 * @see elm_segment_control_item_selected_get()
283 *
284 * @ingroup SegmentControl
285 */
286EAPI void elm_segment_control_item_selected_set(Elm_Object_Item *it, Eina_Bool select);
287
288/**
289 * @}
290 */
diff --git a/libraries/elementary/src/lib/elm_separator.c b/libraries/elementary/src/lib/elm_separator.c
new file mode 100644
index 0000000..e852d5e
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_separator.c
@@ -0,0 +1,106 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *sep;
9 Eina_Bool horizontal;
10};
11
12static const char *widtype = NULL;
13static void _del_hook(Evas_Object *obj);
14static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
15static void _theme_hook(Evas_Object *obj);
16static void _sizing_eval(Evas_Object *obj);
17
18static void
19_del_hook(Evas_Object *obj)
20{
21 Widget_Data *wd = elm_widget_data_get(obj);
22 if (!wd) return;
23 free(wd);
24}
25
26static void
27_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
28{
29 Widget_Data *wd = elm_widget_data_get(obj);
30 if (!wd) return;
31 edje_object_mirrored_set(wd->sep, rtl);
32}
33
34static void
35_theme_hook(Evas_Object *obj)
36{
37 Widget_Data *wd = elm_widget_data_get(obj);
38 if (!wd) return;
39 _elm_widget_mirrored_reload(obj);
40 _mirrored_set(obj, elm_widget_mirrored_get(obj));
41 if (wd->horizontal)
42 _elm_theme_object_set(obj, wd->sep, "separator", "horizontal", elm_widget_style_get(obj));
43 else
44 _elm_theme_object_set(obj, wd->sep, "separator", "vertical", elm_widget_style_get(obj));
45 edje_object_scale_set(wd->sep, elm_widget_scale_get(obj) * _elm_config->scale);
46 _sizing_eval(obj);
47}
48
49static void
50_sizing_eval(Evas_Object *obj)
51{
52 Widget_Data *wd = elm_widget_data_get(obj);
53 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
54 if (!wd) return;
55 edje_object_size_min_calc(wd->sep, &minw, &minh);
56 evas_object_size_hint_min_set(obj, minw, minh);
57 evas_object_size_hint_max_set(obj, maxw, maxh);
58 evas_object_size_hint_align_set(obj, maxw, maxh);
59}
60
61EAPI Evas_Object *
62elm_separator_add(Evas_Object *parent)
63{
64 Evas_Object *obj;
65 Evas *e;
66 Widget_Data *wd;
67
68 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
69
70 ELM_SET_WIDTYPE(widtype, "separator");
71 wd->horizontal = EINA_FALSE;
72 elm_widget_type_set(obj, "separator");
73 elm_widget_sub_object_add(parent, obj);
74 elm_widget_data_set(obj, wd);
75 elm_widget_del_hook_set(obj, _del_hook);
76 elm_widget_theme_hook_set(obj, _theme_hook);
77 elm_widget_can_focus_set(obj, EINA_FALSE);
78
79 wd->sep = edje_object_add(e);
80 _elm_theme_object_set(obj, wd->sep, "separator", "vertical", "default");
81 elm_widget_resize_object_set(obj, wd->sep);
82 _mirrored_set(obj, elm_widget_mirrored_get(obj));
83 _sizing_eval(obj);
84 return obj;
85}
86
87EAPI void
88elm_separator_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
89{
90 ELM_CHECK_WIDTYPE(obj, widtype);
91 Widget_Data *wd = elm_widget_data_get(obj);
92 if (!wd) return;
93 horizontal = !!horizontal;
94 if (wd->horizontal == horizontal) return;
95 wd->horizontal = horizontal;
96 _theme_hook(obj);
97}
98
99EAPI Eina_Bool
100elm_separator_horizontal_get(const Evas_Object *obj)
101{
102 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
103 Widget_Data *wd = elm_widget_data_get(obj);
104 if (!wd) return EINA_FALSE;
105 return wd->horizontal;
106}
diff --git a/libraries/elementary/src/lib/elm_separator.h b/libraries/elementary/src/lib/elm_separator.h
new file mode 100644
index 0000000..1bc02d9
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_separator.h
@@ -0,0 +1,44 @@
1/**
2 * @defgroup Separator Separator
3 * @ingroup Elementary
4 *
5 * @brief Separator is a very thin object used to separate other objects.
6 *
7 * A separator can be vertical or horizontal.
8 *
9 * @ref tutorial_separator is a good example of how to use a separator.
10 * @{
11 */
12/**
13 * @brief Add a separator object to @p parent
14 *
15 * @param parent The parent object
16 *
17 * @return The separator object, or NULL upon failure
18 *
19 * @ingroup Separator
20 */
21EAPI Evas_Object *elm_separator_add(Evas_Object *parent);
22/**
23 * @brief Set the horizontal mode of a separator object
24 *
25 * @param obj The separator object
26 * @param horizontal If true, the separator is horizontal
27 *
28 * @ingroup Separator
29 */
30EAPI void elm_separator_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
31/**
32 * @brief Get the horizontal mode of a separator object
33 *
34 * @param obj The separator object
35 * @return If true, the separator is horizontal
36 *
37 * @see elm_separator_horizontal_set()
38 *
39 * @ingroup Separator
40 */
41EAPI Eina_Bool elm_separator_horizontal_get(const Evas_Object *obj);
42/**
43 * @}
44 */
diff --git a/libraries/elementary/src/lib/elm_slider.c b/libraries/elementary/src/lib/elm_slider.c
new file mode 100644
index 0000000..7221ea0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_slider.c
@@ -0,0 +1,1073 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *slider;
9 Evas_Object *icon;
10 Evas_Object *end;
11 Evas_Object *spacer;
12
13 Ecore_Timer *delay;
14
15 Eina_Hash *labels;
16 const char *units;
17 const char *indicator;
18
19 char *(*indicator_format_func)(double val);
20 void (*indicator_format_free)(char *str);
21
22 char *(*units_format_func)(double val);
23 void (*units_format_free)(char *str);
24
25 double val, val_min, val_max, val2;
26 Evas_Coord size;
27 Evas_Coord downx, downy;
28
29 Eina_Bool horizontal : 1;
30 Eina_Bool inverted : 1;
31 Eina_Bool indicator_show : 1;
32 Eina_Bool spacer_down : 1;
33 Eina_Bool frozen : 1;
34};
35
36#define ELM_SLIDER_INVERTED_FACTOR (-1.0)
37
38static const char *widtype = NULL;
39static void _del_hook(Evas_Object *obj);
40static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
41static void _theme_hook(Evas_Object *obj);
42static void _disable_hook(Evas_Object *obj);
43static void _sizing_eval(Evas_Object *obj);
44static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
45static void _sub_del(void *data, Evas_Object *obj, void *event_info);
46static void _units_set(Evas_Object *obj);
47static void _val_set(Evas_Object *obj);
48static void _indicator_set(Evas_Object *obj);
49static void _on_focus_hook(void *data, Evas_Object *obj);
50static void _drag_up(void *data, Evas_Object *obj,
51 const char *emission, const char *source);
52static void _drag_down(void *data, Evas_Object *obj,
53 const char *emission, const char *source);
54static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
55 Evas_Callback_Type type, void *event_info);
56static void _spacer_down_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
57static void _spacer_move_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
58static void _spacer_up_cb(void *data, Evas * e, Evas_Object * obj, void *event_info);
59
60static const char SIG_CHANGED[] = "changed";
61static const char SIG_DELAY_CHANGED[] = "delay,changed";
62static const char SIG_DRAG_START[] = "slider,drag,start";
63static const char SIG_DRAG_STOP[] = "slider,drag,stop";
64static const Evas_Smart_Cb_Description _signals[] = {
65 {SIG_CHANGED, ""},
66 {SIG_DELAY_CHANGED, ""},
67 {SIG_DRAG_START, ""},
68 {SIG_DRAG_STOP, ""},
69 {NULL, NULL}
70};
71
72static Eina_Bool
73_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
74{
75 Evas_Event_Mouse_Wheel *mev;
76 Evas_Event_Key_Down *ev;
77 Widget_Data *wd;
78
79 wd = elm_widget_data_get(obj);
80 if (!wd) return EINA_FALSE;
81
82 if (type == EVAS_CALLBACK_KEY_DOWN) goto key_down;
83 else if (type != EVAS_CALLBACK_MOUSE_WHEEL) return EINA_FALSE;
84
85 mev = event_info;
86 if (mev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
87 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
88
89 if (mev->z < 0) _drag_up(obj, NULL, NULL, NULL);
90 else _drag_down(obj, NULL, NULL, NULL);
91 mev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
92 return EINA_TRUE;
93
94 key_down:
95 ev = event_info;
96 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
97 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
98 if ((!strcmp(ev->keyname, "Left")) ||
99 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
100 {
101 if (!wd->horizontal) return EINA_FALSE;
102 if (!wd->inverted) _drag_down(obj, NULL, NULL, NULL);
103 else _drag_up(obj, NULL, NULL, NULL);
104 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
105 return EINA_TRUE;
106 }
107 else if ((!strcmp(ev->keyname, "Right")) ||
108 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
109 {
110 if (!wd->horizontal) return EINA_FALSE;
111 if (!wd->inverted) _drag_up(obj, NULL, NULL, NULL);
112 else _drag_down(obj, NULL, NULL, NULL);
113 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
114 return EINA_TRUE;
115 }
116 else if ((!strcmp(ev->keyname, "Up")) ||
117 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
118 {
119 if (wd->horizontal) return EINA_FALSE;
120 if (wd->inverted) _drag_up(obj, NULL, NULL, NULL);
121 else _drag_down(obj, NULL, NULL, NULL);
122 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
123 return EINA_TRUE;
124 }
125 else if ((!strcmp(ev->keyname, "Down")) ||
126 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
127 {
128 if (wd->horizontal) return EINA_FALSE;
129 if (wd->inverted) _drag_down(obj, NULL, NULL, NULL);
130 else _drag_up(obj, NULL, NULL, NULL);
131 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
132 return EINA_TRUE;
133 }
134 else return EINA_FALSE;
135}
136
137static void
138_del_hook(Evas_Object *obj)
139{
140 Widget_Data *wd = elm_widget_data_get(obj);
141 if (!wd) return;
142 if (wd->labels) eina_hash_free(wd->labels);
143 if (wd->indicator) eina_stringshare_del(wd->units);
144 if (wd->delay) ecore_timer_del(wd->delay);
145 free(wd);
146}
147
148static void
149_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
150{
151 Widget_Data *wd = elm_widget_data_get(obj);
152 if (!wd) return;
153 if (elm_widget_focus_get(obj))
154 {
155 edje_object_signal_emit(wd->slider, "elm,action,focus", "elm");
156 evas_object_focus_set(wd->slider, EINA_TRUE);
157 }
158 else
159 {
160 edje_object_signal_emit(wd->slider, "elm,action,unfocus", "elm");
161 evas_object_focus_set(wd->slider, EINA_FALSE);
162 }
163}
164
165static void
166_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
167{
168 Widget_Data *wd = elm_widget_data_get(obj);
169 if (!wd) return;
170 edje_object_mirrored_set(wd->slider, rtl);
171}
172
173static Eina_Bool
174_labels_foreach_text_set(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata)
175{
176 Widget_Data *wd = fdata;
177
178 edje_object_part_text_escaped_set(wd->slider, key, data);
179
180 return 1;
181}
182
183static void
184_theme_hook(Evas_Object *obj)
185{
186 Widget_Data *wd = elm_widget_data_get(obj);
187 if (!wd) return;
188 _elm_widget_mirrored_reload(obj);
189 _mirrored_set(obj, elm_widget_mirrored_get(obj));
190 if (wd->horizontal)
191 _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", elm_widget_style_get(obj));
192 else
193 _elm_theme_object_set(obj, wd->slider, "slider", "vertical", elm_widget_style_get(obj));
194 if (wd->icon)
195 {
196 edje_object_part_swallow(wd->slider, "elm.swallow.content", wd->icon);
197 edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
198 }
199 if (wd->end)
200 edje_object_signal_emit(wd->slider, "elm,state,end,visible", "elm");
201 else
202 edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
203 if (wd->labels)
204 {
205 eina_hash_foreach(wd->labels, _labels_foreach_text_set, wd);
206 edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
207 }
208
209 if (wd->units)
210 edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
211
212 if (wd->horizontal)
213 evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
214 else
215 evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
216
217 if (wd->inverted)
218 edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
219
220 edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
221 _units_set(obj);
222 _indicator_set(obj);
223 edje_object_message_signal_process(wd->slider);
224 edje_object_scale_set(wd->slider, elm_widget_scale_get(obj) * _elm_config->scale);
225 _val_set(obj);
226 _sizing_eval(obj);
227}
228
229static void
230_disable_hook(Evas_Object *obj)
231{
232 Widget_Data *wd = elm_widget_data_get(obj);
233 if (!wd) return;
234 if (elm_widget_disabled_get(obj))
235 edje_object_signal_emit(wd->slider, "elm,state,disabled", "elm");
236 else
237 edje_object_signal_emit(wd->slider, "elm,state,enabled", "elm");
238}
239
240static void
241_sizing_eval(Evas_Object *obj)
242{
243 Widget_Data *wd = elm_widget_data_get(obj);
244 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
245 if (!wd) return;
246 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
247 edje_object_size_min_restricted_calc(wd->slider, &minw, &minh, minw, minh);
248 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
249 evas_object_size_hint_min_set(obj, minw, minh);
250 evas_object_size_hint_max_set(obj, maxw, maxh);
251}
252
253static void
254_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
255{
256 Widget_Data *wd = elm_widget_data_get(data);
257 if (!wd) return;
258 if ((obj != wd->icon) && (obj != wd->end)) return;
259 _sizing_eval(data);
260}
261
262static void
263_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
264{
265 Widget_Data *wd = elm_widget_data_get(obj);
266 Evas_Object *sub = event_info;
267 if (!wd) return;
268 if (sub == wd->icon)
269 {
270 edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
271 evas_object_event_callback_del_full
272 (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
273 wd->icon = NULL;
274 edje_object_message_signal_process(wd->slider);
275 _sizing_eval(obj);
276 }
277 if (sub == wd->end)
278 {
279 edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
280 evas_object_event_callback_del_full(sub,
281 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
282 _changed_size_hints, obj);
283 wd->end = NULL;
284 edje_object_message_signal_process(wd->slider);
285 _sizing_eval(obj);
286 }
287}
288
289static Eina_Bool
290_delay_change(void *data)
291{
292 Widget_Data *wd = elm_widget_data_get(data);
293 if (!wd) return ECORE_CALLBACK_CANCEL;
294 wd->delay = NULL;
295 evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, NULL);
296 return ECORE_CALLBACK_CANCEL;
297}
298
299static void
300_val_fetch(Evas_Object *obj)
301{
302 Eina_Bool rtl;
303 Widget_Data *wd = elm_widget_data_get(obj);
304 double posx = 0.0, posy = 0.0, pos = 0.0, val;
305 if (!wd) return;
306 edje_object_part_drag_value_get(wd->slider, "elm.dragable.slider",
307 &posx, &posy);
308 if (wd->horizontal) pos = posx;
309 else pos = posy;
310
311 rtl = elm_widget_mirrored_get(obj);
312 if ((!rtl && wd->inverted) || (rtl &&
313 ((!wd->horizontal && wd->inverted) ||
314 (wd->horizontal && !wd->inverted)))) pos = 1.0 - pos;
315 val = (pos * (wd->val_max - wd->val_min)) + wd->val_min;
316 if (val != wd->val)
317 {
318 wd->val = val;
319 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
320 if (wd->delay) ecore_timer_del(wd->delay);
321 wd->delay = ecore_timer_add(0.2, _delay_change, obj);
322 }
323}
324
325static void
326_val_set(Evas_Object *obj)
327{
328 Eina_Bool rtl;
329 Widget_Data *wd = elm_widget_data_get(obj);
330 double pos;
331 if (!wd) return;
332 if (wd->val_max > wd->val_min)
333 pos = (wd->val - wd->val_min) / (wd->val_max - wd->val_min);
334 else
335 pos = 0.0;
336 if (pos < 0.0) pos = 0.0;
337 else if (pos > 1.0) pos = 1.0;
338
339 rtl = elm_widget_mirrored_get(obj);
340 if ((!rtl && wd->inverted) || (rtl &&
341 ((!wd->horizontal && wd->inverted) ||
342 (wd->horizontal && !wd->inverted)))) pos = 1.0 - pos;
343 edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", pos, pos);
344}
345
346static void
347_units_set(Evas_Object *obj)
348{
349 Widget_Data *wd = elm_widget_data_get(obj);
350 if (!wd) return;
351 if (wd->units_format_func)
352 {
353 char *buf;
354 buf = wd->units_format_func(wd->val);
355 edje_object_part_text_escaped_set(wd->slider, "elm.units", buf);
356 if (wd->units_format_free) wd->units_format_free(buf);
357 }
358 else if (wd->units)
359 {
360 char buf[1024];
361
362 snprintf(buf, sizeof(buf), wd->units, wd->val);
363 edje_object_part_text_escaped_set(wd->slider, "elm.units", buf);
364 }
365 else
366 edje_object_part_text_escaped_set(wd->slider, "elm.units", NULL);
367}
368
369static void
370_indicator_set(Evas_Object *obj)
371{
372 Widget_Data *wd = elm_widget_data_get(obj);
373 if (!wd) return;
374 if (wd->indicator_format_func)
375 {
376 char *buf;
377 buf = wd->indicator_format_func(wd->val);
378 edje_object_part_text_escaped_set(wd->slider, "elm.dragable.slider:elm.indicator", buf);
379 if (wd->indicator_format_free) wd->indicator_format_free(buf);
380 }
381 else if (wd->indicator)
382 {
383 char buf[1024];
384 snprintf(buf, sizeof(buf), wd->indicator, wd->val);
385 edje_object_part_text_escaped_set(wd->slider, "elm.dragable.slider:elm.indicator", buf);
386 }
387 else
388 edje_object_part_text_escaped_set(wd->slider, "elm.dragable.slider:elm.indicator", NULL);
389}
390
391static void
392_drag(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
393{
394 _val_fetch(data);
395 _units_set(data);
396 _indicator_set(data);
397}
398
399static void
400_drag_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
401{
402 _val_fetch(data);
403 evas_object_smart_callback_call(data, SIG_DRAG_START, NULL);
404 _units_set(data);
405 _indicator_set(data);
406 elm_widget_scroll_freeze_push(data);
407}
408
409static void
410_drag_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
411{
412 _val_fetch(data);
413 evas_object_smart_callback_call(data, SIG_DRAG_STOP, NULL);
414 _units_set(data);
415 _indicator_set(data);
416 elm_widget_scroll_freeze_pop(data);
417}
418
419static void
420_drag_step(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
421{
422 _val_fetch(data);
423 _units_set(data);
424 _indicator_set(data);
425}
426
427static void
428_drag_up(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
429{
430 double step;
431 Widget_Data *wd;
432
433 wd = elm_widget_data_get(data);
434 step = 0.05;
435
436 if (wd->inverted) step *= ELM_SLIDER_INVERTED_FACTOR;
437
438 edje_object_part_drag_step(wd->slider, "elm.dragable.slider", step, step);
439}
440
441static void
442_drag_down(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
443{
444 double step;
445 Widget_Data *wd;
446
447 wd = elm_widget_data_get(data);
448 step = -0.05;
449
450 if (wd->inverted) step *= ELM_SLIDER_INVERTED_FACTOR;
451
452 edje_object_part_drag_step(wd->slider, "elm.dragable.slider", step, step);
453}
454
455static void
456_spacer_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
457{
458 Widget_Data *wd = elm_widget_data_get(data);
459 Evas_Event_Mouse_Down *ev = event_info;
460 Evas_Coord x, y, w, h;
461 double button_x = 0.0, button_y = 0.0;
462
463 wd->spacer_down = EINA_TRUE;
464 wd->val2 = wd->val;
465 evas_object_geometry_get(wd->spacer, &x, &y, &w, &h);
466 wd->downx = ev->canvas.x - x;
467 wd->downy = ev->canvas.y - y;
468 if (wd->horizontal)
469 {
470 button_x = ((double)ev->canvas.x - (double)x) / (double)w;
471 if (button_x > 1) button_x = 1;
472 if (button_x < 0) button_x = 0;
473 }
474 else
475 {
476 button_y = ((double)ev->canvas.y - (double)y) / (double)h;
477 if (button_y > 1) button_y = 1;
478 if (button_y < 0) button_y = 0;
479 }
480 edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", button_x, button_y);
481 _val_fetch(data);
482 evas_object_smart_callback_call(data, SIG_DRAG_START, NULL);
483 _units_set(data);
484 _indicator_set(data);
485 edje_object_signal_emit(wd->slider, "elm,state,indicator,show", "elm");
486}
487
488static void
489_spacer_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
490{
491 Widget_Data *wd = elm_widget_data_get(data);
492 Evas_Event_Mouse_Move *ev = event_info;
493 Evas_Coord x, y, w, h;
494 double button_x = 0.0, button_y = 0.0;
495
496 if (wd->spacer_down)
497 {
498 Evas_Coord d = 0;
499
500 evas_object_geometry_get(wd->spacer, &x, &y, &w, &h);
501 if (wd->horizontal) d = abs(ev->cur.canvas.x - x - wd->downx);
502 else d = abs(ev->cur.canvas.y - y - wd->downy);
503 if (d > (_elm_config->thumbscroll_threshold - 1))
504 {
505 if (!wd->frozen)
506 {
507 elm_widget_scroll_freeze_push(data);
508 wd->frozen = 1;
509 }
510 ev->event_flags &= ~EVAS_EVENT_FLAG_ON_HOLD;
511 }
512
513 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
514 {
515 if (wd->spacer_down) wd->spacer_down = EINA_FALSE;
516 _val_fetch(data);
517 evas_object_smart_callback_call(data, SIG_DRAG_STOP, NULL);
518 _units_set(data);
519 _indicator_set(data);
520 if (wd->frozen)
521 {
522 elm_widget_scroll_freeze_pop(data);
523 wd->frozen = 0;
524 }
525 edje_object_signal_emit(wd->slider, "elm,state,indicator,hide", "elm");
526 elm_slider_value_set(data, wd->val2);
527 return;
528 }
529 if (wd->horizontal)
530 {
531 button_x = ((double)ev->cur.canvas.x - (double)x) / (double)w;
532 if (button_x > 1) button_x = 1;
533 if (button_x < 0) button_x = 0;
534 }
535 else
536 {
537 button_y = ((double)ev->cur.canvas.y - (double)y) / (double)h;
538 if (button_y > 1) button_y = 1;
539 if (button_y < 0) button_y = 0;
540 }
541 edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", button_x, button_y);
542 _val_fetch(data);
543 _units_set(data);
544 _indicator_set(data);
545 }
546}
547
548static void
549_spacer_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
550{
551 Widget_Data *wd = elm_widget_data_get(data);
552
553 if (!wd->spacer_down) return;
554 if (wd->spacer_down) wd->spacer_down = EINA_FALSE;
555 _val_fetch(data);
556 evas_object_smart_callback_call(data, SIG_DRAG_STOP, NULL);
557 _units_set(data);
558 _indicator_set(data);
559 if (wd->frozen)
560 {
561 elm_widget_scroll_freeze_pop(data);
562 wd->frozen = 0;
563 }
564 edje_object_signal_emit(wd->slider, "elm,state,indicator,hide", "elm");
565}
566
567static void
568_elm_slider_label_set(Evas_Object *obj, const char *part, const char *label)
569{
570 ELM_CHECK_WIDTYPE(obj, widtype);
571 Widget_Data *wd = elm_widget_data_get(obj);
572 const char* default_part = "elm.text";
573 const char* real_part;
574
575 if (!wd) return;
576
577 if (!part)
578 real_part = default_part;
579 else
580 real_part = part;
581
582 if (wd->labels)
583 {
584 const char* old_label;
585
586 old_label = eina_hash_find(wd->labels, real_part);
587 if (!old_label)
588 eina_hash_add(wd->labels, real_part, eina_stringshare_add(label));
589 else
590 {
591 eina_stringshare_ref(old_label);
592 eina_hash_modify(wd->labels, real_part, eina_stringshare_add(label));
593 eina_stringshare_del(old_label);
594 }
595 }
596
597 if (label)
598 {
599 edje_object_signal_emit(wd->slider, "elm,state,text,visible", "elm");
600 edje_object_message_signal_process(wd->slider);
601 }
602 else
603 {
604 edje_object_signal_emit(wd->slider, "elm,state,text,hidden", "elm");
605 edje_object_message_signal_process(wd->slider);
606 }
607
608 edje_object_part_text_escaped_set(wd->slider, real_part, label);
609 _sizing_eval(obj);
610}
611
612static const char *
613_elm_slider_label_get(const Evas_Object *obj, const char *part)
614{
615 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
616 Widget_Data *wd = elm_widget_data_get(obj);
617 if (!wd) return NULL;
618 if (!wd->labels) return NULL;
619
620 if (!part)
621 return eina_hash_find(wd->labels, "elm.text");
622 return eina_hash_find(wd->labels, part);
623}
624
625static void
626_icon_set(Evas_Object *obj, Evas_Object *icon)
627{
628 Widget_Data *wd = elm_widget_data_get(obj);
629 if (!wd) return;
630 if (wd->icon == icon) return;
631 if (wd->icon) evas_object_del(wd->icon);
632 wd->icon = icon;
633 if (icon)
634 {
635 elm_widget_sub_object_add(obj, icon);
636 evas_object_event_callback_add(icon, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
637 _changed_size_hints, obj);
638 edje_object_part_swallow(wd->slider, "elm.swallow.icon", icon);
639 edje_object_signal_emit(wd->slider, "elm,state,icon,visible", "elm");
640 edje_object_message_signal_process(wd->slider);
641 }
642 _sizing_eval(obj);
643}
644
645static Evas_Object *
646_icon_unset(Evas_Object *obj)
647{
648 Widget_Data *wd = elm_widget_data_get(obj);
649 Evas_Object *ret = NULL;
650 if (!wd) return NULL;
651 if (wd->icon)
652 {
653 elm_widget_sub_object_del(obj, wd->icon);
654 evas_object_event_callback_del_full(wd->icon,
655 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
656 _changed_size_hints, obj);
657 ret = wd->icon;
658 edje_object_part_unswallow(wd->slider, wd->icon);
659 edje_object_signal_emit(wd->slider, "elm,state,icon,hidden", "elm");
660 wd->icon = NULL;
661 _sizing_eval(obj);
662 }
663 return ret;
664}
665
666static void
667_end_set(Evas_Object *obj, Evas_Object *end)
668{
669 Widget_Data *wd = elm_widget_data_get(obj);
670 if (!wd) return;
671 if (wd->end == end) return;
672 if (wd->end) evas_object_del(wd->end);
673 wd->end = end;
674 if (end)
675 {
676 elm_widget_sub_object_add(obj, end);
677 evas_object_event_callback_add(end, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
678 _changed_size_hints, obj);
679 edje_object_part_swallow(wd->slider, "elm.swallow.end", end);
680 edje_object_signal_emit(wd->slider, "elm,state,end,visible", "elm");
681 edje_object_message_signal_process(wd->slider);
682 }
683 _sizing_eval(obj);
684}
685
686static Evas_Object *
687_end_unset(Evas_Object *obj)
688{
689 Widget_Data *wd = elm_widget_data_get(obj);
690 Evas_Object *ret = NULL;
691 if (!wd) return NULL;
692 if (wd->end)
693 {
694 elm_widget_sub_object_del(obj, wd->end);
695 evas_object_event_callback_del_full(wd->end,
696 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
697 _changed_size_hints, obj);
698 ret = wd->end;
699 edje_object_part_unswallow(wd->slider, wd->end);
700 edje_object_signal_emit(wd->slider, "elm,state,end,hidden", "elm");
701 wd->end = NULL;
702 _sizing_eval(obj);
703 }
704 return ret;
705}
706
707static void
708_content_set_hook(Evas_Object *obj, const char *part, Evas_Object *content)
709{
710 ELM_CHECK_WIDTYPE(obj, widtype);
711 if (!part || !strcmp(part, "icon"))
712 _icon_set(obj, content);
713 else if (!strcmp(part, "end"))
714 _end_set(obj, content);
715}
716
717static Evas_Object *
718_content_get_hook(const Evas_Object *obj, const char *part)
719{
720 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
721 Widget_Data *wd;
722 wd = elm_widget_data_get(obj);
723 if (!wd) return NULL;
724 if (!part || !strcmp(part, "icon"))
725 return wd->icon;
726 else if (!strcmp(part, "end"))
727 return wd->end;
728 return NULL;
729}
730
731static Evas_Object *
732_content_unset_hook(Evas_Object *obj, const char *part)
733{
734 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
735 if (!part || !strcmp(part, "icon"))
736 return _icon_unset(obj);
737 else if (!strcmp(part, "end"))
738 return _end_unset(obj);
739 return NULL;
740}
741
742static void
743_hash_labels_free_cb(void* label)
744{
745 if (label)
746 eina_stringshare_del(label);
747}
748
749static void
750_min_max_set(Evas_Object *obj)
751{
752 char *buf_min = NULL;
753 char *buf_max = NULL;
754
755 Widget_Data *wd = elm_widget_data_get(obj);
756 if (!wd) return;
757 if (wd->units_format_func)
758 {
759 buf_min = wd->units_format_func(wd->val_min);
760 buf_max = wd->units_format_func(wd->val_max);
761 }
762 else if (wd->units)
763 {
764 int length = strlen(wd->units);
765
766 buf_min = alloca(length + 128);
767 buf_max = alloca(length + 128);
768
769 snprintf((char*) buf_min, length + 128, wd->units, wd->val_min);
770 snprintf((char*) buf_max, length + 128, wd->units, wd->val_max);
771 }
772
773 edje_object_part_text_escaped_set(wd->slider, "elm.units.min", buf_min);
774 edje_object_part_text_escaped_set(wd->slider, "elm.units.max", buf_max);
775
776 if (wd->units_format_func && wd->units_format_free)
777 {
778 wd->units_format_free(buf_min);
779 wd->units_format_free(buf_max);
780 }
781}
782
783
784EAPI Evas_Object *
785elm_slider_add(Evas_Object *parent)
786{
787 Evas_Object *obj;
788 Evas *e;
789 Widget_Data *wd;
790
791 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
792
793 ELM_SET_WIDTYPE(widtype, "slider");
794 elm_widget_type_set(obj, "slider");
795 elm_widget_sub_object_add(parent, obj);
796 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
797 elm_widget_data_set(obj, wd);
798 elm_widget_del_hook_set(obj, _del_hook);
799 elm_widget_theme_hook_set(obj, _theme_hook);
800 elm_widget_disable_hook_set(obj, _disable_hook);
801 elm_widget_can_focus_set(obj, EINA_TRUE);
802 elm_widget_event_hook_set(obj, _event_hook);
803 elm_widget_text_set_hook_set(obj, _elm_slider_label_set);
804 elm_widget_text_get_hook_set(obj, _elm_slider_label_get);
805 elm_widget_content_set_hook_set(obj, _content_set_hook);
806 elm_widget_content_get_hook_set(obj, _content_get_hook);
807 elm_widget_content_unset_hook_set(obj, _content_unset_hook);
808
809 wd->horizontal = EINA_TRUE;
810 wd->indicator_show = EINA_TRUE;
811 wd->val = 0.0;
812 wd->val_min = 0.0;
813 wd->val_max = 1.0;
814 wd->labels = eina_hash_string_superfast_new(_hash_labels_free_cb);
815
816 wd->slider = edje_object_add(e);
817 _elm_theme_object_set(obj, wd->slider, "slider", "horizontal", "default");
818 elm_widget_resize_object_set(obj, wd->slider);
819 edje_object_signal_callback_add(wd->slider, "drag", "*", _drag, obj);
820 edje_object_signal_callback_add(wd->slider, "drag,start", "*", _drag_start, obj);
821 edje_object_signal_callback_add(wd->slider, "drag,stop", "*", _drag_stop, obj);
822 edje_object_signal_callback_add(wd->slider, "drag,step", "*", _drag_step, obj);
823 edje_object_signal_callback_add(wd->slider, "drag,page", "*", _drag_stop, obj);
824 // edje_object_signal_callback_add(wd->slider, "drag,set", "*", _drag_stop, obj);
825 edje_object_part_drag_value_set(wd->slider, "elm.dragable.slider", 0.0, 0.0);
826
827 wd->spacer = evas_object_rectangle_add(e);
828 evas_object_color_set(wd->spacer, 0, 0, 0, 0);
829 evas_object_pass_events_set(wd->spacer, EINA_TRUE);
830 elm_widget_sub_object_add(obj, wd->spacer);
831 edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
832 evas_object_event_callback_add(wd->spacer, EVAS_CALLBACK_MOUSE_DOWN, _spacer_down_cb, obj);
833 evas_object_event_callback_add(wd->spacer, EVAS_CALLBACK_MOUSE_MOVE, _spacer_move_cb, obj);
834 evas_object_event_callback_add(wd->spacer, EVAS_CALLBACK_MOUSE_UP, _spacer_up_cb, obj);
835 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
836
837 _mirrored_set(obj, elm_widget_mirrored_get(obj));
838 _sizing_eval(obj);
839
840 // TODO: convert Elementary to subclassing of Evas_Smart_Class
841 // TODO: and save some bytes, making descriptions per-class and not instance!
842 evas_object_smart_callbacks_descriptions_set(obj, _signals);
843 return obj;
844}
845
846EAPI void
847elm_slider_span_size_set(Evas_Object *obj, Evas_Coord size)
848{
849 ELM_CHECK_WIDTYPE(obj, widtype);
850 Widget_Data *wd = elm_widget_data_get(obj);
851 if (!wd) return;
852 if (wd->size == size) return;
853 wd->size = size;
854 if (wd->horizontal)
855 evas_object_size_hint_min_set(wd->spacer, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale, 1);
856 else
857 evas_object_size_hint_min_set(wd->spacer, 1, (double)wd->size * elm_widget_scale_get(obj) * _elm_config->scale);
858 if (wd->indicator_show)
859 edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
860 else
861 edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");
862 edje_object_part_swallow(wd->slider, "elm.swallow.bar", wd->spacer);
863 _sizing_eval(obj);
864}
865
866EAPI Evas_Coord
867elm_slider_span_size_get(const Evas_Object *obj)
868{
869 ELM_CHECK_WIDTYPE(obj, widtype) 0;
870 Widget_Data *wd = elm_widget_data_get(obj);
871 if (!wd) return 0;
872 return wd->size;
873}
874
875EAPI void
876elm_slider_unit_format_set(Evas_Object *obj, const char *units)
877{
878 ELM_CHECK_WIDTYPE(obj, widtype);
879 Widget_Data *wd = elm_widget_data_get(obj);
880 if (!wd) return;
881 eina_stringshare_replace(&wd->units, units);
882 if (units)
883 {
884 edje_object_signal_emit(wd->slider, "elm,state,units,visible", "elm");
885 edje_object_message_signal_process(wd->slider);
886 }
887 else
888 {
889 edje_object_signal_emit(wd->slider, "elm,state,units,hidden", "elm");
890 edje_object_message_signal_process(wd->slider);
891 }
892 _min_max_set(obj);
893 _units_set(obj);
894 _sizing_eval(obj);
895}
896
897EAPI const char *
898elm_slider_unit_format_get(const Evas_Object *obj)
899{
900 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
901 Widget_Data *wd = elm_widget_data_get(obj);
902 if (!wd) return NULL;
903 return wd->units;
904}
905
906EAPI void
907elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator)
908{
909 ELM_CHECK_WIDTYPE(obj, widtype);
910 Widget_Data *wd = elm_widget_data_get(obj);
911 if (!wd) return;
912 eina_stringshare_replace(&wd->indicator, indicator);
913 _indicator_set(obj);
914}
915
916EAPI const char *
917elm_slider_indicator_format_get(const Evas_Object *obj)
918{
919 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
920 Widget_Data *wd = elm_widget_data_get(obj);
921 if (!wd) return NULL;
922 return wd->indicator;
923}
924
925EAPI void
926elm_slider_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
927{
928 ELM_CHECK_WIDTYPE(obj, widtype);
929 Widget_Data *wd = elm_widget_data_get(obj);
930 if (!wd) return;
931 horizontal = !!horizontal;
932 if (wd->horizontal == horizontal) return;
933 wd->horizontal = horizontal;
934 _theme_hook(obj);
935}
936
937EAPI Eina_Bool
938elm_slider_horizontal_get(const Evas_Object *obj)
939{
940 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
941 Widget_Data *wd = elm_widget_data_get(obj);
942 if (!wd) return EINA_FALSE;
943 return wd->horizontal;
944}
945
946EAPI void
947elm_slider_min_max_set(Evas_Object *obj, double min, double max)
948{
949 ELM_CHECK_WIDTYPE(obj, widtype);
950 Widget_Data *wd = elm_widget_data_get(obj);
951 if (!wd) return;
952 if ((wd->val_min == min) && (wd->val_max == max)) return;
953 wd->val_min = min;
954 wd->val_max = max;
955 if (wd->val < wd->val_min) wd->val = wd->val_min;
956 if (wd->val > wd->val_max) wd->val = wd->val_max;
957 _min_max_set(obj);
958 _val_set(obj);
959 _units_set(obj);
960 _indicator_set(obj);
961}
962
963EAPI void
964elm_slider_min_max_get(const Evas_Object *obj, double *min, double *max)
965{
966 if (min) *min = 0.0;
967 if (max) *max = 0.0;
968 ELM_CHECK_WIDTYPE(obj, widtype);
969 Widget_Data *wd = elm_widget_data_get(obj);
970 if (!wd) return;
971 if (min) *min = wd->val_min;
972 if (max) *max = wd->val_max;
973}
974
975EAPI void
976elm_slider_value_set(Evas_Object *obj, double val)
977{
978 ELM_CHECK_WIDTYPE(obj, widtype);
979 Widget_Data *wd = elm_widget_data_get(obj);
980 if (!wd) return;
981 if (wd->val == val) return;
982 wd->val = val;
983 if (wd->val < wd->val_min) wd->val = wd->val_min;
984 if (wd->val > wd->val_max) wd->val = wd->val_max;
985 _val_set(obj);
986 _units_set(obj);
987 _indicator_set(obj);
988}
989
990EAPI double
991elm_slider_value_get(const Evas_Object *obj)
992{
993 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
994 Widget_Data *wd = elm_widget_data_get(obj);
995 if (!wd) return 0.0;
996 return wd->val;
997}
998
999EAPI void
1000elm_slider_inverted_set(Evas_Object *obj, Eina_Bool inverted)
1001{
1002 ELM_CHECK_WIDTYPE(obj, widtype);
1003 Widget_Data *wd = elm_widget_data_get(obj);
1004 if (!wd) return;
1005 inverted = !!inverted;
1006 if (wd->inverted == inverted) return;
1007 wd->inverted = inverted;
1008 if (wd->inverted)
1009 edje_object_signal_emit(wd->slider, "elm,state,inverted,on", "elm");
1010 else
1011 edje_object_signal_emit(wd->slider, "elm,state,inverted,off", "elm");
1012 edje_object_message_signal_process(wd->slider);
1013 _val_set(obj);
1014 _units_set(obj);
1015 _indicator_set(obj);
1016}
1017
1018EAPI Eina_Bool
1019elm_slider_inverted_get(const Evas_Object *obj)
1020{
1021 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1022 Widget_Data *wd = elm_widget_data_get(obj);
1023 if (!wd) return EINA_FALSE;
1024 return wd->inverted;
1025}
1026
1027EAPI void
1028elm_slider_indicator_format_function_set(Evas_Object *obj, char *(*func)(double val), void (*free_func)(char *str))
1029{
1030 ELM_CHECK_WIDTYPE(obj, widtype);
1031 Widget_Data *wd = elm_widget_data_get(obj);
1032 if (!wd) return;
1033 wd->indicator_format_func = func;
1034 wd->indicator_format_free = free_func;
1035 _indicator_set(obj);
1036}
1037
1038EAPI void
1039elm_slider_units_format_function_set(Evas_Object *obj, char *(*func)(double val), void (*free_func)(char *str))
1040{
1041 ELM_CHECK_WIDTYPE(obj, widtype);
1042 Widget_Data *wd = elm_widget_data_get(obj);
1043 if (!wd) return;
1044 wd->units_format_func = func;
1045 wd->units_format_free = free_func;
1046 _min_max_set(obj);
1047 _units_set(obj);
1048}
1049
1050EAPI void
1051elm_slider_indicator_show_set(Evas_Object *obj, Eina_Bool show)
1052{
1053 ELM_CHECK_WIDTYPE(obj, widtype);
1054 Widget_Data *wd = elm_widget_data_get(obj);
1055 if (show) {
1056 wd->indicator_show = EINA_TRUE;
1057 edje_object_signal_emit(wd->slider, "elm,state,val,show", "elm");
1058 }
1059 else {
1060 wd->indicator_show = EINA_FALSE;
1061 edje_object_signal_emit(wd->slider, "elm,state,val,hide", "elm");
1062 }
1063}
1064
1065EAPI Eina_Bool
1066elm_slider_indicator_show_get(const Evas_Object *obj)
1067{
1068 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1069 Widget_Data *wd = elm_widget_data_get(obj);
1070 if (!wd) return EINA_FALSE;
1071 return wd->indicator_show;
1072}
1073
diff --git a/libraries/elementary/src/lib/elm_slider.h b/libraries/elementary/src/lib/elm_slider.h
new file mode 100644
index 0000000..5375aaf
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_slider.h
@@ -0,0 +1,400 @@
1/**
2 * @defgroup Slider Slider
3 * @ingroup Elementary
4 *
5 * @image html img/widget/slider/preview-00.png
6 * @image latex img/widget/slider/preview-00.eps width=\textwidth
7 *
8 * The slider adds a draggable “slider” widget for selecting the value of
9 * something within a range.
10 *
11 * A slider can be horizontal or vertical. It can contain an Icon and has a
12 * primary label as well as a units label (that is formatted with floating
13 * point values and thus accepts a printf-style format string, like
14 * “%1.2f units”. There is also an indicator string that may be somewhere
15 * else (like on the slider itself) that also accepts a format string like
16 * units. Label, Icon Unit and Indicator strings/objects are optional.
17 *
18 * A slider may be inverted which means values invert, with high vales being
19 * on the left or top and low values on the right or bottom (as opposed to
20 * normally being low on the left or top and high on the bottom and right).
21 *
22 * The slider should have its minimum and maximum values set by the
23 * application with elm_slider_min_max_set() and value should also be set by
24 * the application before use with elm_slider_value_set(). The span of the
25 * slider is its length (horizontally or vertically). This will be scaled by
26 * the object or applications scaling factor. At any point code can query the
27 * slider for its value with elm_slider_value_get().
28 *
29 * Smart callbacks one can listen to:
30 * - "changed" - Whenever the slider value is changed by the user.
31 * - "slider,drag,start" - dragging the slider indicator around has started.
32 * - "slider,drag,stop" - dragging the slider indicator around has stopped.
33 * - "delay,changed" - A short time after the value is changed by the user.
34 * This will be called only when the user stops dragging for
35 * a very short period or when they release their
36 * finger/mouse, so it avoids possibly expensive reactions to
37 * the value change.
38 *
39 * Available styles for it:
40 * - @c "default"
41 *
42 * Default content parts of the slider widget that you can use for are:
43 * @li "icon" - An icon of the slider
44 * @li "end" - A end part content of the slider
45 *
46 * Default text parts of the slider widget that you can use for are:
47 * @li "default" - Label of the slider
48 *
49 * Supported elm_object common APIs.
50 * @li @ref elm_object_disabled_set
51 * @li @ref elm_object_disabled_get
52 * @li @ref elm_object_part_text_set
53 * @li @ref elm_object_part_text_get
54 * @li @ref elm_object_part_content_set
55 * @li @ref elm_object_part_content_get
56 * @li @ref elm_object_part_content_unset
57 *
58 * Here is an example on its usage:
59 * @li @ref slider_example
60 */
61
62/**
63 * @addtogroup Slider
64 * @{
65 */
66
67/**
68 * Add a new slider widget to the given parent Elementary
69 * (container) object.
70 *
71 * @param parent The parent object.
72 * @return a new slider widget handle or @c NULL, on errors.
73 *
74 * This function inserts a new slider widget on the canvas.
75 *
76 * @ingroup Slider
77 */
78EAPI Evas_Object *elm_slider_add(Evas_Object *parent);
79
80/**
81 * Set the (exact) length of the bar region of a given slider widget.
82 *
83 * @param obj The slider object.
84 * @param size The length of the slider's bar region.
85 *
86 * This sets the minimum width (when in horizontal mode) or height
87 * (when in vertical mode) of the actual bar area of the slider
88 * @p obj. This in turn affects the object's minimum size. Use
89 * this when you're not setting other size hints expanding on the
90 * given direction (like weight and alignment hints) and you would
91 * like it to have a specific size.
92 *
93 * @note Icon, end, label, indicator and unit text around @p obj
94 * will require their
95 * own space, which will make @p obj to require more the @p size,
96 * actually.
97 *
98 * @see elm_slider_span_size_get()
99 *
100 * @ingroup Slider
101 */
102EAPI void elm_slider_span_size_set(Evas_Object *obj, Evas_Coord size);
103
104/**
105 * Get the length set for the bar region of a given slider widget
106 *
107 * @param obj The slider object.
108 * @return The length of the slider's bar region.
109 *
110 * If that size was not set previously, with
111 * elm_slider_span_size_set(), this call will return @c 0.
112 *
113 * @ingroup Slider
114 */
115EAPI Evas_Coord elm_slider_span_size_get(const Evas_Object *obj);
116
117/**
118 * Set the format string for the unit label.
119 *
120 * @param obj The slider object.
121 * @param format The format string for the unit display.
122 *
123 * Unit label is displayed all the time, if set, after slider's bar.
124 * In horizontal mode, at right and in vertical mode, at bottom.
125 *
126 * If @c NULL, unit label won't be visible. If not it sets the format
127 * string for the label text. To the label text is provided a floating point
128 * value, so the label text can display up to 1 floating point value.
129 * Note that this is optional.
130 *
131 * Use a format string such as "%1.2f meters" for example, and it will
132 * display values like: "3.14 meters" for a value equal to 3.14159.
133 *
134 * Default is unit label disabled.
135 *
136 * @see elm_slider_indicator_format_get()
137 *
138 * @ingroup Slider
139 */
140EAPI void elm_slider_unit_format_set(Evas_Object *obj, const char *format);
141
142/**
143 * Get the unit label format of the slider.
144 *
145 * @param obj The slider object.
146 * @return The unit label format string in UTF-8.
147 *
148 * Unit label is displayed all the time, if set, after slider's bar.
149 * In horizontal mode, at right and in vertical mode, at bottom.
150 *
151 * @see elm_slider_unit_format_set() for more
152 * information on how this works.
153 *
154 * @ingroup Slider
155 */
156EAPI const char *elm_slider_unit_format_get(const Evas_Object *obj);
157
158/**
159 * Set the format string for the indicator label.
160 *
161 * @param obj The slider object.
162 * @param indicator The format string for the indicator display.
163 *
164 * The slider may display its value somewhere else then unit label,
165 * for example, above the slider knob that is dragged around. This function
166 * sets the format string used for this.
167 *
168 * If @c NULL, indicator label won't be visible. If not it sets the format
169 * string for the label text. To the label text is provided a floating point
170 * value, so the label text can display up to 1 floating point value.
171 * Note that this is optional.
172 *
173 * Use a format string such as "%1.2f meters" for example, and it will
174 * display values like: "3.14 meters" for a value equal to 3.14159.
175 *
176 * Default is indicator label disabled.
177 *
178 * @see elm_slider_indicator_format_get()
179 *
180 * @ingroup Slider
181 */
182EAPI void elm_slider_indicator_format_set(Evas_Object *obj, const char *indicator);
183
184/**
185 * Get the indicator label format of the slider.
186 *
187 * @param obj The slider object.
188 * @return The indicator label format string in UTF-8.
189 *
190 * The slider may display its value somewhere else then unit label,
191 * for example, above the slider knob that is dragged around. This function
192 * gets the format string used for this.
193 *
194 * @see elm_slider_indicator_format_set() for more
195 * information on how this works.
196 *
197 * @ingroup Slider
198 */
199EAPI const char *elm_slider_indicator_format_get(const Evas_Object *obj);
200
201/**
202 * Set the format function pointer for the indicator label
203 *
204 * @param obj The slider object.
205 * @param func The indicator format function.
206 * @param free_func The freeing function for the format string.
207 *
208 * Set the callback function to format the indicator string.
209 *
210 * @see elm_slider_indicator_format_set() for more info on how this works.
211 *
212 * @ingroup Slider
213 */
214EAPI void elm_slider_indicator_format_function_set(Evas_Object *obj, char *(*func)(double val), void (*free_func)(char *str));
215
216/**
217 * Set the format function pointer for the units label
218 *
219 * @param obj The slider object.
220 * @param func The units format function.
221 * @param free_func The freeing function for the format string.
222 *
223 * Set the callback function to format the indicator string.
224 *
225 * @see elm_slider_units_format_set() for more info on how this works.
226 *
227 * @ingroup Slider
228 */
229EAPI void elm_slider_units_format_function_set(Evas_Object *obj, char *(*func)(double val), void (*free_func)(char *str));
230
231/**
232 * Set the orientation of a given slider widget.
233 *
234 * @param obj The slider object.
235 * @param horizontal Use @c EINA_TRUE to make @p obj to be
236 * @b horizontal, @c EINA_FALSE to make it @b vertical.
237 *
238 * Use this function to change how your slider is to be
239 * disposed: vertically or horizontally.
240 *
241 * By default it's displayed horizontally.
242 *
243 * @see elm_slider_horizontal_get()
244 *
245 * @ingroup Slider
246 */
247EAPI void elm_slider_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
248
249/**
250 * Retrieve the orientation of a given slider widget
251 *
252 * @param obj The slider object.
253 * @return @c EINA_TRUE, if @p obj is set to be @b horizontal,
254 * @c EINA_FALSE if it's @b vertical (and on errors).
255 *
256 * @see elm_slider_horizontal_set() for more details.
257 *
258 * @ingroup Slider
259 */
260EAPI Eina_Bool elm_slider_horizontal_get(const Evas_Object *obj);
261
262/**
263 * Set the minimum and maximum values for the slider.
264 *
265 * @param obj The slider object.
266 * @param min The minimum value.
267 * @param max The maximum value.
268 *
269 * Define the allowed range of values to be selected by the user.
270 *
271 * If actual value is less than @p min, it will be updated to @p min. If it
272 * is bigger then @p max, will be updated to @p max. Actual value can be
273 * get with elm_slider_value_get().
274 *
275 * By default, min is equal to 0.0, and max is equal to 1.0.
276 *
277 * @warning Maximum must be greater than minimum, otherwise behavior
278 * is undefined.
279 *
280 * @see elm_slider_min_max_get()
281 *
282 * @ingroup Slider
283 */
284EAPI void elm_slider_min_max_set(Evas_Object *obj, double min, double max);
285
286/**
287 * Get the minimum and maximum values of the slider.
288 *
289 * @param obj The slider object.
290 * @param min Pointer to store the minimum value.
291 * @param max Pointer to store the maximum value.
292 *
293 * @note If only one value is needed, the other pointer can be passed
294 * as @c NULL.
295 *
296 * @see elm_slider_min_max_set() for details.
297 *
298 * @ingroup Slider
299 */
300EAPI void elm_slider_min_max_get(const Evas_Object *obj, double *min, double *max);
301
302/**
303 * Set the value the slider displays.
304 *
305 * @param obj The slider object.
306 * @param val The value to be displayed.
307 *
308 * Value will be presented on the unit label following format specified with
309 * elm_slider_unit_format_set() and on indicator with
310 * elm_slider_indicator_format_set().
311 *
312 * @warning The value must to be between min and max values. This values
313 * are set by elm_slider_min_max_set().
314 *
315 * @see elm_slider_value_get()
316 * @see elm_slider_unit_format_set()
317 * @see elm_slider_indicator_format_set()
318 * @see elm_slider_min_max_set()
319 *
320 * @ingroup Slider
321 */
322EAPI void elm_slider_value_set(Evas_Object *obj, double val);
323
324/**
325 * Get the value displayed by the spinner.
326 *
327 * @param obj The spinner object.
328 * @return The value displayed.
329 *
330 * @see elm_spinner_value_set() for details.
331 *
332 * @ingroup Slider
333 */
334EAPI double elm_slider_value_get(const Evas_Object *obj);
335
336/**
337 * Invert a given slider widget's displaying values order
338 *
339 * @param obj The slider object.
340 * @param inverted Use @c EINA_TRUE to make @p obj inverted,
341 * @c EINA_FALSE to bring it back to default, non-inverted values.
342 *
343 * A slider may be @b inverted, in which state it gets its
344 * values inverted, with high vales being on the left or top and
345 * low values on the right or bottom, as opposed to normally have
346 * the low values on the former and high values on the latter,
347 * respectively, for horizontal and vertical modes.
348 *
349 * @see elm_slider_inverted_get()
350 *
351 * @ingroup Slider
352 */
353EAPI void elm_slider_inverted_set(Evas_Object *obj, Eina_Bool inverted);
354
355/**
356 * Get whether a given slider widget's displaying values are
357 * inverted or not.
358 *
359 * @param obj The slider object.
360 * @return @c EINA_TRUE, if @p obj has inverted values,
361 * @c EINA_FALSE otherwise (and on errors).
362 *
363 * @see elm_slider_inverted_set() for more details.
364 *
365 * @ingroup Slider
366 */
367EAPI Eina_Bool elm_slider_inverted_get(const Evas_Object *obj);
368
369/**
370 * Set whether to enlarge slider indicator (augmented knob) or not.
371 *
372 * @param obj The slider object.
373 * @param show @c EINA_TRUE will make it enlarge, @c EINA_FALSE will
374 * let the knob always at default size.
375 *
376 * By default, indicator will be bigger while dragged by the user.
377 *
378 * @warning It won't display values set with
379 * elm_slider_indicator_format_set() if you disable indicator.
380 *
381 * @ingroup Slider
382 */
383EAPI void elm_slider_indicator_show_set(Evas_Object *obj, Eina_Bool show);
384
385/**
386 * Get whether a given slider widget's enlarging indicator or not.
387 *
388 * @param obj The slider object.
389 * @return @c EINA_TRUE, if @p obj is enlarging indicator, or
390 * @c EINA_FALSE otherwise (and on errors).
391 *
392 * @see elm_slider_indicator_show_set() for details.
393 *
394 * @ingroup Slider
395 */
396EAPI Eina_Bool elm_slider_indicator_show_get(const Evas_Object *obj);
397
398/**
399 * @}
400 */
diff --git a/libraries/elementary/src/lib/elm_slideshow.c b/libraries/elementary/src/lib/elm_slideshow.c
new file mode 100644
index 0000000..08aa142
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_slideshow.c
@@ -0,0 +1,776 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5typedef struct _Elm_Slideshow_Item Elm_Slideshow_Item;
6
7struct _Elm_Slideshow_Item
8{
9 ELM_WIDGET_ITEM;
10
11 Eina_List *l, *l_built;
12
13 const Elm_Slideshow_Item_Class *itc;
14};
15
16struct _Widget_Data
17{
18 Evas_Object *slideshow;
19
20 // list of Elm_Slideshow_Item*
21 Eina_List *items;
22 Eina_List *items_built;
23
24 Elm_Slideshow_Item *current;
25 Elm_Slideshow_Item *previous;
26
27 Eina_List *transitions;
28 const char *transition;
29
30 int count_item_pre_before;
31 int count_item_pre_after;
32 Ecore_Timer *timer;
33 double timeout;
34 Eina_Bool loop:1;
35
36 struct
37 {
38 const char *current;
39 Eina_List *list; //list of const char *
40 } layout;
41};
42
43static const char *widtype = NULL;
44static void _del_pre_hook(Evas_Object *obj);
45static void _del_hook(Evas_Object *obj);
46static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
47static void _theme_hook(Evas_Object *obj);
48static void _sizing_eval(Evas_Object *obj);
49static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
50static Eina_Bool _timer_cb(void *data);
51static void _on_focus_hook(void *data, Evas_Object *obj);
52static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
53 Evas_Callback_Type type, void *event_info);
54
55static const char SIG_CHANGED[] = "changed";
56static const char SIG_TRANSITION_END[] = "transition,end";
57
58static const Evas_Smart_Cb_Description _signals[] = {
59 {SIG_CHANGED, ""},
60 {SIG_TRANSITION_END, ""},
61 {NULL, NULL}
62};
63
64static Eina_Bool
65_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
66{
67 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
68 Evas_Event_Key_Down *ev = event_info;
69 Widget_Data *wd = elm_widget_data_get(obj);
70 if (!wd) return EINA_FALSE;
71 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
72 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
73 if ((!strcmp(ev->keyname, "Left")) ||
74 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
75 {
76 elm_slideshow_previous(obj);
77 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
78 return EINA_TRUE;
79 }
80 if ((!strcmp(ev->keyname, "Right")) ||
81 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
82 {
83 elm_slideshow_next(obj);
84 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
85 return EINA_TRUE;
86 }
87 if ((!strcmp(ev->keyname, "Return")) ||
88 (!strcmp(ev->keyname, "KP_Enter")) ||
89 (!strcmp(ev->keyname, "space")))
90 {
91 if (wd->timeout)
92 {
93 if (wd->timer)
94 {
95 ecore_timer_del(wd->timer);
96 wd->timer = NULL;
97 }
98 else
99 elm_slideshow_timeout_set(obj, wd->timeout);
100 }
101 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
102 return EINA_TRUE;
103 }
104 return EINA_FALSE;
105}
106
107static void
108_del_pre_hook(Evas_Object *obj)
109{
110 Widget_Data *wd = elm_widget_data_get(obj);
111 if (!wd) return;
112 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
113 _changed_size_hints, obj);
114}
115
116static void
117_del_hook(Evas_Object *obj)
118{
119 const char *layout;
120 Widget_Data *wd = elm_widget_data_get(obj);
121 if (!wd) return;
122 elm_slideshow_clear(obj);
123 elm_widget_stringlist_free(wd->transitions);
124 if (wd->timer) ecore_timer_del(wd->timer);
125 EINA_LIST_FREE(wd->layout.list, layout)
126 eina_stringshare_del(layout);
127 free(wd);
128}
129
130static void
131_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
132{
133 Widget_Data *wd = elm_widget_data_get(obj);
134 if (!wd) return;
135 if (elm_widget_focus_get(obj))
136 {
137 edje_object_signal_emit(wd->slideshow, "elm,action,focus", "elm");
138 evas_object_focus_set(wd->slideshow, EINA_TRUE);
139 }
140 else
141 {
142 edje_object_signal_emit(wd->slideshow, "elm,action,unfocus", "elm");
143 evas_object_focus_set(wd->slideshow, EINA_FALSE);
144 }
145}
146
147static void
148_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
149{
150 Widget_Data *wd = elm_widget_data_get(obj);
151 if (!wd) return;
152 edje_object_mirrored_set(wd->slideshow, rtl);
153}
154
155static void
156_theme_hook(Evas_Object *obj)
157{
158 Widget_Data *wd = elm_widget_data_get(obj);
159 if (!wd) return;
160 _elm_widget_mirrored_reload(obj);
161 _mirrored_set(obj, elm_widget_mirrored_get(obj));
162 _elm_theme_object_set(obj, wd->slideshow, "slideshow", "base", elm_widget_style_get(obj));
163 edje_object_scale_set(wd->slideshow, elm_widget_scale_get(obj) *
164 _elm_config->scale);
165 _sizing_eval(obj);
166}
167
168static void
169_sizing_eval(Evas_Object *obj)
170{
171 Widget_Data *wd = elm_widget_data_get(obj);
172 Evas_Coord minw = -1, minh = -1;
173 if (!wd) return;
174 edje_object_size_min_calc(wd->slideshow, &minw, &minh);
175 evas_object_size_hint_min_set(obj, minw, minh);
176 evas_object_size_hint_max_set(obj, minw, minh);
177}
178
179
180static Elm_Slideshow_Item* _item_prev_get(Elm_Slideshow_Item* item)
181{
182 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
183 Elm_Slideshow_Item* prev = eina_list_data_get(eina_list_prev(item->l));
184 if ((!prev) && (wd->loop))
185 prev = eina_list_data_get(eina_list_last(item->l));
186 return prev;
187}
188
189static Elm_Slideshow_Item* _item_next_get(Elm_Slideshow_Item* item)
190{
191 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
192 Elm_Slideshow_Item* next = eina_list_data_get(eina_list_next(item->l));
193 if ((!next) && (wd->loop))
194 next = eina_list_data_get(wd->items);
195 return next;
196}
197
198static void
199_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
200{
201 _sizing_eval(data);
202}
203
204static void
205_sub_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
206{
207 ;
208}
209
210static void
211_item_realize(Elm_Slideshow_Item *item)
212{
213 Elm_Slideshow_Item *_item_prev, *_item_next;
214 Evas_Object *obj = WIDGET(item);
215 Widget_Data *wd = elm_widget_data_get(obj);
216 int ac, bc, lc, ic = 0;
217
218 if (!wd) return;
219 if ((!VIEW(item)) && (item->itc->func.get))
220 {
221 VIEW(item) = item->itc->func.get(elm_widget_item_data_get(item),
222 obj);
223 evas_object_smart_member_add(VIEW(item), obj);
224 item->l_built = eina_list_append(NULL, item);
225 wd->items_built = eina_list_merge(wd->items_built, item->l_built);
226 //FIXME: item could be showed by obj
227 evas_object_hide(VIEW(item));
228 }
229 else if (item->l_built)
230 wd->items_built = eina_list_demote_list(wd->items_built, item->l_built);
231
232 //pre-create previous and next item
233 ac = wd->count_item_pre_after;
234 _item_next = item;
235 bc = wd->count_item_pre_before;
236 _item_prev = item;
237 lc = eina_list_count(wd->items) - 1;
238 while (lc > 0 && ((ac > 0) || (bc > 0)))
239 {
240 if (lc > 0 && ac > 0)
241 {
242 --ac;
243 --lc;
244 if (_item_next)
245 {
246 _item_next = _item_next_get(_item_next);
247 if ((_item_next)
248 && (!VIEW(_item_next))
249 && (_item_next->itc->func.get))
250 {
251 ic++;
252 VIEW(_item_next) =
253 _item_next->itc->func.get(
254 elm_widget_item_data_get(_item_next), obj);
255 evas_object_smart_member_add(VIEW(_item_next), obj);
256 _item_next->l_built = eina_list_append(NULL, _item_next);
257 wd->items_built = eina_list_merge(wd->items_built,
258 _item_next->l_built);
259 //FIXME: _item_next could be showed by obj later
260 evas_object_hide(VIEW(_item_next));
261 }
262 else if (_item_next && _item_next->l_built)
263 {
264 ic++;
265 wd->items_built =
266 eina_list_demote_list(wd->items_built,
267 _item_next->l_built);
268 }
269 }
270 }
271
272 if (lc > 0 && bc > 0)
273 {
274 --bc;
275 --lc;
276 if (_item_prev)
277 {
278 _item_prev = _item_prev_get(_item_prev);
279 if ((_item_prev)
280 && (!VIEW(_item_prev))
281 && (_item_prev->itc->func.get))
282 {
283 ic++;
284 VIEW(_item_prev) =
285 _item_prev->itc->func.get(
286 elm_widget_item_data_get(_item_prev), obj);
287 evas_object_smart_member_add(VIEW(_item_prev), obj);
288 _item_prev->l_built = eina_list_append(NULL, _item_prev);
289 wd->items_built = eina_list_merge(wd->items_built,
290 _item_prev->l_built);
291 //FIXME: _item_prev could be showed by obj later
292 evas_object_hide(VIEW(_item_prev));
293 }
294 else if (_item_prev && _item_prev->l_built)
295 {
296 ic++;
297 wd->items_built =
298 eina_list_demote_list(wd->items_built,
299 _item_prev->l_built);
300 }
301 }
302 }
303 }
304
305 //delete unused items
306 lc = ic + 1;
307 while ((int)eina_list_count(wd->items_built) > lc)
308 {
309 item = eina_list_data_get(wd->items_built);
310 wd->items_built = eina_list_remove_list(wd->items_built,
311 wd->items_built);
312 if (item->itc->func.del)
313 item->itc->func.del(elm_widget_item_data_get(item), VIEW(item));
314 evas_object_del(VIEW(item));
315 VIEW(item) = NULL;
316 }
317}
318
319static void
320_end(void *data, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
321{
322 Elm_Slideshow_Item *item;
323 Widget_Data *wd = elm_widget_data_get(data);
324 if (!wd) return;
325
326 item = wd->previous;
327 if (item)
328 {
329 edje_object_part_unswallow(wd->slideshow, VIEW(item));
330 evas_object_hide(VIEW(item));
331 wd->previous = NULL;
332 }
333
334 item = wd->current;
335 if ((!item) || (!VIEW(item))) return;
336
337 _item_realize(item);
338 edje_object_part_unswallow(wd->slideshow, VIEW(item));
339
340 edje_object_part_swallow(wd->slideshow, "elm.swallow.1", VIEW(item));
341 edje_object_signal_emit(wd->slideshow, "anim,end", "slideshow");
342 if (emission != NULL)
343 evas_object_smart_callback_call(data, SIG_TRANSITION_END, wd->current);
344}
345
346static Eina_Bool
347_timer_cb(void *data)
348{
349 Evas_Object *obj = data;
350 Widget_Data *wd = elm_widget_data_get(obj);
351 if (!wd) return ECORE_CALLBACK_CANCEL;
352 wd->timer = NULL;
353 elm_slideshow_next(obj);
354 return ECORE_CALLBACK_CANCEL;
355}
356
357static Eina_Bool
358_item_del_pre_hook(Elm_Object_Item *it)
359{
360 Elm_Slideshow_Item *item = (Elm_Slideshow_Item *)it;
361 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
362 if (!wd) return EINA_FALSE;
363
364 if (wd->previous == item) wd->previous = NULL;
365 if (wd->current == item)
366 {
367 Eina_List *l = eina_list_data_find_list(wd->items, item);
368 Eina_List *l2 = eina_list_next(l);
369 wd->current = NULL;
370 if (!l2)
371 {
372 l2 = eina_list_prev(l);
373 if (l2)
374 elm_slideshow_item_show(eina_list_data_get(l2));
375
376 }
377 else
378 elm_slideshow_item_show(eina_list_data_get(l2));
379 }
380
381 wd->items = eina_list_remove_list(wd->items, item->l);
382 wd->items_built = eina_list_remove_list(wd->items_built, item->l_built);
383
384 if ((VIEW(item)) && (item->itc->func.del))
385 item->itc->func.del(elm_widget_item_data_get(item), VIEW(item));
386
387 return EINA_TRUE;
388}
389
390EAPI Evas_Object *
391elm_slideshow_add(Evas_Object *parent)
392{
393 Evas_Object *obj;
394 Evas *e;
395 Widget_Data *wd;
396
397 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
398
399 ELM_SET_WIDTYPE(widtype, "slideshow");
400 elm_widget_type_set(obj, "slideshow");
401 elm_widget_sub_object_add(parent, obj);
402 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
403 elm_widget_data_set(obj, wd);
404 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
405 elm_widget_del_hook_set(obj, _del_hook);
406 elm_widget_theme_hook_set(obj, _theme_hook);
407 elm_widget_can_focus_set(obj, EINA_TRUE);
408 elm_widget_event_hook_set(obj, _event_hook);
409
410 wd->current = NULL;
411 wd->previous = NULL;
412
413 wd->slideshow = edje_object_add(e);
414 _elm_theme_object_set(obj, wd->slideshow, "slideshow", "base", "default");
415 wd->count_item_pre_before = 2;
416 wd->count_item_pre_after = 2;
417 elm_widget_resize_object_set(obj, wd->slideshow);
418
419 wd->transitions = elm_widget_stringlist_get(edje_object_data_get(wd->slideshow, "transitions"));
420 if (eina_list_count(wd->transitions) > 0)
421 wd->transition = eina_stringshare_add(eina_list_data_get(wd->transitions));
422
423 wd->layout.list = elm_widget_stringlist_get(edje_object_data_get(wd->slideshow, "layouts"));
424 if (eina_list_count(wd->layout.list) > 0)
425 wd->layout.current = eina_list_data_get(wd->layout.list);
426
427 edje_object_signal_callback_add(wd->slideshow, "end", "slideshow", _end, obj);
428
429 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
430 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
431
432 evas_object_smart_callbacks_descriptions_set(obj, _signals);
433
434 _mirrored_set(obj, elm_widget_mirrored_get(obj));
435 _sizing_eval(obj);
436 return obj;
437}
438
439EAPI Elm_Object_Item*
440elm_slideshow_item_add(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data)
441{
442 Elm_Slideshow_Item *item;
443 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
444 Widget_Data *wd = elm_widget_data_get(obj);
445
446 if (!wd) return NULL;
447 item = elm_widget_item_new(obj, Elm_Slideshow_Item);
448 if (!item) return NULL;
449 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
450 item->itc = itc;
451 item->l = eina_list_append(item->l, item);
452 elm_widget_item_data_set(item, data);
453
454 wd->items = eina_list_merge(wd->items, item->l);
455
456 if (!wd->current) elm_slideshow_item_show((Elm_Object_Item *)item);
457
458 return (Elm_Object_Item *)item;
459}
460
461EAPI Elm_Object_Item*
462elm_slideshow_item_sorted_insert(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data, Eina_Compare_Cb func)
463{
464 Elm_Slideshow_Item *item;
465 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
466 Widget_Data *wd = elm_widget_data_get(obj);
467 if (!wd) return NULL;
468
469 item = elm_widget_item_new(obj, Elm_Slideshow_Item);
470 if (!item) return NULL;
471 elm_widget_item_del_pre_hook_set(item, _item_del_pre_hook);
472 item->itc = itc;
473 item->l = eina_list_append(item->l, item);
474 elm_widget_item_data_set(item, data);
475
476 wd->items = eina_list_sorted_merge(wd->items, item->l, func);
477
478 if (!wd->current) elm_slideshow_item_show((Elm_Object_Item *)item);
479
480 return (Elm_Object_Item *)item;
481}
482
483EAPI void
484elm_slideshow_item_show(Elm_Object_Item *it)
485{
486 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
487
488 char buf[1024];
489 Elm_Slideshow_Item *item, *next = NULL;
490 Widget_Data *wd;
491 item = (Elm_Slideshow_Item *)it;
492 wd = elm_widget_data_get(WIDGET(item));
493 if (!wd) return;
494 if (item == wd->current) return;
495
496 next = item;
497 _end(WIDGET(item), WIDGET(item), NULL, NULL);
498
499 if (wd->timer) ecore_timer_del(wd->timer);
500 wd->timer = NULL;
501 if (wd->timeout > 0.0)
502 wd->timer = ecore_timer_add(wd->timeout, _timer_cb, WIDGET(item));
503 _item_realize(next);
504 edje_object_part_swallow(wd->slideshow, "elm.swallow.2", VIEW(next));
505 snprintf(buf, sizeof(buf), "%s,next", wd->transition);
506 edje_object_signal_emit(wd->slideshow, buf, "slideshow");
507 wd->previous = wd->current;
508 wd->current = next;
509 evas_object_smart_callback_call(WIDGET(item), SIG_CHANGED, wd->current);
510}
511
512EAPI void
513elm_slideshow_next(Evas_Object *obj)
514{
515 char buf[1024];
516 Elm_Slideshow_Item *next = NULL;
517 ELM_CHECK_WIDTYPE(obj, widtype);
518 Widget_Data *wd = elm_widget_data_get(obj);
519
520 if (!wd) return;
521
522 if (wd->current)
523 next = _item_next_get(wd->current);
524
525 if ((!next) || (next == wd->current)) return;
526
527 _end(obj, obj, NULL, NULL);
528
529 if (wd->timer) ecore_timer_del(wd->timer);
530 wd->timer = NULL;
531 if (wd->timeout > 0.0)
532 wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
533
534 _item_realize(next);
535
536 edje_object_part_swallow(wd->slideshow, "elm.swallow.2", VIEW(next));
537
538 snprintf(buf, sizeof(buf), "%s,next", wd->transition);
539 edje_object_signal_emit(wd->slideshow, buf, "slideshow");
540
541 wd->previous = wd->current;
542 wd->current = next;
543 evas_object_smart_callback_call(obj, SIG_CHANGED, wd->current);
544}
545
546EAPI void
547elm_slideshow_previous(Evas_Object *obj)
548{
549 char buf[1024];
550 Elm_Slideshow_Item *prev = NULL;
551 ELM_CHECK_WIDTYPE(obj, widtype);
552 Widget_Data *wd = elm_widget_data_get(obj);
553
554 if (!wd) return;
555
556 if (wd->current)
557 prev = _item_prev_get(wd->current);
558
559 if ((!prev) || (prev == wd->current)) return;
560
561 _end(obj, obj, NULL, NULL);
562
563 if (wd->timer) ecore_timer_del(wd->timer);
564 wd->timer = NULL;
565 if (wd->timeout > 0.0)
566 wd->timer = ecore_timer_add(wd->timeout, _timer_cb, obj);
567
568 _item_realize(prev);
569
570 edje_object_part_swallow(wd->slideshow, "elm.swallow.2", VIEW(prev));
571
572 snprintf(buf, 1024, "%s,previous", wd->transition);
573 edje_object_signal_emit(wd->slideshow, buf, "slideshow");
574
575 wd->previous = wd->current;
576 wd->current = prev;
577 evas_object_smart_callback_call(obj, SIG_CHANGED, wd->current);
578}
579
580EAPI const Eina_List *
581elm_slideshow_transitions_get(const Evas_Object *obj)
582{
583 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
584 Widget_Data *wd = elm_widget_data_get(obj);
585 if (!wd) return NULL;
586 return wd->transitions;
587}
588
589EAPI const Eina_List *
590elm_slideshow_layouts_get(const Evas_Object *obj)
591{
592 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
593 Widget_Data *wd = elm_widget_data_get(obj);
594 if (!wd) return NULL;
595 return wd->layout.list;
596}
597
598EAPI void
599elm_slideshow_transition_set(Evas_Object *obj, const char *transition)
600{
601 ELM_CHECK_WIDTYPE(obj, widtype);
602 Widget_Data *wd = elm_widget_data_get(obj);
603 if (!wd) return;
604 eina_stringshare_replace(&wd->transition, transition);
605}
606
607EAPI const char *
608elm_slideshow_transition_get(const Evas_Object *obj)
609{
610 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
611 Widget_Data *wd = elm_widget_data_get(obj);
612 if (!wd) return NULL;
613 return wd->transition;
614}
615
616EAPI void
617elm_slideshow_timeout_set(Evas_Object *obj, double timeout)
618{
619 ELM_CHECK_WIDTYPE(obj, widtype);
620 Widget_Data *wd = elm_widget_data_get(obj);
621 if (!wd) return;
622 wd->timeout = timeout;
623 if (wd->timer) ecore_timer_del(wd->timer);
624 wd->timer = NULL;
625 if (timeout > 0.0)
626 wd->timer = ecore_timer_add(timeout, _timer_cb, obj);
627}
628
629EAPI double
630elm_slideshow_timeout_get(const Evas_Object *obj)
631{
632 ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
633 Widget_Data *wd = elm_widget_data_get(obj);
634 if (!wd) return -1.0;
635 return wd->timeout;
636}
637
638EAPI void
639elm_slideshow_loop_set(Evas_Object *obj, Eina_Bool loop)
640{
641 ELM_CHECK_WIDTYPE(obj, widtype);
642 Widget_Data *wd = elm_widget_data_get(obj);
643 if (!wd) return;
644 wd->loop = loop;
645}
646
647EAPI const char *
648elm_slideshow_layout_get(const Evas_Object *obj)
649{
650 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
651 Widget_Data *wd = elm_widget_data_get(obj);
652 if (!wd) return EINA_FALSE;
653 return wd->layout.current;
654}
655
656EAPI void
657elm_slideshow_layout_set(Evas_Object *obj, const char *layout)
658{
659 char buf[PATH_MAX];
660 ELM_CHECK_WIDTYPE(obj, widtype);
661 Widget_Data *wd = elm_widget_data_get(obj);
662 if (!wd) return;
663
664 wd->layout.current = layout;
665 snprintf(buf, sizeof(buf), "layout,%s", layout);
666 edje_object_signal_emit(wd->slideshow, buf, "slideshow");
667}
668
669EAPI Eina_Bool
670elm_slideshow_loop_get(const Evas_Object *obj)
671{
672 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
673 Widget_Data *wd = elm_widget_data_get(obj);
674 if (!wd) return EINA_FALSE;
675 return wd->loop;
676}
677
678EAPI void
679elm_slideshow_clear(Evas_Object *obj)
680{
681 Elm_Slideshow_Item *item;
682 ELM_CHECK_WIDTYPE(obj, widtype);
683 Widget_Data *wd = elm_widget_data_get(obj);
684 if (!wd) return;
685 wd->previous = NULL;
686 wd->current = NULL;
687 EINA_LIST_FREE(wd->items_built, item)
688 {
689 if (item->itc->func.del)
690 item->itc->func.del(elm_widget_item_data_get(item), VIEW(item));
691 }
692
693 EINA_LIST_FREE(wd->items, item)
694 elm_widget_item_free(item);
695}
696
697EAPI const Eina_List *
698elm_slideshow_items_get(const Evas_Object *obj)
699{
700 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
701 Widget_Data *wd = elm_widget_data_get(obj);
702 if (!wd) return NULL;
703 return wd->items;
704}
705
706EAPI Elm_Object_Item *
707elm_slideshow_item_current_get(const Evas_Object *obj)
708{
709 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
710 Widget_Data *wd = elm_widget_data_get(obj);
711 if (!wd) return NULL;
712 return (Elm_Object_Item *) wd->current;
713}
714
715EAPI Evas_Object *
716elm_slideshow_item_object_get(const Elm_Object_Item * it)
717{
718 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
719 return VIEW(it);
720}
721
722EAPI int
723elm_slideshow_cache_before_get(const Evas_Object *obj)
724{
725 ELM_CHECK_WIDTYPE(obj, widtype) -1;
726 Widget_Data *wd = elm_widget_data_get(obj);
727 if (!wd) return -1;
728 return wd->count_item_pre_before;
729}
730
731EAPI void
732elm_slideshow_cache_before_set(Evas_Object *obj, int count)
733{
734 ELM_CHECK_WIDTYPE(obj, widtype);
735 Widget_Data *wd = elm_widget_data_get(obj);
736 if (!wd) return;
737 if (count < 0) count = 0;
738 wd->count_item_pre_before = count;
739}
740
741EAPI int
742elm_slideshow_cache_after_get(const Evas_Object *obj)
743{
744 ELM_CHECK_WIDTYPE(obj, widtype) -1;
745 Widget_Data *wd = elm_widget_data_get(obj);
746 if (!wd) return -1;
747 return wd->count_item_pre_after;
748}
749
750EAPI void
751elm_slideshow_cache_after_set(Evas_Object *obj, int count)
752{
753 ELM_CHECK_WIDTYPE(obj, widtype);
754 Widget_Data *wd = elm_widget_data_get(obj);
755 if (!wd) return;
756 if (count < 0) count = 0;
757 wd->count_item_pre_after = count;
758}
759
760EAPI Elm_Object_Item *
761elm_slideshow_item_nth_get(const Evas_Object *obj, unsigned int nth)
762{
763 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
764 Widget_Data *wd = elm_widget_data_get(obj);
765 if (!wd) return NULL;
766 return eina_list_nth(wd->items, nth);
767}
768
769EAPI unsigned int
770elm_slideshow_count_get(const Evas_Object *obj)
771{
772 ELM_CHECK_WIDTYPE(obj, widtype) 0;
773 Widget_Data *wd = elm_widget_data_get(obj);
774 if (!wd) return 0;
775 return eina_list_count(wd->items);
776}
diff --git a/libraries/elementary/src/lib/elm_slideshow.h b/libraries/elementary/src/lib/elm_slideshow.h
new file mode 100644
index 0000000..546b002
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_slideshow.h
@@ -0,0 +1,546 @@
1/**
2 * @defgroup Slideshow Slideshow
3 * @ingroup Elementary
4 *
5 * @image html img/widget/slideshow/preview-00.png
6 * @image latex img/widget/slideshow/preview-00.eps
7 *
8 * This widget, as the name indicates, is a pre-made image
9 * slideshow panel, with API functions acting on (child) image
10 * items presentation. Between those actions, are:
11 * - advance to next/previous image
12 * - select the style of image transition animation
13 * - set the exhibition time for each image
14 * - start/stop the slideshow
15 *
16 * The transition animations are defined in the widget's theme,
17 * consequently new animations can be added without having to
18 * update the widget's code.
19 *
20 * @section Slideshow_Items Slideshow items
21 *
22 * For slideshow items, just like for @ref Genlist "genlist" ones,
23 * the user defines a @b classes, specifying functions that will be
24 * called on the item's creation and deletion times.
25 *
26 * The #Elm_Slideshow_Item_Class structure contains the following
27 * members:
28 *
29 * - @c func.get - When an item is displayed, this function is
30 * called, and it's where one should create the item object, de
31 * facto. For example, the object can be a pure Evas image object
32 * or an Elementary @ref Photocam "photocam" widget. See
33 * #SlideshowItemGetFunc.
34 * - @c func.del - When an item is no more displayed, this function
35 * is called, where the user must delete any data associated to
36 * the item. See #SlideshowItemDelFunc.
37 *
38 * @section Slideshow_Caching Slideshow caching
39 *
40 * The slideshow provides facilities to have items adjacent to the
41 * one being displayed <b>already "realized"</b> (i.e. loaded) for
42 * you, so that the system does not have to decode image data
43 * anymore at the time it has to actually switch images on its
44 * viewport. The user is able to set the numbers of items to be
45 * cached @b before and @b after the current item, in the widget's
46 * item list.
47 *
48 * Smart events one can add callbacks for are:
49 *
50 * - @c "changed" - when the slideshow switches its view to a new
51 * item. event_info parameter in callback contains the current visible item
52 * - @c "transition,end" - when a slide transition ends. event_info parameter
53 * in callback contains the current visible item
54 *
55 * List of examples for the slideshow widget:
56 * @li @ref slideshow_example
57 */
58
59/**
60 * @addtogroup Slideshow
61 * @{
62 */
63
64typedef struct _Elm_Slideshow_Item_Class Elm_Slideshow_Item_Class; /**< Slideshow item class definition struct */
65typedef struct _Elm_Slideshow_Item_Class_Func Elm_Slideshow_Item_Class_Func; /**< Class functions for slideshow item classes. */
66typedef Evas_Object *(*SlideshowItemGetFunc)(void *data, Evas_Object *obj); /**< Image fetching class function for slideshow item classes. */
67typedef void (*SlideshowItemDelFunc)(void *data, Evas_Object *obj); /**< Deletion class function for slideshow item classes. */
68
69/**
70 * @struct _Elm_Slideshow_Item_Class
71 *
72 * Slideshow item class definition. See @ref Slideshow_Items for
73 * field details.
74 */
75struct _Elm_Slideshow_Item_Class
76{
77 struct _Elm_Slideshow_Item_Class_Func
78 {
79 SlideshowItemGetFunc get;
80 SlideshowItemDelFunc del;
81 } func;
82}; /**< #Elm_Slideshow_Item_Class member definitions */
83
84/**
85 * Add a new slideshow widget to the given parent Elementary
86 * (container) object
87 *
88 * @param parent The parent object
89 * @return A new slideshow widget handle or @c NULL, on errors
90 *
91 * This function inserts a new slideshow widget on the canvas.
92 *
93 * @ingroup Slideshow
94 */
95EAPI Evas_Object *elm_slideshow_add(Evas_Object *parent);
96
97/**
98 * Add (append) a new item in a given slideshow widget.
99 *
100 * @param obj The slideshow object
101 * @param itc The item class for the item
102 * @param data The item's data
103 * @return A handle to the item added or @c NULL, on errors
104 *
105 * Add a new item to @p obj's internal list of items, appending it.
106 * The item's class must contain the function really fetching the
107 * image object to show for this item, which could be an Evas image
108 * object or an Elementary photo, for example. The @p data
109 * parameter is going to be passed to both class functions of the
110 * item.
111 *
112 * @see #Elm_Slideshow_Item_Class
113 * @see elm_slideshow_item_sorted_insert()
114 * @see elm_object_item_data_set()
115 *
116 * @ingroup Slideshow
117 */
118EAPI Elm_Object_Item *elm_slideshow_item_add(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data);
119
120/**
121 * Insert a new item into the given slideshow widget, using the @p func
122 * function to sort items (by item handles).
123 *
124 * @param obj The slideshow object
125 * @param itc The item class for the item
126 * @param data The item's data
127 * @param func The comparing function to be used to sort slideshow
128 * items <b>by #Elm_Slideshow_Item item handles</b>
129 * @return Returns The slideshow item handle, on success, or
130 * @c NULL, on errors
131 *
132 * Add a new item to @p obj's internal list of items, in a position
133 * determined by the @p func comparing function. The item's class
134 * must contain the function really fetching the image object to
135 * show for this item, which could be an Evas image object or an
136 * Elementary photo, for example. The @p data parameter is going to
137 * be passed to both class functions of the item.
138 *
139 * @see #Elm_Slideshow_Item_Class
140 * @see elm_slideshow_item_add()
141 *
142 * @ingroup Slideshow
143 */
144EAPI Elm_Object_Item *elm_slideshow_item_sorted_insert(Evas_Object *obj, const Elm_Slideshow_Item_Class *itc, const void *data, Eina_Compare_Cb func);
145
146/**
147 * Display a given slideshow widget's item, programmatically.
148 *
149 * @param it The item to display on @p obj's viewport
150 *
151 * The change between the current item and @p item will use the
152 * transition @p obj is set to use (@see
153 * elm_slideshow_transition_set()).
154 *
155 * @ingroup Slideshow
156 */
157EAPI void elm_slideshow_item_show(Elm_Object_Item *it);
158
159/**
160 * Slide to the @b next item, in a given slideshow widget
161 *
162 * @param obj The slideshow object
163 *
164 * The sliding animation @p obj is set to use will be the
165 * transition effect used, after this call is issued.
166 *
167 * @note If the end of the slideshow's internal list of items is
168 * reached, it'll wrap around to the list's beginning, again.
169 *
170 * @ingroup Slideshow
171 */
172EAPI void elm_slideshow_next(Evas_Object *obj);
173
174/**
175 * Slide to the @b previous item, in a given slideshow widget
176 *
177 * @param obj The slideshow object
178 *
179 * The sliding animation @p obj is set to use will be the
180 * transition effect used, after this call is issued.
181 *
182 * @note If the beginning of the slideshow's internal list of items
183 * is reached, it'll wrap around to the list's end, again.
184 *
185 * @ingroup Slideshow
186 */
187EAPI void elm_slideshow_previous(Evas_Object *obj);
188
189/**
190 * Returns the list of sliding transition/effect names available, for a
191 * given slideshow widget.
192 *
193 * @param obj The slideshow object
194 * @return The list of transitions (list of @b stringshared strings
195 * as data)
196 *
197 * The transitions, which come from @p obj's theme, must be an EDC
198 * data item named @c "transitions" on the theme file, with (prefix)
199 * names of EDC programs actually implementing them.
200 *
201 * The available transitions for slideshows on the default theme are:
202 * - @c "fade" - the current item fades out, while the new one
203 * fades in to the slideshow's viewport.
204 * - @c "black_fade" - the current item fades to black, and just
205 * then, the new item will fade in.
206 * - @c "horizontal" - the current item slides horizontally, until
207 * it gets out of the slideshow's viewport, while the new item
208 * comes from the left to take its place.
209 * - @c "vertical" - the current item slides vertically, until it
210 * gets out of the slideshow's viewport, while the new item comes
211 * from the bottom to take its place.
212 * - @c "square" - the new item starts to appear from the middle of
213 * the current one, but with a tiny size, growing until its
214 * target (full) size and covering the old one.
215 *
216 * @warning The stringshared strings get no new references
217 * exclusive to the user grabbing the list, here, so if you'd like
218 * to use them out of this call's context, you'd better @c
219 * eina_stringshare_ref() them. Also the list is an internal list and
220 * so is only valid for as long as the slideshow object is valid and
221 * has not internally changed its list for some reason, so make a
222 * copy if you need it around.
223 *
224 * @see elm_slideshow_transition_set()
225 *
226 * @ingroup Slideshow
227 */
228EAPI const Eina_List *elm_slideshow_transitions_get(const Evas_Object *obj);
229
230/**
231 * Set the current slide transition/effect in use for a given
232 * slideshow widget
233 *
234 * @param obj The slideshow object
235 * @param transition The new transition's name string
236 *
237 * If @p transition is implemented in @p obj's theme (i.e., is
238 * contained in the list returned by
239 * elm_slideshow_transitions_get()), this new sliding effect will
240 * be used on the widget.
241 *
242 * @see elm_slideshow_transitions_get() for more details
243 *
244 * @ingroup Slideshow
245 */
246EAPI void elm_slideshow_transition_set(Evas_Object *obj, const char *transition);
247
248/**
249 * Get the current slide transition/effect in use for a given
250 * slideshow widget
251 *
252 * @param obj The slideshow object
253 * @return The current transition's name
254 *
255 * @see elm_slideshow_transition_set() for more details
256 *
257 * @ingroup Slideshow
258 */
259EAPI const char *elm_slideshow_transition_get(const Evas_Object *obj);
260
261/**
262 * Set the interval between each image transition on a given
263 * slideshow widget, <b>and start the slideshow, itself</b>
264 *
265 * @param obj The slideshow object
266 * @param timeout The new displaying timeout for images
267 *
268 * After this call, the slideshow widget will start cycling its
269 * view, sequentially and automatically, with the images of the
270 * items it has. The time between each new image displayed is going
271 * to be @p timeout, in @b seconds. If a different timeout was set
272 * previously and an slideshow was in progress, it will continue
273 * with the new time between transitions, after this call.
274 *
275 * @note A value less than or equal to 0 on @p timeout will disable
276 * the widget's internal timer, thus halting any slideshow which
277 * could be happening on @p obj.
278 *
279 * @see elm_slideshow_timeout_get()
280 *
281 * @ingroup Slideshow
282 */
283EAPI void elm_slideshow_timeout_set(Evas_Object *obj, double timeout);
284
285/**
286 * Get the interval set for image transitions on a given slideshow
287 * widget.
288 *
289 * @param obj The slideshow object
290 * @return Returns the timeout set on it
291 *
292 * @see elm_slideshow_timeout_set() for more details
293 *
294 * @ingroup Slideshow
295 */
296EAPI double elm_slideshow_timeout_get(const Evas_Object *obj);
297
298/**
299 * Set if, after a slideshow is started, for a given slideshow
300 * widget, its items should be displayed cyclically or not.
301 *
302 * @param obj The slideshow object
303 * @param loop Use @c EINA_TRUE to make it cycle through items or
304 * @c EINA_FALSE for it to stop at the end of @p obj's internal
305 * list of items
306 *
307 * @note elm_slideshow_next() and elm_slideshow_previous() will @b
308 * ignore what is set by this functions, i.e., they'll @b always
309 * cycle through items. This affects only the "automatic"
310 * slideshow, as set by elm_slideshow_timeout_set().
311 *
312 * @see elm_slideshow_loop_get()
313 *
314 * @ingroup Slideshow
315 */
316EAPI void elm_slideshow_loop_set(Evas_Object *obj, Eina_Bool loop);
317
318/**
319 * Get if, after a slideshow is started, for a given slideshow
320 * widget, its items are to be displayed cyclically or not.
321 *
322 * @param obj The slideshow object
323 * @return @c EINA_TRUE, if the items in @p obj will be cycled
324 * through or @c EINA_FALSE, otherwise
325 *
326 * @see elm_slideshow_loop_set() for more details
327 *
328 * @ingroup Slideshow
329 */
330EAPI Eina_Bool elm_slideshow_loop_get(const Evas_Object *obj);
331
332/**
333 * Remove all items from a given slideshow widget
334 *
335 * @param obj The slideshow object
336 *
337 * This removes (and deletes) all items in @p obj, leaving it
338 * empty.
339 *
340 * @see elm_object_item_del(), to remove just one item.
341 *
342 * @ingroup Slideshow
343 */
344EAPI void elm_slideshow_clear(Evas_Object *obj);
345
346/**
347 * Get the internal list of items in a given slideshow widget.
348 *
349 * @param obj The slideshow object
350 * @return The list of items (#Elm_Object_Item as data) or
351 * @c NULL on errors.
352 *
353 * This list is @b not to be modified in any way and must not be
354 * freed. Use the list members with functions like
355 * elm_object_item_del(), elm_object_item_data_get().
356 *
357 * @warning This list is only valid until @p obj object's internal
358 * items list is changed. It should be fetched again with another
359 * call to this function when changes happen.
360 *
361 * @ingroup Slideshow
362 */
363EAPI const Eina_List *elm_slideshow_items_get(const Evas_Object *obj);
364
365/**
366 * Returns the currently displayed item, in a given slideshow widget
367 *
368 * @param obj The slideshow object
369 * @return A handle to the item being displayed in @p obj or
370 * @c NULL, if none is (and on errors)
371 *
372 * @ingroup Slideshow
373 */
374EAPI Elm_Object_Item *elm_slideshow_item_current_get(const Evas_Object *obj);
375
376/**
377 * Get the real Evas object created to implement the view of a
378 * given slideshow item
379 *
380 * @param it The slideshow item.
381 * @return the Evas object implementing this item's view.
382 *
383 * This returns the actual Evas object used to implement the
384 * specified slideshow item's view. This may be @c NULL, as it may
385 * not have been created or may have been deleted, at any time, by
386 * the slideshow. <b>Do not modify this object</b> (move, resize,
387 * show, hide, etc.), as the slideshow is controlling it. This
388 * function is for querying, emitting custom signals or hooking
389 * lower level callbacks for events on that object. Do not delete
390 * this object under any circumstances.
391 *
392 * @see elm_object_item_data_get()
393 *
394 * @ingroup Slideshow
395 */
396EAPI Evas_Object *elm_slideshow_item_object_get(const Elm_Object_Item *it);
397
398/**
399 * Get the the item, in a given slideshow widget, placed at
400 * position @p nth, in its internal items list
401 *
402 * @param obj The slideshow object
403 * @param nth The number of the item to grab a handle to (0 being
404 * the first)
405 * @return The item stored in @p obj at position @p nth or @c NULL,
406 * if there's no item with that index (and on errors)
407 *
408 * @ingroup Slideshow
409 */
410EAPI Elm_Object_Item *elm_slideshow_item_nth_get(const Evas_Object *obj, unsigned int nth);
411
412/**
413 * Set the current slide layout in use for a given slideshow widget
414 *
415 * @param obj The slideshow object
416 * @param layout The new layout's name string
417 *
418 * If @p layout is implemented in @p obj's theme (i.e., is contained
419 * in the list returned by elm_slideshow_layouts_get()), this new
420 * images layout will be used on the widget.
421 *
422 * @see elm_slideshow_layouts_get() for more details
423 *
424 * @ingroup Slideshow
425 */
426EAPI void elm_slideshow_layout_set(Evas_Object *obj, const char *layout);
427
428/**
429 * Get the current slide layout in use for a given slideshow widget
430 *
431 * @param obj The slideshow object
432 * @return The current layout's name
433 *
434 * @see elm_slideshow_layout_set() for more details
435 *
436 * @ingroup Slideshow
437 */
438EAPI const char *elm_slideshow_layout_get(const Evas_Object *obj);
439
440/**
441 * Returns the list of @b layout names available, for a given
442 * slideshow widget.
443 *
444 * @param obj The slideshow object
445 * @return The list of layouts (list of @b stringshared strings
446 * as data)
447 *
448 * Slideshow layouts will change how the widget is to dispose each
449 * image item in its viewport, with regard to cropping, scaling,
450 * etc.
451 *
452 * The layouts, which come from @p obj's theme, must be an EDC
453 * data item name @c "layouts" on the theme file, with (prefix)
454 * names of EDC programs actually implementing them.
455 *
456 * The available layouts for slideshows on the default theme are:
457 * - @c "fullscreen" - item images with original aspect, scaled to
458 * touch top and down slideshow borders or, if the image's height
459 * is not enough, left and right slideshow borders.
460 * - @c "not_fullscreen" - the same behavior as the @c "fullscreen"
461 * one, but always leaving 10% of the slideshow's dimensions of
462 * distance between the item image's borders and the slideshow
463 * borders, for each axis.
464 *
465 * @warning The stringshared strings get no new references
466 * exclusive to the user grabbing the list, here, so if you'd like
467 * to use them out of this call's context, you'd better @c
468 * eina_stringshare_ref() them.
469 *
470 * @see elm_slideshow_layout_set()
471 *
472 * @ingroup Slideshow
473 */
474EAPI const Eina_List *elm_slideshow_layouts_get(const Evas_Object *obj);
475
476/**
477 * Set the number of items to cache, on a given slideshow widget,
478 * <b>before the current item</b>
479 *
480 * @param obj The slideshow object
481 * @param count Number of items to cache before the current one
482 *
483 * The default value for this property is @c 2. See
484 * @ref Slideshow_Caching "slideshow caching" for more details.
485 *
486 * @see elm_slideshow_cache_before_get()
487 *
488 * @ingroup Slideshow
489 */
490EAPI void elm_slideshow_cache_before_set(Evas_Object *obj, int count);
491
492/**
493 * Retrieve the number of items to cache, on a given slideshow widget,
494 * <b>before the current item</b>
495 *
496 * @param obj The slideshow object
497 * @return The number of items set to be cached before the current one
498 *
499 * @see elm_slideshow_cache_before_set() for more details
500 *
501 * @ingroup Slideshow
502 */
503EAPI int elm_slideshow_cache_before_get(const Evas_Object *obj);
504
505/**
506 * Set the number of items to cache, on a given slideshow widget,
507 * <b>after the current item</b>
508 *
509 * @param obj The slideshow object
510 * @param count Number of items to cache after the current one
511 *
512 * The default value for this property is @c 2. See
513 * @ref Slideshow_Caching "slideshow caching" for more details.
514 *
515 * @see elm_slideshow_cache_after_get()
516 *
517 * @ingroup Slideshow
518 */
519EAPI void elm_slideshow_cache_after_set(Evas_Object *obj, int count);
520
521/**
522 * Retrieve the number of items to cache, on a given slideshow widget,
523 * <b>after the current item</b>
524 *
525 * @param obj The slideshow object
526 * @return The number of items set to be cached after the current one
527 *
528 * @see elm_slideshow_cache_after_set() for more details
529 *
530 * @ingroup Slideshow
531 */
532EAPI int elm_slideshow_cache_after_get(const Evas_Object *obj);
533
534/**
535 * Get the number of items stored in a given slideshow widget
536 *
537 * @param obj The slideshow object
538 * @return The number of items on @p obj, at the moment of this call
539 *
540 * @ingroup Slideshow
541 */
542EAPI unsigned int elm_slideshow_count_get(const Evas_Object *obj);
543
544/**
545 * @}
546 */
diff --git a/libraries/elementary/src/lib/elm_spinner.c b/libraries/elementary/src/lib/elm_spinner.c
new file mode 100644
index 0000000..9ff7de1
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_spinner.c
@@ -0,0 +1,830 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include <ctype.h>
4
5typedef struct _Widget_Data Widget_Data;
6typedef struct _Elm_Spinner_Special_Value Elm_Spinner_Special_Value;
7
8struct _Widget_Data
9{
10 Evas_Object *spinner, *ent;
11 const char *label;
12 double val, val_min, val_max, orig_val, step, base;
13 double drag_start_pos, spin_speed, interval, first_interval;
14 int round;
15 Ecore_Timer *delay, *spin;
16 Eina_List *special_values;
17 Eina_Bool wrap : 1;
18 Eina_Bool entry_visible : 1;
19 Eina_Bool dragging : 1;
20 Eina_Bool editable : 1;
21};
22
23struct _Elm_Spinner_Special_Value
24{
25 double value;
26 const char *label;
27};
28
29static const char *widtype = NULL;
30static void _del_hook(Evas_Object *obj);
31static void _disable_hook(Evas_Object *obj);
32static void _write_label(Evas_Object *obj);
33static void _sizing_eval(Evas_Object *obj);
34//static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
35static Eina_Bool _value_set(Evas_Object *obj, double delta);
36static void _on_focus_hook(void *data, Evas_Object *obj);
37static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
38 Evas_Callback_Type type, void *event_info);
39
40static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
41
42static const char SIG_CHANGED[] = "changed";
43static const char SIG_DELAY_CHANGED[] = "delay,changed";
44
45static const Evas_Smart_Cb_Description _signals[] = {
46 {SIG_CHANGED, ""},
47 {SIG_DELAY_CHANGED, ""},
48 {NULL, NULL}
49};
50
51static void
52_del_hook(Evas_Object *obj)
53{
54 Elm_Spinner_Special_Value *sv;
55 Widget_Data *wd = elm_widget_data_get(obj);
56 if (!wd) return;
57 if (wd->label) eina_stringshare_del(wd->label);
58 if (wd->delay) ecore_timer_del(wd->delay);
59 if (wd->spin) ecore_timer_del(wd->spin);
60 if (wd->special_values)
61 {
62 EINA_LIST_FREE(wd->special_values, sv)
63 {
64 eina_stringshare_del(sv->label);
65 free(sv);
66 }
67 }
68 free(wd);
69}
70
71static void
72_disable_hook(Evas_Object *obj)
73{
74 Widget_Data *wd = elm_widget_data_get(obj);
75 if (!wd) return;
76 if (elm_widget_disabled_get(obj))
77 edje_object_signal_emit(wd->spinner, "elm,state,disabled", "elm");
78 else
79 edje_object_signal_emit(wd->spinner, "elm,state,enabled", "elm");
80}
81
82static void
83_signal_emit_hook(Evas_Object *obj, const char *emission, const char *source)
84{
85 Widget_Data *wd = elm_widget_data_get(obj);
86 if (!wd) return;
87 edje_object_signal_emit(wd->spinner, emission, source);
88}
89
90static void
91_signal_callback_add_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
92{
93 Widget_Data *wd = elm_widget_data_get(obj);
94 if (!wd) return;
95 edje_object_signal_callback_add(wd->spinner, emission,
96 source, func_cb, data);
97}
98
99static void
100_signal_callback_del_hook(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data)
101{
102 Widget_Data *wd = elm_widget_data_get(obj);
103 edje_object_signal_callback_del_full(wd->spinner, emission, source,
104 func_cb, data);
105}
106
107static void
108_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
109{
110 Widget_Data *wd = elm_widget_data_get(obj);
111 if (!wd) return;
112 edje_object_mirrored_set(wd->spinner, rtl);
113}
114
115static void
116_theme_hook(Evas_Object *obj)
117{
118 Widget_Data *wd = elm_widget_data_get(obj);
119 if (!wd) return;
120 _elm_widget_mirrored_reload(obj);
121 _mirrored_set(obj, elm_widget_mirrored_get(obj));
122 _elm_theme_object_set(obj, wd->spinner, "spinner", "base", elm_widget_style_get(obj));
123 edje_object_part_swallow(wd->spinner, "elm.swallow.entry", wd->ent);
124 _write_label(obj);
125 if (elm_widget_focus_get(obj))
126 edje_object_signal_emit(wd->spinner, "elm,action,focus", "elm");
127 else
128 edje_object_signal_emit(wd->spinner, "elm,action,unfocus", "elm");
129 if (elm_widget_disabled_get(obj))
130 edje_object_signal_emit(wd->spinner, "elm,state,disabled", "elm");
131 edje_object_message_signal_process(wd->spinner);
132 edje_object_scale_set(wd->spinner, elm_widget_scale_get(obj) * _elm_config->scale);
133 _sizing_eval(obj);
134}
135
136static void
137_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
138{
139 Widget_Data *wd = elm_widget_data_get(obj);
140 if (!wd) return;
141 if (elm_widget_focus_get(obj))
142 {
143 edje_object_signal_emit(wd->spinner, "elm,action,focus", "elm");
144 evas_object_focus_set(wd->spinner, EINA_TRUE);
145 }
146 else
147 {
148 edje_object_signal_emit(wd->spinner, "elm,action,unfocus", "elm");
149 evas_object_focus_set(wd->spinner, EINA_FALSE);
150 }
151}
152
153static Eina_Bool
154_delay_change(void *data)
155{
156 Widget_Data *wd = elm_widget_data_get(data);
157 if (!wd) return ECORE_CALLBACK_CANCEL;
158 wd->delay = NULL;
159 evas_object_smart_callback_call(data, SIG_DELAY_CHANGED, NULL);
160 return ECORE_CALLBACK_CANCEL;
161}
162
163static void
164_entry_show(Widget_Data *wd)
165{
166 char buf[32], fmt[32] = "%0.f";
167
168 /* try to construct just the format from given label
169 * completely ignoring pre/post words
170 */
171 if (wd->label)
172 {
173 const char *start = strchr(wd->label, '%');
174 while (start)
175 {
176 /* handle %% */
177 if (start[1] != '%')
178 break;
179 else
180 start = strchr(start + 2, '%');
181 }
182
183 if (start)
184 {
185 const char *itr, *end = NULL;
186 for (itr = start + 1; *itr != '\0'; itr++)
187 {
188 /* allowing '%d' is quite dangerous, remove it? */
189 if ((*itr == 'd') || (*itr == 'f'))
190 {
191 end = itr + 1;
192 break;
193 }
194 }
195
196 if ((end) && ((size_t)(end - start + 1) < sizeof(fmt)))
197 {
198 memcpy(fmt, start, end - start);
199 fmt[end - start] = '\0';
200 }
201 }
202 }
203 snprintf(buf, sizeof(buf), fmt, wd->val);
204 elm_object_text_set(wd->ent, buf);
205}
206
207static void
208_write_label(Evas_Object *obj)
209{
210 Eina_List *l;
211 Elm_Spinner_Special_Value *sv;
212 Widget_Data *wd = elm_widget_data_get(obj);
213 char buf[1024];
214
215 if (!wd) return;
216 EINA_LIST_FOREACH(wd->special_values, l, sv)
217 {
218 if (sv->value == wd->val)
219 {
220 snprintf(buf, sizeof(buf), "%s", sv->label);
221 goto apply;
222 }
223 }
224 if (wd->label)
225 snprintf(buf, sizeof(buf), wd->label, wd->val);
226 else
227 snprintf(buf, sizeof(buf), "%.0f", wd->val);
228
229apply:
230 edje_object_part_text_escaped_set(wd->spinner, "elm.text", buf);
231 if (wd->entry_visible) _entry_show(wd);
232}
233
234static Eina_Bool
235_value_set(Evas_Object *obj, double new_val)
236{
237 Widget_Data *wd = elm_widget_data_get(obj);
238
239 if (!wd) return EINA_FALSE;
240
241 if (wd->round > 0)
242 new_val = wd->base +
243 (double)((((int)(new_val - wd->base)) / wd->round) * wd->round);
244
245 if (wd->wrap)
246 {
247 while (new_val < wd->val_min)
248 new_val = wd->val_max + new_val + 1 - wd->val_min;
249 while (new_val > wd->val_max)
250 new_val = wd->val_min + new_val - wd->val_max - 1;
251 }
252 else
253 {
254 if (new_val < wd->val_min)
255 new_val = wd->val_min;
256 else if (new_val > wd->val_max)
257 new_val = wd->val_max;
258 }
259
260 if (new_val == wd->val) return EINA_FALSE;
261 wd->val = new_val;
262
263 evas_object_smart_callback_call(obj, SIG_CHANGED, NULL);
264 if (wd->delay) ecore_timer_del(wd->delay);
265 wd->delay = ecore_timer_add(0.2, _delay_change, obj);
266
267 return EINA_TRUE;
268}
269
270static void
271_sizing_eval(Evas_Object *obj)
272{
273 Widget_Data *wd = elm_widget_data_get(obj);
274 Evas_Coord minw = -1, minh = -1;
275 if (!wd) return;
276 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
277 edje_object_size_min_restricted_calc(wd->spinner, &minw, &minh, minw, minh);
278 elm_coords_finger_size_adjust(1, &minw, 1, &minh);
279 evas_object_size_hint_min_set(obj, minw, minh);
280 evas_object_size_hint_max_set(obj, -1, -1);
281}
282
283/*
284 static void
285 _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info)
286 {
287 _sizing_eval(data);
288 }
289 */
290
291static void
292_val_set(Evas_Object *obj)
293{
294 Widget_Data *wd = elm_widget_data_get(obj);
295 double pos = 0.0;
296 if (!wd) return;
297 if (wd->val_max > wd->val_min)
298 pos = ((wd->val - wd->val_min) / (wd->val_max - wd->val_min));
299 if (pos < 0.0) pos = 0.0;
300 else if (pos > 1.0) pos = 1.0;
301 edje_object_part_drag_value_set(wd->spinner, "elm.dragable.slider",
302 pos, pos);
303}
304
305static void
306_drag(void *data, Evas_Object *_obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
307{
308 Evas_Object *obj = data;
309 Widget_Data *wd = elm_widget_data_get(obj);
310 double pos = 0.0, offset, delta;
311 if (!wd) return;
312 if (wd->entry_visible) return;
313 edje_object_part_drag_value_get(wd->spinner, "elm.dragable.slider",
314 &pos, NULL);
315
316 offset = wd->step * _elm_config->scale;
317 delta = (pos - wd->drag_start_pos) * offset;
318 /* If we are on rtl mode, change the delta to be negative on such changes */
319 if (elm_widget_mirrored_get(obj)) delta *= -1;
320 if (_value_set(data, wd->drag_start_pos + delta)) _write_label(data);
321 wd->dragging = 1;
322}
323
324static void
325_drag_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
326{
327 Widget_Data *wd = elm_widget_data_get(data);
328 double pos;
329 if (!wd) return;
330 edje_object_part_drag_value_get(wd->spinner, "elm.dragable.slider",
331 &pos, NULL);
332 wd->drag_start_pos = pos;
333}
334
335static void
336_drag_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
337{
338 Widget_Data *wd = elm_widget_data_get(data);
339 if (!wd) return;
340 wd->drag_start_pos = 0;
341 edje_object_part_drag_value_set(wd->spinner, "elm.dragable.slider", 0.0, 0.0);
342}
343
344static void
345_hide_entry(Evas_Object *obj)
346{
347 Widget_Data *wd = elm_widget_data_get(obj);
348 if (!wd) return;
349 edje_object_signal_emit(wd->spinner, "elm,state,inactive", "elm");
350 wd->entry_visible = 0;
351}
352
353static void
354_reset_value(Evas_Object *obj)
355{
356 Widget_Data *wd = elm_widget_data_get(obj);
357 if (!wd) return;
358 _hide_entry(obj);
359 elm_spinner_value_set(obj, wd->orig_val);
360}
361
362static void
363_apply_entry_value(Evas_Object *obj)
364{
365 Widget_Data *wd = elm_widget_data_get(obj);
366 const char *str;
367 char *end;
368 double val;
369
370 if (!wd) return;
371 _hide_entry(obj);
372 str = elm_object_text_get(wd->ent);
373 if (!str) return;
374 val = strtod(str, &end);
375 if ((*end != '\0') && (!isspace(*end))) return;
376 elm_spinner_value_set(obj, val);
377}
378
379static void
380_toggle_entry(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
381{
382 Widget_Data *wd = elm_widget_data_get(data);
383 if (!wd) return;
384 if (wd->dragging)
385 {
386 wd->dragging = 0;
387 return;
388 }
389 if (elm_widget_disabled_get(data)) return;
390 if (!wd->editable) return;
391 if (wd->entry_visible) _apply_entry_value(data);
392 else
393 {
394 wd->orig_val = wd->val;
395 edje_object_signal_emit(wd->spinner, "elm,state,active", "elm");
396 _entry_show(wd);
397 elm_entry_select_all(wd->ent);
398 elm_widget_focus_set(wd->ent, 1);
399 wd->entry_visible = 1;
400 }
401}
402
403static Eina_Bool
404_spin_value(void *data)
405{
406 Widget_Data *wd = elm_widget_data_get(data);
407 if (!wd) return ECORE_CALLBACK_CANCEL;
408 if (_value_set(data, wd->val + wd->spin_speed)) _write_label(data);
409 wd->interval = wd->interval / 1.05;
410 ecore_timer_interval_set(wd->spin, wd->interval);
411 return ECORE_CALLBACK_RENEW;
412}
413
414static void
415_val_inc_start(Evas_Object *obj)
416{
417 Widget_Data *wd = elm_widget_data_get(obj);
418 if (!wd) return;
419 wd->interval = wd->first_interval;
420 wd->spin_speed = wd->step;
421 if (wd->spin) ecore_timer_del(wd->spin);
422 wd->spin = ecore_timer_add(wd->interval, _spin_value, obj);
423 _spin_value(obj);
424}
425
426static void
427_val_inc_stop(Evas_Object *obj)
428{
429 Widget_Data *wd = elm_widget_data_get(obj);
430 if (!wd) return;
431 wd->interval = wd->first_interval;
432 wd->spin_speed = 0;
433 if (wd->spin) ecore_timer_del(wd->spin);
434 wd->spin = NULL;
435}
436
437static void
438_val_dec_start(Evas_Object *obj)
439{
440 Widget_Data *wd = elm_widget_data_get(obj);
441 if (!wd) return;
442 wd->interval = wd->first_interval;
443 wd->spin_speed = -wd->step;
444 if (wd->spin) ecore_timer_del(wd->spin);
445 wd->spin = ecore_timer_add(wd->interval, _spin_value, obj);
446 _spin_value(obj);
447}
448
449static void
450_val_dec_stop(Evas_Object *obj)
451{
452 Widget_Data *wd = elm_widget_data_get(obj);
453 if (!wd) return;
454 wd->interval = wd->first_interval;
455 wd->spin_speed = 0;
456 if (wd->spin) ecore_timer_del(wd->spin);
457 wd->spin = NULL;
458}
459
460static void
461_button_inc_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
462{
463 Widget_Data *wd = elm_widget_data_get(data);
464 if (!wd) return;
465 if (wd->entry_visible)
466 {
467 _reset_value(data);
468 return;
469 }
470 _val_inc_start(data);
471}
472
473static void
474_button_inc_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
475{
476 Widget_Data *wd = elm_widget_data_get(data);
477 if (!wd) return;
478 _val_inc_stop(data);
479}
480
481static void
482_button_dec_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
483{
484 Widget_Data *wd = elm_widget_data_get(data);
485 if (!wd) return;
486 if (wd->entry_visible)
487 {
488 _reset_value(data);
489 return;
490 }
491 _val_dec_start(data);
492}
493
494static void
495_button_dec_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
496{
497 Widget_Data *wd = elm_widget_data_get(data);
498 if (!wd) return;
499 _val_dec_stop(data);
500}
501
502static void
503_entry_activated(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
504{
505 Widget_Data *wd = elm_widget_data_get(data);
506 if (!wd) return;
507 _apply_entry_value(data);
508 evas_object_smart_callback_call(data, SIG_CHANGED, NULL);
509 if (wd->delay) ecore_timer_del(wd->delay);
510 wd->delay = ecore_timer_add(0.2, _delay_change, data);
511}
512
513static Eina_Bool
514_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
515{
516 Widget_Data *wd = elm_widget_data_get(obj);
517 if (!wd) return EINA_FALSE;
518 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
519 if (type == EVAS_CALLBACK_KEY_DOWN)
520 {
521 Evas_Event_Key_Down *ev = event_info;
522 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
523 else if (!strcmp(ev->keyname, "Left") ||
524 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)) ||
525 !strcmp(ev->keyname, "Down") ||
526 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
527 {
528 _val_dec_start(obj);
529 edje_object_signal_emit(wd->spinner, "elm,left,anim,activate", "elm");
530 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
531 return EINA_TRUE;
532 }
533 else if (!strcmp(ev->keyname, "Right") ||
534 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)) ||
535 !strcmp(ev->keyname, "Up") ||
536 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
537 {
538 _val_inc_start(obj);
539 edje_object_signal_emit(wd->spinner, "elm,right,anim,activate", "elm");
540 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
541 return EINA_TRUE;
542 }
543 }
544 else if (type == EVAS_CALLBACK_KEY_UP)
545 {
546 Evas_Event_Key_Down *ev = event_info;
547 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
548 if (!strcmp(ev->keyname, "Right") ||
549 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)) ||
550 !strcmp(ev->keyname, "Up") ||
551 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
552 _val_inc_stop(obj);
553 else if (!strcmp(ev->keyname, "Left") ||
554 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)) ||
555 !strcmp(ev->keyname, "Down") ||
556 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
557 _val_dec_stop(obj);
558 else return EINA_FALSE;
559 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
560 return EINA_TRUE;
561 }
562 return EINA_FALSE;
563}
564
565EAPI Evas_Object *
566elm_spinner_add(Evas_Object *parent)
567{
568 Evas_Object *obj;
569 Evas *e;
570 Widget_Data *wd;
571
572 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
573
574 ELM_SET_WIDTYPE(widtype, "spinner");
575 elm_widget_type_set(obj, "spinner");
576 elm_widget_sub_object_add(parent, obj);
577 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
578 elm_widget_data_set(obj, wd);
579 elm_widget_del_hook_set(obj, _del_hook);
580 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
581 elm_widget_theme_hook_set(obj, _theme_hook);
582 elm_widget_disable_hook_set(obj, _disable_hook);
583 elm_widget_signal_emit_hook_set(obj, _signal_emit_hook);
584 elm_widget_signal_callback_add_hook_set(obj, _signal_callback_add_hook);
585 elm_widget_signal_callback_del_hook_set(obj, _signal_callback_del_hook);
586 elm_widget_can_focus_set(obj, EINA_TRUE);
587 elm_widget_event_hook_set(obj, _event_hook);
588
589 wd->val = 0.0;
590 wd->val_min = 0.0;
591 wd->val_max = 100.0;
592 wd->wrap = 0;
593 wd->step = 1.0;
594 wd->first_interval = 0.85;
595 wd->entry_visible = 0;
596 wd->editable = EINA_TRUE;
597
598 wd->spinner = edje_object_add(e);
599 _elm_theme_object_set(obj, wd->spinner, "spinner", "base", "default");
600 elm_widget_resize_object_set(obj, wd->spinner);
601 edje_object_signal_callback_add(wd->spinner, "drag", "*", _drag, obj);
602 edje_object_signal_callback_add(wd->spinner, "drag,start", "*",
603 _drag_start, obj);
604 edje_object_signal_callback_add(wd->spinner, "drag,stop", "*",
605 _drag_stop, obj);
606 edje_object_signal_callback_add(wd->spinner, "drag,step", "*",
607 _drag_stop, obj);
608 edje_object_signal_callback_add(wd->spinner, "drag,page", "*",
609 _drag_stop, obj);
610
611 edje_object_signal_callback_add(wd->spinner, "elm,action,increment,start",
612 "*", _button_inc_start, obj);
613 edje_object_signal_callback_add(wd->spinner, "elm,action,increment,stop",
614 "*", _button_inc_stop, obj);
615 edje_object_signal_callback_add(wd->spinner, "elm,action,decrement,start",
616 "*", _button_dec_start, obj);
617 edje_object_signal_callback_add(wd->spinner, "elm,action,decrement,stop",
618 "*", _button_dec_stop, obj);
619 edje_object_part_drag_value_set(wd->spinner, "elm.dragable.slider",
620 0.0, 0.0);
621
622 wd->ent = elm_entry_add(obj);
623 elm_entry_single_line_set(wd->ent, 1);
624 evas_object_smart_callback_add(wd->ent, "activated", _entry_activated, obj);
625 edje_object_part_swallow(wd->spinner, "elm.swallow.entry", wd->ent);
626 edje_object_signal_callback_add(wd->spinner, "elm,action,entry,toggle",
627 "*", _toggle_entry, obj);
628
629 evas_object_smart_callbacks_descriptions_set(obj, _signals);
630
631 _mirrored_set(obj, elm_widget_mirrored_get(obj));
632 _write_label(obj);
633 _sizing_eval(obj);
634 return obj;
635}
636
637EAPI void
638elm_spinner_label_format_set(Evas_Object *obj, const char *fmt)
639{
640 ELM_CHECK_WIDTYPE(obj, widtype);
641 Widget_Data *wd = elm_widget_data_get(obj);
642 if (!wd) return;
643 eina_stringshare_replace(&wd->label, fmt);
644 _write_label(obj);
645 _sizing_eval(obj);
646}
647
648EAPI const char *
649elm_spinner_label_format_get(const Evas_Object *obj)
650{
651 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
652 Widget_Data *wd = elm_widget_data_get(obj);
653 if (!wd) return NULL;
654 return wd->label;
655}
656
657EAPI void
658elm_spinner_min_max_set(Evas_Object *obj, double min, double max)
659{
660 ELM_CHECK_WIDTYPE(obj, widtype);
661 Widget_Data *wd = elm_widget_data_get(obj);
662 if (!wd) return;
663 if ((wd->val_min == min) && (wd->val_max == max)) return;
664 wd->val_min = min;
665 wd->val_max = max;
666 if (wd->val < wd->val_min) wd->val = wd->val_min;
667 if (wd->val > wd->val_max) wd->val = wd->val_max;
668 _val_set(obj);
669 _write_label(obj);
670}
671
672EAPI void
673elm_spinner_min_max_get(const Evas_Object *obj, double *min, double *max)
674{
675 if (min) *min = 0.0;
676 if (max) *max = 0.0;
677 ELM_CHECK_WIDTYPE(obj, widtype);
678 Widget_Data *wd = elm_widget_data_get(obj);
679 if (!wd) return;
680 if (min) *min = wd->val_min;
681 if (max) *max = wd->val_max;
682}
683
684EAPI void
685elm_spinner_step_set(Evas_Object *obj, double step)
686{
687 ELM_CHECK_WIDTYPE(obj, widtype);
688 Widget_Data *wd = elm_widget_data_get(obj);
689 if (!wd) return;
690 wd->step = step;
691}
692
693EAPI double
694elm_spinner_step_get(const Evas_Object *obj)
695{
696 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
697 Widget_Data *wd = elm_widget_data_get(obj);
698 if (!wd) return 0.0;
699 return wd->step;
700}
701
702EAPI void
703elm_spinner_value_set(Evas_Object *obj, double val)
704{
705 ELM_CHECK_WIDTYPE(obj, widtype);
706 Widget_Data *wd = elm_widget_data_get(obj);
707 if (!wd) return;
708 if (wd->val == val) return;
709 wd->val = val;
710 if (wd->val < wd->val_min) wd->val = wd->val_min;
711 if (wd->val > wd->val_max) wd->val = wd->val_max;
712 _val_set(obj);
713 _write_label(obj);
714}
715
716EAPI double
717elm_spinner_value_get(const Evas_Object *obj)
718{
719 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
720 Widget_Data *wd = elm_widget_data_get(obj);
721 if (!wd) return 0.0;
722 return wd->val;
723}
724
725EAPI void
726elm_spinner_wrap_set(Evas_Object *obj, Eina_Bool wrap)
727{
728 ELM_CHECK_WIDTYPE(obj, widtype);
729 Widget_Data *wd = elm_widget_data_get(obj);
730 if (!wd) return;
731 wd->wrap = wrap;
732}
733
734EAPI Eina_Bool
735elm_spinner_wrap_get(const Evas_Object *obj)
736{
737 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
738 Widget_Data *wd = elm_widget_data_get(obj);
739 if (!wd) return EINA_FALSE;
740 return wd->wrap;
741}
742
743EAPI void
744elm_spinner_special_value_add(Evas_Object *obj, double value, const char *label)
745{
746 Elm_Spinner_Special_Value *sv;
747 ELM_CHECK_WIDTYPE(obj, widtype);
748 Widget_Data *wd = elm_widget_data_get(obj);
749 if (!wd) return;
750
751 sv = calloc(1, sizeof(*sv));
752 if (!sv) return;
753 sv->value = value;
754 sv->label = eina_stringshare_add(label);
755
756 wd->special_values = eina_list_append(wd->special_values, sv);
757 _write_label(obj);
758}
759
760EAPI void
761elm_spinner_editable_set(Evas_Object *obj, Eina_Bool editable)
762{
763 ELM_CHECK_WIDTYPE(obj, widtype);
764 Widget_Data *wd = elm_widget_data_get(obj);
765 if (!wd) return;
766 wd->editable = editable;
767}
768
769EAPI Eina_Bool
770elm_spinner_editable_get(const Evas_Object *obj)
771{
772 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
773 Widget_Data *wd = elm_widget_data_get(obj);
774 if (!wd) return EINA_FALSE;
775 return wd->editable;
776}
777
778EAPI void
779elm_spinner_interval_set(Evas_Object *obj, double interval)
780{
781 ELM_CHECK_WIDTYPE(obj, widtype);
782 Widget_Data *wd = elm_widget_data_get(obj);
783 if (!wd) return;
784 wd->first_interval = interval;
785}
786
787EAPI double
788elm_spinner_interval_get(const Evas_Object *obj)
789{
790 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
791 Widget_Data *wd = elm_widget_data_get(obj);
792 if (!wd) return 0.0;
793 return wd->first_interval;
794}
795
796EAPI void
797elm_spinner_base_set(Evas_Object *obj, double base)
798{
799 ELM_CHECK_WIDTYPE(obj, widtype);
800 Widget_Data *wd = elm_widget_data_get(obj);
801 if (!wd) return;
802 wd->base = base;
803}
804
805EAPI double
806elm_spinner_base_get(const Evas_Object *obj)
807{
808 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
809 Widget_Data *wd = elm_widget_data_get(obj);
810 if (!wd) return 0.0;
811 return wd->base;
812}
813
814EAPI void
815elm_spinner_round_set(Evas_Object *obj, int rnd)
816{
817 ELM_CHECK_WIDTYPE(obj, widtype);
818 Widget_Data *wd = elm_widget_data_get(obj);
819 if (!wd) return;
820 wd->round = rnd;
821}
822
823EAPI int
824elm_spinner_round_get(const Evas_Object *obj)
825{
826 ELM_CHECK_WIDTYPE(obj, widtype) 0;
827 Widget_Data *wd = elm_widget_data_get(obj);
828 if (!wd) return 0;
829 return wd->round;
830}
diff --git a/libraries/elementary/src/lib/elm_spinner.h b/libraries/elementary/src/lib/elm_spinner.h
new file mode 100644
index 0000000..114a090
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_spinner.h
@@ -0,0 +1,426 @@
1/**
2 * @defgroup Spinner Spinner
3 * @ingroup Elementary
4 *
5 * @image html img/widget/spinner/preview-00.png
6 * @image latex img/widget/spinner/preview-00.eps
7 *
8 * A spinner is a widget which allows the user to increase or decrease
9 * numeric values using arrow buttons, or edit values directly, clicking
10 * over it and typing the new value.
11 *
12 * By default the spinner will not wrap and has a label
13 * of "%.0f" (just showing the integer value of the double).
14 *
15 * A spinner has a label that is formatted with floating
16 * point values and thus accepts a printf-style format string, like
17 * “%1.2f units”.
18 *
19 * It also allows specific values to be replaced by pre-defined labels.
20 *
21 * Smart callbacks one can register to:
22 *
23 * - "changed" - Whenever the spinner value is changed.
24 * - "delay,changed" - A short time after the value is changed by the user.
25 * This will be called only when the user stops dragging for a very short
26 * period or when they release their finger/mouse, so it avoids possibly
27 * expensive reactions to the value change.
28 *
29 * Available styles for it:
30 * - @c "default";
31 * - @c "vertical": up/down buttons at the right side and text left aligned.
32 *
33 * Supported elm_object common APIs.
34 * @li @ref elm_object_signal_emit
35 * @li @ref elm_object_signal_callback_add
36 * @li @ref elm_object_signal_callback_del
37 * @li @ref elm_object_disabled_set
38 * @li @ref elm_object_disabled_get
39 *
40 * Here is an example on its usage:
41 * @ref spinner_example
42 */
43
44/**
45 * @addtogroup Spinner
46 * @{
47 */
48
49/**
50 * Add a new spinner widget to the given parent Elementary
51 * (container) object.
52 *
53 * @param parent The parent object.
54 * @return a new spinner widget handle or @c NULL, on errors.
55 *
56 * This function inserts a new spinner widget on the canvas.
57 *
58 * @ingroup Spinner
59 *
60 */
61EAPI Evas_Object *elm_spinner_add(Evas_Object *parent);
62
63/**
64 * Set the format string of the displayed label.
65 *
66 * @param obj The spinner object.
67 * @param fmt The format string for the label display.
68 *
69 * If @c NULL, this sets the format to "%.0f". If not it sets the format
70 * string for the label text. The label text is provided a floating point
71 * value, so the label text can display up to 1 floating point value.
72 * Note that this is optional.
73 *
74 * Use a format string such as "%1.2f meters" for example, and it will
75 * display values like: "3.14 meters" for a value equal to 3.14159.
76 *
77 * Default is "%0.f".
78 *
79 * @see elm_spinner_label_format_get()
80 *
81 * @ingroup Spinner
82 */
83EAPI void elm_spinner_label_format_set(Evas_Object *obj, const char *fmt);
84
85/**
86 * Get the label format of the spinner.
87 *
88 * @param obj The spinner object.
89 * @return The text label format string in UTF-8.
90 *
91 * @see elm_spinner_label_format_set() for details.
92 *
93 * @ingroup Spinner
94 */
95EAPI const char *elm_spinner_label_format_get(const Evas_Object *obj);
96
97/**
98 * Set the minimum and maximum values for the spinner.
99 *
100 * @param obj The spinner object.
101 * @param min The minimum value.
102 * @param max The maximum value.
103 *
104 * Define the allowed range of values to be selected by the user.
105 *
106 * If actual value is less than @p min, it will be updated to @p min. If it
107 * is bigger then @p max, will be updated to @p max. Actual value can be
108 * get with elm_spinner_value_get().
109 *
110 * By default, min is equal to 0, and max is equal to 100.
111 *
112 * @warning Maximum must be greater than minimum.
113 *
114 * @see elm_spinner_min_max_get()
115 *
116 * @ingroup Spinner
117 */
118EAPI void elm_spinner_min_max_set(Evas_Object *obj, double min, double max);
119
120/**
121 * Get the minimum and maximum values of the spinner.
122 *
123 * @param obj The spinner object.
124 * @param min Pointer to store the minimum value.
125 * @param max Pointer to store the maximum value.
126 *
127 * @note If only one value is needed, the other pointer can be passed
128 * as @c NULL.
129 *
130 * @see elm_spinner_min_max_set() for details.
131 *
132 * @ingroup Spinner
133 */
134EAPI void elm_spinner_min_max_get(const Evas_Object *obj, double *min, double *max);
135
136/**
137 * Set the step used to increment or decrement the spinner value.
138 *
139 * @param obj The spinner object.
140 * @param step The step value.
141 *
142 * This value will be incremented or decremented to the displayed value.
143 * It will be incremented while the user keep right or top arrow pressed,
144 * and will be decremented while the user keep left or bottom arrow pressed.
145 *
146 * The interval to increment / decrement can be set with
147 * elm_spinner_interval_set().
148 *
149 * By default step value is equal to 1.
150 *
151 * @see elm_spinner_step_get()
152 *
153 * @ingroup Spinner
154 */
155EAPI void elm_spinner_step_set(Evas_Object *obj, double step);
156
157/**
158 * Get the step used to increment or decrement the spinner value.
159 *
160 * @param obj The spinner object.
161 * @return The step value.
162 *
163 * @see elm_spinner_step_get() for more details.
164 *
165 * @ingroup Spinner
166 */
167EAPI double elm_spinner_step_get(const Evas_Object *obj);
168
169/**
170 * Set the value the spinner displays.
171 *
172 * @param obj The spinner object.
173 * @param val The value to be displayed.
174 *
175 * Value will be presented on the label following format specified with
176 * elm_spinner_format_set().
177 *
178 * @warning The value must to be between min and max values. This values
179 * are set by elm_spinner_min_max_set().
180 *
181 * @see elm_spinner_value_get().
182 * @see elm_spinner_format_set().
183 * @see elm_spinner_min_max_set().
184 *
185 * @ingroup Spinner
186 */
187EAPI void elm_spinner_value_set(Evas_Object *obj, double val);
188
189/**
190 * Get the value displayed by the spinner.
191 *
192 * @param obj The spinner object.
193 * @return The value displayed.
194 *
195 * @see elm_spinner_value_set() for details.
196 *
197 * @ingroup Spinner
198 */
199EAPI double elm_spinner_value_get(const Evas_Object *obj);
200
201/**
202 * Set whether the spinner should wrap when it reaches its
203 * minimum or maximum value.
204 *
205 * @param obj The spinner object.
206 * @param wrap @c EINA_TRUE to enable wrap or @c EINA_FALSE to
207 * disable it.
208 *
209 * Disabled by default. If disabled, when the user tries to increment the
210 * value,
211 * but displayed value plus step value is bigger than maximum value,
212 * the spinner
213 * won't allow it. The same happens when the user tries to decrement it,
214 * but the value less step is less than minimum value.
215 *
216 * When wrap is enabled, in such situations it will allow these changes,
217 * but will get the value that would be less than minimum and subtracts
218 * from maximum. Or add the value that would be more than maximum to
219 * the minimum.
220 *
221 * E.g.:
222 * @li min value = 10
223 * @li max value = 50
224 * @li step value = 20
225 * @li displayed value = 20
226 *
227 * When the user decrement value (using left or bottom arrow), it will
228 * displays @c 40, because max - (min - (displayed - step)) is
229 * @c 50 - (@c 10 - (@c 20 - @c 20)) = @c 40.
230 *
231 * @see elm_spinner_wrap_get().
232 *
233 * @ingroup Spinner
234 */
235EAPI void elm_spinner_wrap_set(Evas_Object *obj, Eina_Bool wrap);
236
237/**
238 * Get whether the spinner should wrap when it reaches its
239 * minimum or maximum value.
240 *
241 * @param obj The spinner object
242 * @return @c EINA_TRUE means wrap is enabled. @c EINA_FALSE indicates
243 * it's disabled. If @p obj is @c NULL, @c EINA_FALSE is returned.
244 *
245 * @see elm_spinner_wrap_set() for details.
246 *
247 * @ingroup Spinner
248 */
249EAPI Eina_Bool elm_spinner_wrap_get(const Evas_Object *obj);
250
251/**
252 * Set whether the spinner can be directly edited by the user or not.
253 *
254 * @param obj The spinner object.
255 * @param editable @c EINA_TRUE to allow users to edit it or @c EINA_FALSE to
256 * don't allow users to edit it directly.
257 *
258 * Spinner objects can have edition @b disabled, in which state they will
259 * be changed only by arrows.
260 * Useful for contexts
261 * where you don't want your users to interact with it writing the value.
262 * Specially
263 * when using special values, the user can see real value instead
264 * of special label on edition.
265 *
266 * It's enabled by default.
267 *
268 * @see elm_spinner_editable_get()
269 *
270 * @ingroup Spinner
271 */
272EAPI void elm_spinner_editable_set(Evas_Object *obj, Eina_Bool editable);
273
274/**
275 * Get whether the spinner can be directly edited by the user or not.
276 *
277 * @param obj The spinner object.
278 * @return @c EINA_TRUE means edition is enabled. @c EINA_FALSE indicates
279 * it's disabled. If @p obj is @c NULL, @c EINA_FALSE is returned.
280 *
281 * @see elm_spinner_editable_set() for details.
282 *
283 * @ingroup Spinner
284 */
285EAPI Eina_Bool elm_spinner_editable_get(const Evas_Object *obj);
286
287/**
288 * Set a special string to display in the place of the numerical value.
289 *
290 * @param obj The spinner object.
291 * @param value The value to be replaced.
292 * @param label The label to be used.
293 *
294 * It's useful for cases when a user should select an item that is
295 * better indicated by a label than a value. For example, weekdays or months.
296 *
297 * E.g.:
298 * @code
299 * sp = elm_spinner_add(win);
300 * elm_spinner_min_max_set(sp, 1, 3);
301 * elm_spinner_special_value_add(sp, 1, "January");
302 * elm_spinner_special_value_add(sp, 2, "February");
303 * elm_spinner_special_value_add(sp, 3, "March");
304 * evas_object_show(sp);
305 * @endcode
306 *
307 * @ingroup Spinner
308 */
309EAPI void elm_spinner_special_value_add(Evas_Object *obj, double value, const char *label);
310
311/**
312 * Set the interval on time updates for an user mouse button hold
313 * on spinner widgets' arrows.
314 *
315 * @param obj The spinner object.
316 * @param interval The (first) interval value in seconds.
317 *
318 * This interval value is @b decreased while the user holds the
319 * mouse pointer either incrementing or decrementing spinner's value.
320 *
321 * This helps the user to get to a given value distant from the
322 * current one easier/faster, as it will start to change quicker and
323 * quicker on mouse button holds.
324 *
325 * The calculation for the next change interval value, starting from
326 * the one set with this call, is the previous interval divided by
327 * @c 1.05, so it decreases a little bit.
328 *
329 * The default starting interval value for automatic changes is
330 * @c 0.85 seconds.
331 *
332 * @see elm_spinner_interval_get()
333 *
334 * @ingroup Spinner
335 */
336EAPI void elm_spinner_interval_set(Evas_Object *obj, double interval);
337
338/**
339 * Get the interval on time updates for an user mouse button hold
340 * on spinner widgets' arrows.
341 *
342 * @param obj The spinner object.
343 * @return The (first) interval value, in seconds, set on it.
344 *
345 * @see elm_spinner_interval_set() for more details.
346 *
347 * @ingroup Spinner
348 */
349EAPI double elm_spinner_interval_get(const Evas_Object *obj);
350
351/**
352 * Set the base for rounding
353 *
354 * @param obj The spinner object
355 * @param base The base value
356 *
357 * Rounding works as follows:
358 *
359 * rounded_val = base + (double)(((value - base) / round) * round)
360 *
361 * Where rounded_val, value and base are doubles, and round is an integer.
362 *
363 * This means that things will be rounded to increments (or decrements) of
364 * "round" starting from value @p base. The default base for rounding is 0.
365 *
366 * Example: round = 3, base = 2
367 * Values: 3, 6, 9, 12, 15, ...
368 *
369 * Example: round = 2, base = 5.5
370 * Values: 5.5, 7.5, 9.5, 11.5, ...
371 *
372 * @see elm_spinner_round_get()
373 * @see elm_spinner_base_get() too.
374 *
375 * @ingroup Spinner
376 */
377EAPI void elm_spinner_base_set(Evas_Object *obj, double base);
378
379/**
380 * Get the base for rounding
381 *
382 * @param obj The spinner object
383 * @return The base rounding value
384 *
385 * This returns the base for rounding.
386 *
387 * @see elm_spinner_round_set() too.
388 * @see elm_spinner_base_set() too.
389 *
390 * @ingroup Spinner
391 */
392EAPI double elm_spinner_base_get(const Evas_Object *obj);
393
394/**
395 * Set the round value for rounding
396 *
397 * @param obj The spinner object
398 * @param rnd The rounding value
399 *
400 * Sets the rounding value used for value rounding in the spinner.
401 *
402 * @see elm_spinner_round_get()
403 * @see elm_spinner_base_set()
404 *
405 * @ingroup Spinner
406 */
407EAPI void elm_spinner_round_set(Evas_Object *obj, int rnd);
408
409/**
410 * Get the round value for rounding
411 *
412 * @param obj The spinner object
413 * @return The rounding value
414 *
415 * This returns the round value for rounding.
416 *
417 * @see elm_spinner_round_set() too.
418 * @see elm_spinner_base_set() too.
419 *
420 * @ingroup Spinner
421 */
422EAPI int elm_spinner_round_get(const Evas_Object *obj);
423
424/**
425 * @}
426 */
diff --git a/libraries/elementary/src/lib/elm_store.c b/libraries/elementary/src/lib/elm_store.c
new file mode 100644
index 0000000..a296f36
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_store.c
@@ -0,0 +1,751 @@
1#include <Elementary.h>
2#include <Elementary_Cursor.h>
3#include "elm_priv.h"
4
5typedef struct _Elm_Store_Filesystem Elm_Store_Filesystem;
6typedef struct _Elm_Store_Item_Filesystem Elm_Store_Item_Filesystem;
7
8#define ELM_STORE_MAGIC 0x3f89ea56
9#define ELM_STORE_FILESYSTEM_MAGIC 0x3f89ea57
10#define ELM_STORE_ITEM_MAGIC 0x5afe8c1d
11
12struct _Elm_Store
13{
14 EINA_MAGIC;
15 void (*free)(Elm_Store *store);
16 struct
17 {
18 void (*free)(Elm_Store_Item *item);
19 } item;
20 Evas_Object *genlist;
21 Ecore_Thread *list_th;
22 Eina_Inlist *items;
23 Eina_List *realized;
24 int realized_count;
25 int cache_max;
26 struct
27 {
28 struct
29 {
30 Elm_Store_Item_List_Cb func;
31 void *data;
32 } list;
33 struct
34 {
35 Elm_Store_Item_Fetch_Cb func;
36 void *data;
37 } fetch;
38 struct
39 {
40 Elm_Store_Item_Unfetch_Cb func;
41 void *data;
42 } unfetch;
43 } cb;
44 Eina_Bool sorted : 1;
45 Eina_Bool fetch_thread : 1;
46};
47
48struct _Elm_Store_Item
49{
50 EINA_INLIST;
51 EINA_MAGIC;
52 Elm_Store *store;
53 Elm_Object_Item *item;
54 Ecore_Thread *fetch_th;
55 Ecore_Job *eval_job;
56 const Elm_Store_Item_Mapping *mapping;
57 void *data;
58 Eina_Lock lock;
59 Eina_Bool live : 1;
60 Eina_Bool was_live : 1;
61 Eina_Bool realized : 1;
62 Eina_Bool fetched : 1;
63};
64
65struct _Elm_Store_Filesystem
66{
67 Elm_Store base;
68 EINA_MAGIC;
69 const char *dir;
70};
71
72struct _Elm_Store_Item_Filesystem
73{
74 Elm_Store_Item base;
75 const char *path;
76};
77
78static Elm_Genlist_Item_Class _store_item_class;
79
80static void
81_store_cache_trim(Elm_Store *st)
82{
83 while ((st->realized ) &&
84 (((int)eina_list_count(st->realized) - st->realized_count)
85 > st->cache_max))
86 {
87 Elm_Store_Item *sti = st->realized->data;
88 if (sti->realized)
89 {
90 st->realized = eina_list_remove_list(st->realized, st->realized);
91 sti->realized = EINA_FALSE;
92 }
93 eina_lock_take(&sti->lock);
94 if (!sti->fetched)
95 {
96 eina_lock_release(&sti->lock);
97 if (sti->fetch_th)
98 {
99 ecore_thread_cancel(sti->fetch_th);
100 sti->fetch_th = NULL;
101 }
102 eina_lock_take(&sti->lock);
103 }
104 sti->fetched = EINA_FALSE;
105//// let fetch/unfetch do the locking
106// eina_lock_release(&sti->lock);
107 if (st->cb.unfetch.func)
108 st->cb.unfetch.func(st->cb.unfetch.data, sti);
109// eina_lock_take(&sti->lock);
110 sti->data = NULL;
111 eina_lock_release(&sti->lock);
112 }
113}
114
115static void
116_store_genlist_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
117{
118 Elm_Store *st = data;
119 st->genlist = NULL;
120 if (st->list_th)
121 {
122 ecore_thread_cancel(st->list_th);
123 st->list_th = NULL;
124 }
125 eina_list_free(st->realized);
126 while (st->items)
127 {
128 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
129 if (sti->eval_job) ecore_job_del(sti->eval_job);
130 if (sti->fetch_th)
131 {
132 ecore_thread_cancel(sti->fetch_th);
133 sti->fetch_th = NULL;
134 }
135 if (sti->store->item.free) sti->store->item.free(sti);
136 eina_lock_take(&sti->lock);
137 if (sti->data)
138 {
139 if (st->cb.unfetch.func)
140 st->cb.unfetch.func(st->cb.unfetch.data, sti);
141 sti->data = NULL;
142 }
143 eina_lock_release(&sti->lock);
144 eina_lock_free(&sti->lock);
145 st->items = NULL;
146 free(sti);
147 }
148 // FIXME: kill threads and more
149}
150
151////// **** WARNING ***********************************************************
152//// * This function runs inside a thread outside efl mainloop. Be careful! *
153// ************************************************************************
154/* TODO: refactor lock part into core? this does not depend on filesystm part */
155static void
156_store_filesystem_fetch_do(void *data, Ecore_Thread *th __UNUSED__)
157{
158 Elm_Store_Item *sti = data;
159 eina_lock_take(&sti->lock);
160 if (sti->data)
161 {
162 eina_lock_release(&sti->lock);
163 return;
164 }
165 if (!sti->fetched)
166 {
167//// let fetch/unfetch do the locking
168// eina_lock_release(&sti->lock);
169 if (sti->store->cb.fetch.func)
170 sti->store->cb.fetch.func(sti->store->cb.fetch.data, sti);
171// eina_lock_take(&sti->lock);
172 sti->fetched = EINA_TRUE;
173 }
174 eina_lock_release(&sti->lock);
175}
176// ************************************************************************
177//// * End of separate thread function. *
178////// ************************************************************************
179/* TODO: refactor lock part into core? this does not depend on filesystm part */
180static void
181_store_filesystem_fetch_end(void *data, Ecore_Thread *th)
182{
183 Elm_Store_Item *sti = data;
184 eina_lock_take(&sti->lock);
185 if (sti->data) elm_genlist_item_update(sti->item);
186 eina_lock_release(&sti->lock);
187 if (th == sti->fetch_th) sti->fetch_th = NULL;
188}
189
190/* TODO: refactor lock part into core? this does not depend on filesystm part */
191static void
192_store_filesystem_fetch_cancel(void *data, Ecore_Thread *th)
193{
194 Elm_Store_Item *sti = data;
195 eina_lock_take(&sti->lock);
196 if (th == sti->fetch_th) sti->fetch_th = NULL;
197 if (sti->data) elm_genlist_item_update(sti->item);
198 eina_lock_release(&sti->lock);
199}
200
201static void
202_store_item_eval(void *data)
203{
204 Elm_Store_Item *sti = data;
205 sti->eval_job = NULL;
206 if (sti->live == sti->was_live) return;
207 sti->was_live = sti->live;
208 if (sti->live)
209 {
210 _store_cache_trim(sti->store);
211 if (sti->realized)
212 sti->store->realized = eina_list_remove(sti->store->realized, sti);
213 sti->store->realized = eina_list_append(sti->store->realized, sti);
214 sti->realized = EINA_TRUE;
215 if ((sti->store->fetch_thread) && (!sti->fetch_th))
216 sti->fetch_th = ecore_thread_run(_store_filesystem_fetch_do,
217 _store_filesystem_fetch_end,
218 _store_filesystem_fetch_cancel,
219 sti);
220 else if ((!sti->store->fetch_thread))
221 {
222 _store_filesystem_fetch_do(sti, NULL);
223 _store_filesystem_fetch_end(sti, NULL);
224 }
225 }
226 else
227 {
228 if (sti->fetch_th)
229 {
230 ecore_thread_cancel(sti->fetch_th);
231 sti->fetch_th = NULL;
232 }
233 _store_cache_trim(sti->store);
234 }
235}
236
237static void
238_store_genlist_item_realized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
239{
240 Elm_Store *st = data;
241 Elm_Object_Item *gli = event_info;
242 Elm_Store_Item *sti = elm_object_item_data_get(gli);
243 if (!sti) return;
244 st->realized_count++;
245 sti->live = EINA_TRUE;
246 if (sti->eval_job) ecore_job_del(sti->eval_job);
247 sti->eval_job = ecore_job_add(_store_item_eval, sti);
248}
249
250static void
251_store_genlist_item_unrealized(void *data, Evas_Object *obj __UNUSED__, void *event_info)
252{
253 Elm_Store *st = data;
254 Elm_Object_Item *gli = event_info;
255 Elm_Store_Item *sti = elm_object_item_data_get(gli);
256 if (!sti) return;
257 st->realized_count--;
258 sti->live = EINA_FALSE;
259 if (sti->eval_job) ecore_job_del(sti->eval_job);
260 sti->eval_job = ecore_job_add(_store_item_eval, sti);
261}
262
263static const Elm_Store_Item_Mapping *
264_store_item_mapping_find(Elm_Store_Item *sti, const char *part)
265{
266 const Elm_Store_Item_Mapping *m;
267
268 for (m = sti->mapping; m; m ++)
269 {
270 if (m->type == ELM_STORE_ITEM_MAPPING_NONE) break;
271 if (!strcmp(part, m->part)) return m;
272 }
273 return NULL;
274}
275
276static char *
277_store_item_text_get(void *data, Evas_Object *obj __UNUSED__, const char *part)
278{
279 Elm_Store_Item *sti = data;
280 const char *s = "";
281 eina_lock_take(&sti->lock);
282 if (sti->data)
283 {
284 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
285 if (m)
286 {
287 switch (m->type)
288 {
289 case ELM_STORE_ITEM_MAPPING_LABEL:
290 s = *(char **)(((unsigned char *)sti->data) + m->offset);
291 break;
292 case ELM_STORE_ITEM_MAPPING_CUSTOM:
293 if (m->details.custom.func)
294 s = m->details.custom.func(sti->data, sti, part);
295 break;
296 default:
297 break;
298 }
299 }
300 }
301 eina_lock_release(&sti->lock);
302 return s ? strdup(s) : NULL;
303}
304
305static Evas_Object *
306_store_item_content_get(void *data, Evas_Object *obj, const char *part)
307{
308 Elm_Store_Item *sti = data;
309 eina_lock_take(&sti->lock);
310 if (sti->data)
311 {
312 const Elm_Store_Item_Mapping *m = _store_item_mapping_find(sti, part);
313 if (m)
314 {
315 Evas_Object *ic = NULL;
316 const char *s = NULL;
317
318 switch (m->type)
319 {
320 case ELM_STORE_ITEM_MAPPING_ICON:
321 ic = elm_icon_add(obj);
322 s = *(char **)(((unsigned char *)sti->data) + m->offset);
323 elm_icon_order_lookup_set(ic, m->details.icon.lookup_order);
324 evas_object_size_hint_aspect_set(ic,
325 EVAS_ASPECT_CONTROL_VERTICAL,
326 m->details.icon.w,
327 m->details.icon.h);
328 elm_icon_smooth_set(ic, m->details.icon.smooth);
329 elm_icon_no_scale_set(ic, m->details.icon.no_scale);
330 elm_icon_resizable_set(ic,
331 m->details.icon.scale_up,
332 m->details.icon.scale_down);
333 if (s)
334 {
335 if (m->details.icon.standard_name)
336 elm_icon_standard_set(ic, s);
337 else
338 elm_icon_file_set(ic, s, NULL);
339 }
340 break;
341 case ELM_STORE_ITEM_MAPPING_PHOTO:
342 ic = elm_icon_add(obj);
343 s = *(char **)(((unsigned char *)sti->data) + m->offset);
344 elm_photo_size_set(ic, m->details.photo.size);
345 if (s)
346 elm_photo_file_set(ic, s);
347 break;
348 case ELM_STORE_ITEM_MAPPING_CUSTOM:
349 if (m->details.custom.func)
350 ic = m->details.custom.func(sti->data, sti, part);
351 break;
352 default:
353 break;
354 }
355 eina_lock_release(&sti->lock);
356 return ic;
357 }
358 }
359 eina_lock_release(&sti->lock);
360 return NULL;
361}
362
363static void
364_store_item_del(void *data __UNUSED__, Evas_Object *obj __UNUSED__)
365{
366}
367
368////// **** WARNING ***********************************************************
369//// * This function runs inside a thread outside efl mainloop. Be careful! *
370// ************************************************************************
371static int
372_store_filesystem_sort_cb(void *d1, void *d2)
373{
374 Elm_Store_Item_Info *info1 = d1, *info2 = d2;
375 if ((!info1->sort_id) || (!info2->sort_id)) return 0;
376 return strcoll(info1->sort_id, info2->sort_id);
377}
378
379static void
380_store_filesystem_list_do(void *data, Ecore_Thread *th __UNUSED__)
381{
382 Elm_Store_Filesystem *st = data;
383 Eina_Iterator *it;
384 const Eina_File_Direct_Info *finf;
385 Eina_List *sorted = NULL;
386 Elm_Store_Item_Info_Filesystem *info;
387
388 // FIXME: need a way to abstract the open, list, feed items from list
389 // and maybe get initial sortable key vals etc.
390 it = eina_file_stat_ls(st->dir);
391 if (!it) return;
392 EINA_ITERATOR_FOREACH(it, finf)
393 {
394 Eina_Bool ok;
395 size_t pathsz = finf->path_length + 1;
396
397 if (finf->path[finf->name_start] == '.') continue ;
398
399 info = calloc(1, sizeof(Elm_Store_Item_Info_Filesystem) + pathsz);
400 if (!info) continue;
401 info->path = ((char *)info) + sizeof(Elm_Store_Item_Info_Filesystem);
402 memcpy(info->path, finf->path, pathsz);
403 ok = EINA_TRUE;
404 if (st->base.cb.list.func)
405 ok = st->base.cb.list.func(st->base.cb.list.data, &info->base);
406 if (ok)
407 {
408 if (!st->base.sorted) ecore_thread_feedback(th, info);
409 else sorted = eina_list_append(sorted, info);
410 }
411 else
412 {
413 if (info->base.sort_id) free(info->base.sort_id);
414 free(info);
415 }
416 if (ecore_thread_check(th)) break;
417 }
418 eina_iterator_free(it);
419 if (sorted)
420 {
421 sorted = eina_list_sort(sorted, 0,
422 EINA_COMPARE_CB(_store_filesystem_sort_cb));
423 EINA_LIST_FREE(sorted, info)
424 {
425 if (!ecore_thread_check(th)) ecore_thread_feedback(th, info);
426 }
427 }
428}
429// ************************************************************************
430//// * End of separate thread function. *
431////// ************************************************************************
432
433static void
434_store_filesystem_list_end(void *data, Ecore_Thread *th)
435{
436 Elm_Store *st = data;
437 if (th == st->list_th) st->list_th = NULL;
438}
439
440static void
441_store_filesystem_list_cancel(void *data, Ecore_Thread *th)
442{
443 Elm_Store *st = data;
444 if (th == st->list_th) st->list_th = NULL;
445}
446
447static void
448_store_filesystem_list_update(void *data, Ecore_Thread *th __UNUSED__, void *msg)
449{
450 Elm_Store *st = data;
451 Elm_Store_Item_Filesystem *sti;
452 Elm_Genlist_Item_Class *itc;
453 Elm_Store_Item_Info_Filesystem *info = msg;
454
455 sti = calloc(1, sizeof(Elm_Store_Item_Filesystem));
456 if (!sti) goto done;
457 eina_lock_new(&sti->base.lock);
458 EINA_MAGIC_SET(&(sti->base), ELM_STORE_ITEM_MAGIC);
459 sti->base.store = st;
460 sti->base.data = info->base.data;
461 sti->base.mapping = info->base.mapping;
462 sti->path = eina_stringshare_add(info->path);
463
464 itc = info->base.item_class;
465 if (!itc) itc = &_store_item_class;
466 else
467 {
468 itc->func.text_get = _store_item_text_get;
469 itc->func.content_get = _store_item_content_get;
470 itc->func.state_get = NULL; // FIXME: support state gets later
471 itc->func.del = _store_item_del;
472 }
473
474 // FIXME: handle being a parent (tree)
475 sti->base.item = elm_genlist_item_append(st->genlist, itc,
476 sti/* item data */,
477 NULL/* parent */,
478 ELM_GENLIST_ITEM_NONE,
479 NULL/* func */,
480 NULL/* func data */);
481 st->items = eina_inlist_append(st->items, (Eina_Inlist *)sti);
482done:
483 if (info->base.sort_id) free(info->base.sort_id);
484 free(info);
485}
486
487// public api calls
488static Elm_Store *
489_elm_store_new(size_t size)
490{
491 Elm_Store *st = calloc(1, size);
492 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
493
494 // TODO: BEGIN - move to elm_store_init()
495 eina_magic_string_set(ELM_STORE_MAGIC, "Elm_Store");
496 eina_magic_string_set(ELM_STORE_FILESYSTEM_MAGIC, "Elm_Store_Filesystem");
497 eina_magic_string_set(ELM_STORE_ITEM_MAGIC, "Elm_Store_Item");
498 // setup default item class (always the same) if list cb doesnt provide one
499 _store_item_class.item_style = "default";
500 _store_item_class.func.text_get = _store_item_text_get;
501 _store_item_class.func.content_get = _store_item_content_get;
502 _store_item_class.func.state_get = NULL; // FIXME: support state gets later
503 _store_item_class.func.del = _store_item_del;
504 // TODO: END - move to elm_store_init()
505
506 EINA_MAGIC_SET(st, ELM_STORE_MAGIC);
507 st->cache_max = 128;
508 st->fetch_thread = EINA_TRUE;
509 return st;
510}
511#define elm_store_new(type) (type*)_elm_store_new(sizeof(type))
512
513static void
514_elm_store_filesystem_free(Elm_Store *store)
515{
516 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
517 eina_stringshare_del(st->dir);
518}
519
520static void
521_elm_store_filesystem_item_free(Elm_Store_Item *item)
522{
523 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
524 eina_stringshare_del(sti->path);
525}
526
527EAPI Elm_Store *
528elm_store_filesystem_new(void)
529{
530 Elm_Store_Filesystem *st = elm_store_new(Elm_Store_Filesystem);
531 EINA_SAFETY_ON_NULL_RETURN_VAL(st, NULL);
532
533 EINA_MAGIC_SET(st, ELM_STORE_FILESYSTEM_MAGIC);
534 st->base.free = _elm_store_filesystem_free;
535 st->base.item.free = _elm_store_filesystem_item_free;
536
537 return &st->base;
538}
539
540EAPI void
541elm_store_free(Elm_Store *st)
542{
543 void (*item_free)(Elm_Store_Item *);
544 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
545 if (st->list_th)
546 {
547 ecore_thread_cancel(st->list_th);
548 st->list_th = NULL;
549 }
550 eina_list_free(st->realized);
551 item_free = st->item.free;
552 while (st->items)
553 {
554 Elm_Store_Item *sti = (Elm_Store_Item *)st->items;
555 if (sti->eval_job) ecore_job_del(sti->eval_job);
556 if (sti->fetch_th)
557 {
558 ecore_thread_cancel(sti->fetch_th);
559 sti->fetch_th = NULL;
560 }
561 if (item_free) item_free(sti);
562 eina_lock_take(&sti->lock);
563 if (sti->data)
564 {
565 if (st->cb.unfetch.func)
566 st->cb.unfetch.func(st->cb.unfetch.data, sti);
567 sti->data = NULL;
568 }
569 eina_lock_release(&sti->lock);
570 eina_lock_free(&sti->lock);
571 free(sti);
572 }
573 if (st->genlist)
574 {
575 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
576 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
577 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
578 elm_genlist_clear(st->genlist);
579 st->genlist = NULL;
580 }
581 if (st->free) st->free(st);
582 free(st);
583}
584
585EAPI void
586elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj)
587{
588 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
589 if (st->genlist == obj) return;
590 if (st->genlist)
591 {
592 evas_object_event_callback_del_full(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
593 evas_object_smart_callback_del(st->genlist, "realized", _store_genlist_item_realized);
594 evas_object_smart_callback_del(st->genlist, "unrealized", _store_genlist_item_unrealized);
595 elm_genlist_clear(st->genlist);
596 }
597 st->genlist = obj;
598 if (!st->genlist) return;
599 evas_object_smart_callback_add(st->genlist, "realized", _store_genlist_item_realized, st);
600 evas_object_smart_callback_add(st->genlist, "unrealized", _store_genlist_item_unrealized, st);
601 evas_object_event_callback_add(st->genlist, EVAS_CALLBACK_DEL, _store_genlist_del, st);
602 elm_genlist_clear(st->genlist);
603}
604
605EAPI void
606elm_store_filesystem_directory_set(Elm_Store *store, const char *dir)
607{
608 Elm_Store_Filesystem *st = (Elm_Store_Filesystem *)store;
609 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return;
610 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return;
611 if (store->list_th)
612 {
613 ecore_thread_cancel(store->list_th);
614 store->list_th = NULL;
615 }
616 if (!eina_stringshare_replace(&st->dir, dir)) return;
617 store->list_th = ecore_thread_feedback_run(_store_filesystem_list_do,
618 _store_filesystem_list_update,
619 _store_filesystem_list_end,
620 _store_filesystem_list_cancel,
621 st, EINA_TRUE);
622}
623
624EAPI const char *
625elm_store_filesystem_directory_get(const Elm_Store *store)
626{
627 const Elm_Store_Filesystem *st = (const Elm_Store_Filesystem *)store;
628 if (!EINA_MAGIC_CHECK(store, ELM_STORE_MAGIC)) return NULL;
629 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
630 return st->dir;
631}
632
633EAPI void
634elm_store_cache_set(Elm_Store *st, int max)
635{
636 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
637 if (max < 0) max = 0;
638 st->cache_max = max;
639 _store_cache_trim(st);
640}
641
642EAPI int
643elm_store_cache_get(const Elm_Store *st)
644{
645 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return 0;
646 return st->cache_max;
647}
648
649EAPI void
650elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data)
651{
652 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
653 st->cb.list.func = func;
654 st->cb.list.data = (void *)data;
655}
656
657EAPI void
658elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data)
659{
660 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
661 st->cb.fetch.func = func;
662 st->cb.fetch.data = (void *)data;
663}
664
665EAPI void
666elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread)
667{
668 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
669 st->fetch_thread = !!use_thread;
670}
671
672EAPI Eina_Bool
673elm_store_fetch_thread_get(const Elm_Store *st)
674{
675 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
676 return st->fetch_thread;
677}
678
679EAPI void
680elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data)
681{
682 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
683 st->cb.unfetch.func = func;
684 st->cb.unfetch.data = (void *)data;
685}
686
687EAPI void
688elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted)
689{
690 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return;
691 st->sorted = sorted;
692}
693
694EAPI Eina_Bool
695elm_store_sorted_get(const Elm_Store *st)
696{
697 if (!EINA_MAGIC_CHECK(st, ELM_STORE_MAGIC)) return EINA_FALSE;
698 return st->sorted;
699}
700
701EAPI void
702elm_store_item_data_set(Elm_Store_Item *sti, void *data)
703{
704 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return;
705//// let fetch/unfetch do the locking
706// eina_lock_take(&sti->lock);
707 sti->data = data;
708// eina_lock_release(&sti->lock);
709}
710
711EAPI void *
712elm_store_item_data_get(Elm_Store_Item *sti)
713{
714 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
715 void *d;
716//// let fetch/unfetch do the locking
717// eina_lock_take(&sti->lock);
718 d = sti->data;
719// eina_lock_release(&sti->lock);
720 return d;
721}
722
723EAPI const Elm_Store *
724elm_store_item_store_get(const Elm_Store_Item *sti)
725{
726 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
727 // dont need lock
728 return sti->store;
729}
730
731EAPI const Elm_Object_Item *
732elm_store_item_genlist_item_get(const Elm_Store_Item *sti)
733{
734 if (!EINA_MAGIC_CHECK(sti, ELM_STORE_ITEM_MAGIC)) return NULL;
735 // dont need lock
736 return sti->item;
737}
738
739EAPI const char *
740elm_store_item_filesystem_path_get(const Elm_Store_Item *item)
741{
742 Elm_Store_Item_Filesystem *sti = (Elm_Store_Item_Filesystem *)item;
743 Elm_Store_Filesystem *st;
744 if (!EINA_MAGIC_CHECK(item, ELM_STORE_ITEM_MAGIC)) return NULL;
745 if (!EINA_MAGIC_CHECK(item->store, ELM_STORE_MAGIC)) return NULL;
746 /* ensure we're dealing with filesystem item */
747 st = (Elm_Store_Filesystem *)item->store;
748 if (!EINA_MAGIC_CHECK(st, ELM_STORE_FILESYSTEM_MAGIC)) return NULL;
749 // dont need lock
750 return sti->path;
751}
diff --git a/libraries/elementary/src/lib/elm_store.h b/libraries/elementary/src/lib/elm_store.h
new file mode 100644
index 0000000..8b28e91
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_store.h
@@ -0,0 +1,402 @@
1/**
2 * @defgroup Store Elementary Store
3 * @ingroup Elementary
4 *
5 * Store is an abstracting API that is intended to farm off fetching of data
6 * to threads running asynchronously from the mainloop that actually fetch
7 * data needed for a genlist (or possibly future other widgets) so scrolling
8 * never blocks waiting on IO (though normally this should be the users
9 * job - if using genlist, to ensure all data genlist needs is in memory at
10 * the time it needs it, and if it isn't to queue and defer a fetch and let
11 * genlist know later when its ready. Store actually does this and implements
12 * the infrastructure of this, leaving the actual fetch and convert up to
13 * functions provided by the user).
14 *
15 * It is possible for store to run inline without a thread, but this is
16 * highly inadvisable. you can disable this with:
17 *
18 * elm_store_fetch_thread_set(store, EINA_FALSE);
19 *
20 * Store works first by creating a store, setting up functions to list items
21 * and fetch items. Currently the only store type supported is the
22 * filesystem store, which will list the files inside a directory (not
23 * recursively) and then hand each file it finds (the file path) to the
24 * list function for evaluation.
25 *
26 * The list function may look at filename, may open the file or do
27 * anything it likes to determine something about the file. Either it
28 * filters it out (returns EINA_FALSE) and it is discarded or it
29 * returns EINA_TRUE and also provides a "sort id" which is a string
30 * store uses to figure out sorting. This string could be the filename, or
31 * some data based on its contents. The strings are sorted alphabetically
32 * like any normal ASCII strings, with case being important. As this listing
33 * function runs in a thread, it can do blocking IO and parsing without
34 * hurting the fluidity of the main loop and GUI. The list function also
35 * returns information on how to map fields in the source file to elements
36 * of the genlist item. For example, how the fetcher reads the private
37 * data struct of the user (what memory offset in the struct the data is at)
38 * and what type is there (it's a label of some sort, an icon, or with a
39 * custom mapping function that figures it out itself and creates the
40 * content needed for the genlist item).
41 *
42 * Store then uses this sort id to build (over time) a sorted list of items
43 * that then map 1:1 to genlist items. When these items are visible and
44 * need content, Store calls the fetch function per item, which is responsible
45 * for fetching the data from the given item and returning data to store
46 * so it can map this to some item content. This function also runs in a
47 * thread, and thus can do blocking IO work to later return the data. Sorting
48 * is optional and can be enabled or disabled too.
49 *
50 * When items are no longer needed, store will cal the unfetch function to
51 * free data in memory about that item that is no longer needed. This function
52 * is called in the mainloop and is expected to take minimal or almost no time
53 * to simply free up memory resources.
54 *
55 * @{
56 */
57
58typedef struct _Elm_Store Elm_Store; /**< A store object */
59typedef struct _Elm_Store_Item Elm_Store_Item; /**< A handle of a store item passed to store fetch/unfetch functions */
60typedef struct _Elm_Store_Item_Info Elm_Store_Item_Info; /**< Basic information about a store item - always cast into a specific type like Elm_Store_Item_Info_Filesystem */
61typedef struct _Elm_Store_Item_Info_Filesystem Elm_Store_Item_Info_Filesystem; /**< Filesystem specific information about a store item */
62typedef struct _Elm_Store_Item_Mapping Elm_Store_Item_Mapping; /**< A basic way of telling Store how to take your return data (string, or something else from your struct) and convert it into something genlist can use */
63typedef struct _Elm_Store_Item_Mapping_Empty Elm_Store_Item_Mapping_Empty; /**< An empty piece of mapping information. Useful for String labels as they get used directly */
64typedef struct _Elm_Store_Item_Mapping_Icon Elm_Store_Item_Mapping_Icon; /***< The data being mapped at the given address is an icon, so use these properties for finding it */
65typedef struct _Elm_Store_Item_Mapping_Photo Elm_Store_Item_Mapping_Photo; /**< The data is a photo, so use these parameters to find it */
66typedef struct _Elm_Store_Item_Mapping_Custom Elm_Store_Item_Mapping_Custom; /**> The item needs a custom mapping which means calling a function and returning a string from it, as opposed to a static lookup. It should not be allocated, and should live in a buffer in memory that survives the return of this function if its a label, or an allocated icon object if its an icon needed etc. */
67
68typedef Eina_Bool (*Elm_Store_Item_List_Cb)(void *data, Elm_Store_Item_Info *info); /**< Function to call for listing an item */
69typedef void (*Elm_Store_Item_Fetch_Cb)(void *data, Elm_Store_Item *sti); /**< Function to call to fetch item data */
70typedef void (*Elm_Store_Item_Unfetch_Cb)(void *data, Elm_Store_Item *sti); /**< Function to cal lto un-fetch (free) an item */
71typedef void *(*Elm_Store_Item_Mapping_Cb)(void *data, Elm_Store_Item *sti, const char *part); /**< Custom mapping function to call */
72
73typedef enum
74{
75 ELM_STORE_ITEM_MAPPING_NONE = 0,
76 ELM_STORE_ITEM_MAPPING_LABEL, /**< const char * -> label */
77 ELM_STORE_ITEM_MAPPING_STATE, /**< Eina_Bool -> state */
78 ELM_STORE_ITEM_MAPPING_ICON, /**< char * -> icon path */
79 ELM_STORE_ITEM_MAPPING_PHOTO, /**< char * -> photo path */
80 ELM_STORE_ITEM_MAPPING_CUSTOM, /**< item->custom(it->data, it, part) -> void * (-> any) */
81 ELM_STORE_ITEM_MAPPING_LAST
82} Elm_Store_Item_Mapping_Type;
83
84struct _Elm_Store_Item_Mapping_Icon
85{
86 int w, h; /**< The desired icon size in addition to the file path returned from the mapping */
87 Elm_Icon_Lookup_Order lookup_order; /**< The order in which to find the icon */
88 Eina_Bool standard_name : 1; /**< Use a standard name to find it (EINA_TRUE) or not */
89 Eina_Bool no_scale : 1; /**< EINA_TRUE is you don't want the icon scaled */
90 Eina_Bool smooth : 1; /**< EINA_TRUE if icon is to be smooth scaled */
91 Eina_Bool scale_up : 1; /**< EINA_TRUE if scaling up is allowed */
92 Eina_Bool scale_down : 1; /**< EINA_TRUE if scaling down is allowed */
93};
94
95struct _Elm_Store_Item_Mapping_Empty
96{
97 Eina_Bool dummy; /**< dummy entry - set to anything you like */
98};
99
100struct _Elm_Store_Item_Mapping_Photo
101{
102 int size; /**< Photo size to use (see elm_photo_add()) with the given photo path */
103};
104
105struct _Elm_Store_Item_Mapping_Custom
106{
107 Elm_Store_Item_Mapping_Cb func; /**< The function called to do the custom mapping and return it */
108};
109
110struct _Elm_Store_Item_Mapping
111{
112 Elm_Store_Item_Mapping_Type type; /**< what kind of mapping is this */
113 const char *part; /**< what part name in the genlist item is this filling in */
114 int offset; /**< offset in memory (in bytes) relative to base of structure for item data where the data for the mapping lives */
115 union
116 {
117 Elm_Store_Item_Mapping_Empty empty;
118 Elm_Store_Item_Mapping_Icon icon;
119 Elm_Store_Item_Mapping_Photo photo;
120 Elm_Store_Item_Mapping_Custom custom;
121 // add more types here
122 } details; /**< Allowed to be one of these possible mapping types */
123};
124
125struct _Elm_Store_Item_Info
126{
127 Elm_Genlist_Item_Class *item_class; /**< The genlist item class that should be used for the item that has been listed */
128 const Elm_Store_Item_Mapping *mapping; /**< What kind of mappings do we use for the fields of this item to fill in the genlist item. Terminate array pointed to here with ELM_STORE_ITEM_MAPPING_END */
129 void *data; /**< Pointer to pass to struct data in memory if its already there, of not, NULL */
130 char *sort_id; /**< Sort ID string (strduped()) to know how to wort items, or NULL, if you don't care */
131};
132
133struct _Elm_Store_Item_Info_Filesystem
134{
135 Elm_Store_Item_Info base; /**< Base information about an item */
136 char *path; /**< Extra information specific to the filesystem store */
137};
138
139#define ELM_STORE_ITEM_MAPPING_END { ELM_STORE_ITEM_MAPPING_NONE, NULL, 0, { .empty = { EINA_TRUE } } } /**< Use this to end a list of mappings */
140#define ELM_STORE_ITEM_MAPPING_OFFSET(st, it) offsetof(st, it) /**< Use this to get the offset in bytes in memory for where the data for the mapping lives relative to the item data (a private struct pointed to owned by the user */
141
142/**
143 * Create a new store object
144 *
145 * This creates a new store object to then configure so it works.
146 *
147 * @return A new store object, or NULL if creation fails
148 *
149 * @ingroup Store
150 */
151EAPI Elm_Store *elm_store_filesystem_new(void);
152/**
153 * Free the store object and all items it manages
154 *
155 * This frees the given @p st store and all the items it manages. It will
156 * clear the List that it populated, but otherwise leave it alone. It will
157 * cancel background threads (and may have to wait for them to complete a
158 * pending operation to do this).
159 *
160 * @param st The store to free
161 *
162 * @ingroup Store
163 */
164EAPI void elm_store_free(Elm_Store *st);
165
166/**
167 * Set the path to the directory to scan for a filesystem store
168 *
169 * This sets the directory (@p dir) to scan and begins scanning in the
170 * the background in threads (or not if threading is disabled with
171 * elm_store_fetch_thread_set()). Note that Listing is always done in a thread
172 * but fetching may not be if disabled here. This should be the last thing
173 * called after fetch, list and unfetch functions are set, as well as target
174 * genlist etc. You also should not change the directory once set. If you
175 * need a new directory scanned, create a new store.
176 *
177 * @param st The store to modify
178 * @param dir A string giving the path to the directory to scan
179 *
180 * @ingroup Store
181 */
182EAPI void elm_store_filesystem_directory_set(Elm_Store *st, const char *dir);
183
184/**
185 * Get the directory set on a filesystem store
186 *
187 * This gets the directory set by elm_store_filesystem_directory_set(). This
188 * string returned will be valid until elm_store_filesystem_directory_set()
189 * changes it or until the store is freed with elm_store_free().
190 *
191 * @return A string with the path set, or NULL if none set.
192 *
193 * @ingroup Store
194 */
195EAPI const char *elm_store_filesystem_directory_get(const Elm_Store *st);
196
197/**
198 * Get the path of a specific store item
199 *
200 * This returns the full path of a store item. This string is valid only
201 * during the list function set by elm_store_list_func_set() or during the
202 * fetch function set by elm_store_fetch_func_set() or during the unfetch
203 * function set by elm_store_unfetch_func_set().
204 *
205 * @param sti The store item to get the path from
206 * @return A full path in a string or NULL if none available
207 *
208 * @ingroup Store
209 */
210EAPI const char *elm_store_item_filesystem_path_get(const Elm_Store_Item *sti);
211
212/**
213 * Set the target genlist to fill in from the store
214 *
215 * This tells the store the target genlist to use to fill in content from
216 * the store. Once a store starts "going" via elm_store_filesystem_directory_set()
217 * The target should never be changed again.
218 *
219 * @param st The store to do the filling.
220 * @param obj The genlist object to fill in and control the content of from the store.
221 *
222 * @ingroup Store
223 */
224EAPI void elm_store_target_genlist_set(Elm_Store *st, Evas_Object *obj);
225
226/**
227 * Set the maximum number of items that are not visible to keep cached
228 *
229 * Store may keep some items around for caching purposes that cannot be seen,
230 * so this controls the maximum number. The default is 128, but may change
231 * at any point in time in the future.
232 *
233 * @param st The store to modify
234 * @param max The number of items to keep (should be greater than or equal to 0)
235 *
236 * @ingroup Store
237 */
238EAPI void elm_store_cache_set(Elm_Store *st, int max);
239
240/**
241 * Get the maximum number if items to cache
242 *
243 * This returns the number of items at most to cache.
244 *
245 * @param st The store to query
246 * @return The maximum number of items to cache (>= 0)
247 * @see elm_store_cache_set()
248 *
249 * @ingroup Store
250 */
251EAPI int elm_store_cache_get(const Elm_Store *st);
252
253/**
254 * Set the function used to deal with listing of items
255 *
256 * This function is called per item that is found so it can examine the item
257 * and discard it (return EINA_FALSE to discard, or EINA_TRUE to accept), and
258 * work out some sorting ID (that may be filename or anything else based on
259 * content). This function is always called from a thread.
260 *
261 * @param st The store to set the function of
262 * @param func The function to be called
263 * @param data the data pointer to be passed to the @p func function when called
264 *
265 * @ingroup Store
266 */
267EAPI void elm_store_list_func_set(Elm_Store *st, Elm_Store_Item_List_Cb func, const void *data);
268
269/**
270 * Set the function used to deal with fetching of items
271 *
272 * This function is called per item that needs data to be fetched when it
273 * becomes visible and such data is needed. This function is normally run
274 * from a thread (unless elm_store_fetch_thread_set() disables this). The
275 * fetch function is to read data from the source and fill a structure
276 * allocated for this item with fields and then rely on the mapping setup
277 * to tell Store how to take a field in the structure and apply it to a
278 * genlist item.
279 *
280 * @param st The store to set the function of
281 * @param func The function to be called
282 * @param data the data pointer to be passed to the @p func function when called
283 *
284 * @ingroup Store
285 */
286EAPI void elm_store_fetch_func_set(Elm_Store *st, Elm_Store_Item_Fetch_Cb func, const void *data);
287
288/**
289 * Set the function used to free the structure allocated for the item
290 *
291 * This function is called per item when it is not needed in memory anymore
292 * and should free the structure allocated in and filled in the function set
293 * by elm_store_fetch_func_set().
294 *
295 * @param st The store to set the function of
296 * @param func The function to be called
297 * @param data the data pointer to be passed to the @p func function when called
298 *
299 * @ingroup Store
300 */
301EAPI void elm_store_unfetch_func_set(Elm_Store *st, Elm_Store_Item_Unfetch_Cb func, const void *data);
302
303/**
304 * Enable or disable fetching in a thread for Store
305 *
306 * @param st The store to modify
307 * @param use_thread EINA_TRUE to use a thread to fetch, EINA_FALSE don't use a thread.
308 *
309 * @ingroup Store
310 */
311EAPI void elm_store_fetch_thread_set(Elm_Store *st, Eina_Bool use_thread);
312
313/**
314 * Get the thread enabled fetching option for Store
315 *
316 * @return The state set currently for the store.
317 * @see elm_store_fetch_thread_set()
318 *
319 * @ingroup Store
320 */
321EAPI Eina_Bool elm_store_fetch_thread_get(const Elm_Store *st);
322
323/**
324 * Set if items are to be sorted or not.
325 *
326 * By default items are not sorted, but read "in order" as they are found. If
327 * you want to sort, your list function set by elm_store_list_func_set() must
328 * provide a sort ID to sort by, and then Store will take care of sorting when
329 * it inserts items. You should set this up before you begin listing items
330 * in the store and then never change it again.
331 *
332 * @param st The store to modify
333 * @param sorted EINA_TRUE if we are to sort, EINA_FALSE if not.
334 *
335 * @ingroup Store
336 */
337EAPI void elm_store_sorted_set(Elm_Store *st, Eina_Bool sorted);
338
339/**
340 * Get the sorting flag
341 *
342 * Get the sorted flag as set by elm_store_sorted_set().
343 *
344 * @param st The store to query
345 * @return EINA_TRUE if sorted, EINA_FALSE if not.
346 *
347 * @ingroup Store
348 */
349EAPI Eina_Bool elm_store_sorted_get(const Elm_Store *st);
350
351/**
352 * Set the item data holding item fields to map to item values in genlist
353 *
354 * Once you decode an item, allocate a structure for it and fill the structure,
355 * you should set the item data with this function (eg in the fetch function).
356 * This item pointer is the base offset to use when mapping fields to item
357 * values. Once you unfetch, store will handle NULLing the data pointer for you.
358 *
359 * @param sti The store item to set the data pointer of
360 * @param data The data pointer to set.
361 *
362 * @ingroup Store
363 */
364EAPI void elm_store_item_data_set(Elm_Store_Item *sti, void *data);
365
366/**
367 * Get the item data
368 *
369 * This gets the data pointer set by elm_store_item_data_set().
370 *
371 * @param sti The store item to query
372 * @return The data pointer set on the item
373 *
374 * @ingroup Store
375 */
376EAPI void *elm_store_item_data_get(Elm_Store_Item *sti);
377
378/**
379 * Fetch the store than a store item belongs to
380 *
381 * This fetches the store object that owns the store item.
382 *
383 * @param sti The store item to query
384 * @return The store the item belongs to
385 *
386 * @ingroup Store
387 */
388EAPI const Elm_Store *elm_store_item_store_get(const Elm_Store_Item *sti);
389
390/**
391 * Fetch the genlist item that this store item controls
392 *
393 * @param sti The store item to query
394 * @return The genlist object item handle controlled by this store item
395 *
396 * @ingroup Store
397 */
398EAPI const Elm_Object_Item *elm_store_item_genlist_item_get(const Elm_Store_Item *sti);
399
400/**
401 * @}
402 */
diff --git a/libraries/elementary/src/lib/elm_table.c b/libraries/elementary/src/lib/elm_table.c
new file mode 100644
index 0000000..532ccf4
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_table.c
@@ -0,0 +1,243 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Widget_Data Widget_Data;
5
6struct _Widget_Data
7{
8 Evas_Object *tbl;
9};
10
11static const char *widtype = NULL;
12static void _del_hook(Evas_Object *obj);
13static void _sizing_eval(Evas_Object *obj);
14static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
15static void _sub_del(void *data, Evas_Object *obj, void *event_info);
16static void _theme_hook(Evas_Object *obj);
17
18static void
19_del_pre_hook(Evas_Object *obj)
20{
21 Widget_Data *wd = elm_widget_data_get(obj);
22 if (!wd) return;
23 evas_object_event_callback_del_full
24 (wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
25 evas_object_del(wd->tbl);
26}
27
28static void
29_del_hook(Evas_Object *obj)
30{
31 Widget_Data *wd = elm_widget_data_get(obj);
32 if (!wd) return;
33 free(wd);
34}
35
36static Eina_Bool
37_elm_table_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
38{
39 Widget_Data *wd = elm_widget_data_get(obj);
40 const Eina_List *items;
41 void *(*list_data_get) (const Eina_List *list);
42 Eina_List *(*list_free) (Eina_List *list);
43
44 if ((!wd) || (!wd->tbl))
45 return EINA_FALSE;
46
47 /* Focus chain */
48 /* TODO: Change this to use other chain */
49 if ((items = elm_widget_focus_custom_chain_get(obj)))
50 {
51 list_data_get = eina_list_data_get;
52 list_free = NULL;
53 }
54 else
55 {
56 items = evas_object_table_children_get(wd->tbl);
57 list_data_get = eina_list_data_get;
58 list_free = eina_list_free;
59
60 if (!items) return EINA_FALSE;
61 }
62
63 Eina_Bool ret = elm_widget_focus_list_next_get(obj, items, list_data_get,
64 dir, next);
65
66 if (list_free)
67 list_free((Eina_List *)items);
68
69 return ret;
70}
71
72static void
73_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
74{
75 Widget_Data *wd = elm_widget_data_get(obj);
76 if ((!wd) || (!wd->tbl))
77 return;
78
79 evas_object_table_mirrored_set(wd->tbl, rtl);
80}
81
82static void
83_theme_hook(Evas_Object *obj)
84{
85 _elm_widget_mirrored_reload(obj);
86 _mirrored_set(obj, elm_widget_mirrored_get(obj));
87}
88
89static void
90_sizing_eval(Evas_Object *obj)
91{
92 Widget_Data *wd = elm_widget_data_get(obj);
93 Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
94 Evas_Coord w, h;
95 if (!wd) return;
96 evas_object_size_hint_min_get(wd->tbl, &minw, &minh);
97 evas_object_size_hint_max_get(wd->tbl, &maxw, &maxh);
98 evas_object_size_hint_min_set(obj, minw, minh);
99 evas_object_size_hint_max_set(obj, maxw, maxh);
100 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
101 if (w < minw) w = minw;
102 if (h < minh) h = minh;
103 if ((maxw >= 0) && (w > maxw)) w = maxw;
104 if ((maxh >= 0) && (h > maxh)) h = maxh;
105 evas_object_resize(obj, w, h);
106}
107
108static void
109_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
110{
111 _sizing_eval(data);
112}
113
114static void
115_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
116{
117 _sizing_eval(obj);
118}
119
120EAPI Evas_Object *
121elm_table_add(Evas_Object *parent)
122{
123 Evas_Object *obj;
124 Evas *e;
125 Widget_Data *wd;
126
127 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
128
129 ELM_SET_WIDTYPE(widtype, "table");
130 elm_widget_type_set(obj, "table");
131 elm_widget_sub_object_add(parent, obj);
132 elm_widget_data_set(obj, wd);
133 elm_widget_del_hook_set(obj, _del_hook);
134 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
135 elm_widget_focus_next_hook_set(obj, _elm_table_focus_next_hook);
136 elm_widget_can_focus_set(obj, EINA_FALSE);
137 elm_widget_highlight_ignore_set(obj, EINA_FALSE);
138 elm_widget_theme_hook_set(obj, _theme_hook);
139
140 wd->tbl = evas_object_table_add(e);
141 evas_object_event_callback_add(wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
142 _changed_size_hints, obj);
143 elm_widget_resize_object_set(obj, wd->tbl);
144
145 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
146
147 _mirrored_set(obj, elm_widget_mirrored_get(obj));
148 return obj;
149}
150
151EAPI void
152elm_table_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
153{
154 ELM_CHECK_WIDTYPE(obj, widtype);
155 Widget_Data *wd = elm_widget_data_get(obj);
156 if (!wd) return;
157 evas_object_table_homogeneous_set(wd->tbl, homogeneous);
158}
159
160EAPI Eina_Bool
161elm_table_homogeneous_get(const Evas_Object *obj)
162{
163 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
164 Widget_Data *wd = elm_widget_data_get(obj);
165 if (!wd) return EINA_FALSE;
166 return evas_object_table_homogeneous_get(wd->tbl);
167}
168
169EAPI void
170elm_table_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
171{
172 ELM_CHECK_WIDTYPE(obj, widtype);
173 Widget_Data *wd = elm_widget_data_get(obj);
174 if (!wd) return;
175 evas_object_table_padding_set(wd->tbl, horizontal, vertical);
176}
177
178EAPI void
179elm_table_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical)
180{
181 ELM_CHECK_WIDTYPE(obj, widtype);
182 Widget_Data *wd = elm_widget_data_get(obj);
183 if (!wd) return;
184 evas_object_table_padding_get(wd->tbl, horizontal, vertical);
185}
186
187EAPI void
188elm_table_pack(Evas_Object *obj, Evas_Object *subobj, int x, int y, int w, int h)
189{
190 ELM_CHECK_WIDTYPE(obj, widtype);
191 Widget_Data *wd = elm_widget_data_get(obj);
192 if (!wd) return;
193 elm_widget_sub_object_add(obj, subobj);
194 evas_object_table_pack(wd->tbl, subobj, x, y, w, h);
195}
196
197EAPI void
198elm_table_unpack(Evas_Object *obj, Evas_Object *subobj)
199{
200 ELM_CHECK_WIDTYPE(obj, widtype);
201 Widget_Data *wd = elm_widget_data_get(obj);
202 if (!wd) return;
203 elm_widget_sub_object_del(obj, subobj);
204 evas_object_table_unpack(wd->tbl, subobj);
205}
206
207EAPI void
208elm_table_pack_set(Evas_Object *subobj, int x, int y, int w, int h)
209{
210 Evas_Object *obj = elm_widget_parent_widget_get(subobj);
211 ELM_CHECK_WIDTYPE(obj, widtype);
212 Widget_Data *wd = elm_widget_data_get(obj);
213 if (!wd) return;
214 evas_object_table_pack(wd->tbl, subobj, x, y, w, h);
215}
216
217EAPI void
218elm_table_pack_get(Evas_Object *subobj, int *x, int *y, int *w, int *h)
219{
220 Evas_Object *obj = elm_widget_parent_widget_get(subobj);
221 unsigned short ix, iy, iw, ih;
222 ELM_CHECK_WIDTYPE(obj, widtype);
223 Widget_Data *wd = elm_widget_data_get(obj);
224 if (!wd) return;
225 evas_object_table_pack_get(wd->tbl, subobj, &ix, &iy, &iw, &ih);
226 if (x) *x = ix;
227 if (y) *y = iy;
228 if (w) *w = iw;
229 if (h) *h = ih;
230}
231
232EAPI void
233elm_table_clear(Evas_Object *obj, Eina_Bool clear)
234{
235 Eina_List *chld;
236 Evas_Object *o;
237 ELM_CHECK_WIDTYPE(obj, widtype);
238 Widget_Data *wd = elm_widget_data_get(obj);
239 if (!wd) return;
240 chld = evas_object_table_children_get(wd->tbl);
241 EINA_LIST_FREE(chld, o) elm_widget_sub_object_del(obj, o);
242 evas_object_table_clear(wd->tbl, clear);
243}
diff --git a/libraries/elementary/src/lib/elm_table.h b/libraries/elementary/src/lib/elm_table.h
new file mode 100644
index 0000000..ceffc86
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_table.h
@@ -0,0 +1,159 @@
1/**
2 * @defgroup Table Table
3 * @ingroup Elementary
4 *
5 * A container widget to arrange other widgets in a table where items can
6 * span multiple columns or rows - even overlap (and then be raised or
7 * lowered accordingly to adjust stacking if they do overlap).
8 *
9 * The row and column count is not fixed. The table widget adjusts itself when
10 * subobjects are added to it dynamically.
11 *
12 * The most common way to use a table is:
13 * @code
14 * table = elm_table_add(win);
15 * evas_object_show(table);
16 * elm_table_padding_set(table, space_between_columns, space_between_rows);
17 * elm_table_pack(table, table_content_object, x_coord, y_coord, colspan, rowspan);
18 * elm_table_pack(table, table_content_object, next_x_coord, next_y_coord, colspan, rowspan);
19 * elm_table_pack(table, table_content_object, other_x_coord, other_y_coord, colspan, rowspan);
20 * @endcode
21 *
22 * The following are examples of how to use a table:
23 * @li @ref tutorial_table_01
24 * @li @ref tutorial_table_02
25 *
26 * @{
27 */
28
29/**
30 * @brief Add a new table to the parent
31 *
32 * @param parent The parent object
33 * @return The new object or NULL if it cannot be created
34 *
35 * @ingroup Table
36 */
37EAPI Evas_Object *elm_table_add(Evas_Object *parent);
38
39/**
40 * @brief Set the homogeneous layout in the table
41 *
42 * @param obj The layout object
43 * @param homogeneous A boolean to set if the layout is homogeneous in the
44 * table (EINA_TRUE = homogeneous, EINA_FALSE = no homogeneous)
45 *
46 * @ingroup Table
47 */
48EAPI void elm_table_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous);
49
50/**
51 * @brief Get the current table homogeneous mode.
52 *
53 * @param obj The table object
54 * @return A boolean to indicating if the layout is homogeneous in the table
55 * (EINA_TRUE = homogeneous, EINA_FALSE = no homogeneous)
56 *
57 * @ingroup Table
58 */
59EAPI Eina_Bool elm_table_homogeneous_get(const Evas_Object *obj);
60
61/**
62 * @brief Set padding between cells.
63 *
64 * @param obj The layout object.
65 * @param horizontal set the horizontal padding.
66 * @param vertical set the vertical padding.
67 *
68 * Default value is 0.
69 *
70 * @ingroup Table
71 */
72EAPI void elm_table_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical);
73
74/**
75 * @brief Get padding between cells.
76 *
77 * @param obj The layout object.
78 * @param horizontal set the horizontal padding.
79 * @param vertical set the vertical padding.
80 *
81 * @ingroup Table
82 */
83EAPI void elm_table_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical);
84
85/**
86 * @brief Add a subobject on the table with the coordinates passed
87 *
88 * @param obj The table object
89 * @param subobj The subobject to be added to the table
90 * @param x Row number
91 * @param y Column number
92 * @param w colspan
93 * @param h rowspan
94 *
95 * @note All positioning inside the table is relative to rows and columns, so
96 * a value of 0 for x and y, means the top left cell of the table, and a
97 * value of 1 for w and h means @p subobj only takes that 1 cell.
98 *
99 * @ingroup Table
100 */
101EAPI void elm_table_pack(Evas_Object *obj, Evas_Object *subobj, int x, int y, int w, int h);
102
103/**
104 * @brief Remove child from table.
105 *
106 * @param obj The table object
107 * @param subobj The subobject
108 *
109 * @ingroup Table
110 */
111EAPI void elm_table_unpack(Evas_Object *obj, Evas_Object *subobj);
112
113/**
114 * @brief Faster way to remove all child objects from a table object.
115 *
116 * @param obj The table object
117 * @param clear If true, will delete children, else just remove from table.
118 *
119 * @ingroup Table
120 */
121EAPI void elm_table_clear(Evas_Object *obj, Eina_Bool clear);
122
123/**
124 * @brief Set the packing location of an existing child of the table
125 *
126 * @param subobj The subobject to be modified in the table
127 * @param x Row number
128 * @param y Column number
129 * @param w rowspan
130 * @param h colspan
131 *
132 * Modifies the position of an object already in the table.
133 *
134 * @note All positioning inside the table is relative to rows and columns, so
135 * a value of 0 for x and y, means the top left cell of the table, and a
136 * value of 1 for w and h means @p subobj only takes that 1 cell.
137 *
138 * @ingroup Table
139 */
140EAPI void elm_table_pack_set(Evas_Object *subobj, int x, int y, int w, int h);
141
142/**
143 * @brief Get the packing location of an existing child of the table
144 *
145 * @param subobj The subobject to be modified in the table
146 * @param x Row number
147 * @param y Column number
148 * @param w rowspan
149 * @param h colspan
150 *
151 * @see elm_table_pack_set()
152 *
153 * @ingroup Table
154 */
155EAPI void elm_table_pack_get(Evas_Object *subobj, int *x, int *y, int *w, int *h);
156
157/**
158 * @}
159 */
diff --git a/libraries/elementary/src/lib/elm_theme.c b/libraries/elementary/src/lib/elm_theme.c
new file mode 100644
index 0000000..a0caea2
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_theme.c
@@ -0,0 +1,706 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_icon.h"
4
5static Elm_Theme theme_default =
6{
7 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1
8};
9
10static Eina_List *themes = NULL;
11
12static void
13_elm_theme_clear(Elm_Theme *th)
14{
15 const char *p;
16 EINA_LIST_FREE(th->themes, p)
17 eina_stringshare_del(p);
18 EINA_LIST_FREE(th->overlay, p)
19 eina_stringshare_del(p);
20 EINA_LIST_FREE(th->extension, p)
21 eina_stringshare_del(p);
22 if (th->cache)
23 {
24 eina_hash_free(th->cache);
25 th->cache = NULL;
26 }
27 if (th->cache_data)
28 {
29 eina_hash_free(th->cache_data);
30 th->cache_data = NULL;
31 }
32 if (th->theme)
33 {
34 eina_stringshare_del(th->theme);
35 th->theme = NULL;
36 }
37 if (th->ref_theme)
38 {
39 th->ref_theme->referrers =
40 eina_list_remove(th->ref_theme->referrers, th);
41 elm_theme_free(th->ref_theme);
42 th->ref_theme = NULL;
43 }
44}
45
46static const char *
47_elm_theme_find_try(Elm_Theme *th, const char *f, const char *group)
48{
49 const char *file;
50
51 if (edje_file_group_exists(f, group))
52 {
53 file = eina_stringshare_add(f);
54 if (file)
55 {
56 eina_hash_add(th->cache, group, file);
57 return file;
58 }
59 }
60 return NULL;
61}
62
63static const char *
64_elm_theme_theme_element_try(Elm_Theme *th, const char *home, const char *f, const char *group)
65{
66 char buf[PATH_MAX];
67 const char *file = NULL;
68
69 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
70 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
71 ((isalpha(f[0])) && (f[1] == ':')))
72 return _elm_theme_find_try(th, f, group);
73 else if (((f[0] == '~') && (f[1] == '/')))
74 {
75 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
76 return _elm_theme_find_try(th, buf, group);
77 }
78 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
79 file = _elm_theme_find_try(th, buf, group);
80 if (file) return file;
81 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
82 file = _elm_theme_find_try(th, buf, group);
83 return file;
84}
85
86static const char *
87_elm_theme_group_file_find(Elm_Theme *th, const char *group)
88{
89 const Eina_List *l;
90 const char *f;
91 static const char *home = NULL;
92 const char *file = eina_hash_find(th->cache, group);
93
94 if (file) return file;
95 if (!home)
96 {
97 home = getenv("HOME");
98 if (!home) home = "";
99 }
100 EINA_LIST_FOREACH(th->overlay, l, f)
101 {
102 file = _elm_theme_theme_element_try(th, home, f, group);
103 if (file) return file;
104 }
105 EINA_LIST_FOREACH(th->themes, l, f)
106 {
107 file = _elm_theme_theme_element_try(th, home, f, group);
108 if (file) return file;
109 }
110 EINA_LIST_FOREACH(th->extension, l, f)
111 {
112 file = _elm_theme_theme_element_try(th, home, f, group);
113 if (file) return file;
114 }
115 if (th->ref_theme) return _elm_theme_group_file_find(th->ref_theme, group);
116 return NULL;
117}
118
119static const char *
120_elm_theme_find_data_try(Elm_Theme *th, const char *f, const char *key)
121{
122 char *data;
123 const char *t;
124
125 data = edje_file_data_get(f, key);
126 t = eina_stringshare_add(data);
127 free(data);
128 if (t)
129 {
130 eina_hash_add(th->cache, key, t);
131 return t;
132 }
133 return NULL;
134}
135
136static const char *
137_elm_theme_theme_data_try(Elm_Theme *th, const char *home, const char *f, const char *key)
138{
139 char buf[PATH_MAX];
140 const char *data = NULL;
141
142 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
143 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
144 ((isalpha(f[0])) && (f[1] == ':')))
145 return _elm_theme_find_data_try(th, f, key);
146 else if (((f[0] == '~') && (f[1] == '/')))
147 {
148 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
149 return _elm_theme_find_try(th, buf, key);
150 }
151 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
152 data = _elm_theme_find_data_try(th, buf, key);
153 if (data) return data;
154 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
155 data = _elm_theme_find_data_try(th, buf, key);
156 return data;
157}
158
159static const char *
160_elm_theme_data_find(Elm_Theme *th, const char *key)
161{
162 const Eina_List *l;
163 const char *f;
164 static const char *home = NULL;
165 const char *data = eina_hash_find(th->cache_data, key);
166
167 if (data) return data;
168 if (!home)
169 {
170 home = getenv("HOME");
171 if (!home) home = "";
172 }
173 EINA_LIST_FOREACH(th->overlay, l, f)
174 {
175 data = _elm_theme_theme_data_try(th, home, f, key);
176 if (data) return data;
177 }
178 EINA_LIST_FOREACH(th->themes, l, f)
179 {
180 data = _elm_theme_theme_data_try(th, home, f, key);
181 if (data) return data;
182 }
183 EINA_LIST_FOREACH(th->extension, l, f)
184 {
185 data = _elm_theme_theme_data_try(th, home, f, key);
186 if (data) return data;
187 }
188 if (th->ref_theme) return _elm_theme_data_find(th->ref_theme, key);
189 return NULL;
190}
191
192Eina_Bool
193_elm_theme_object_set(Evas_Object *parent, Evas_Object *o, const char *clas, const char *group, const char *style)
194{
195 Elm_Theme *th = NULL;
196 if (parent) th = elm_widget_theme_get(parent);
197 return _elm_theme_set(th, o, clas, group, style);
198}
199
200Eina_Bool
201_elm_theme_object_icon_set(Evas_Object *parent, Evas_Object *o, const char *group, const char *style)
202{
203 Elm_Theme *th = NULL;
204 if (parent) th = elm_widget_theme_get(parent);
205 return _elm_theme_icon_set(th, o, group, style);
206}
207
208Eina_Bool
209_elm_theme_set(Elm_Theme *th, Evas_Object *o, const char *clas, const char *group, const char *style)
210{
211 const char *file;
212 char buf2[1024];
213 Eina_Bool ok;
214
215 if ((!clas) || (!group) || (!style)) return EINA_FALSE;
216 if (!th) th = &(theme_default);
217 snprintf(buf2, sizeof(buf2), "elm/%s/%s/%s", clas, group, style);
218 file = _elm_theme_group_file_find(th, buf2);
219 if (file)
220 {
221 ok = edje_object_file_set(o, file, buf2);
222 if (ok) return EINA_TRUE;
223 else
224 DBG("could not set theme group '%s' from file '%s': %s",
225 buf2, file, edje_load_error_str(edje_object_load_error_get(o)));
226 }
227 snprintf(buf2, sizeof(buf2), "elm/%s/%s/default", clas, group);
228 file = _elm_theme_group_file_find(th, buf2);
229 if (!file) return EINA_FALSE;
230 ok = edje_object_file_set(o, file, buf2);
231 if (!ok)
232 DBG("could not set theme group '%s' from file '%s': %s",
233 buf2, file, edje_load_error_str(edje_object_load_error_get(o)));
234 return ok;
235}
236
237Eina_Bool
238_elm_theme_icon_set(Elm_Theme *th, Evas_Object *o, const char *group, const char *style)
239{
240 const char *file;
241 char buf2[1024];
242 int w, h;
243
244 if (!th) th = &(theme_default);
245 snprintf(buf2, sizeof(buf2), "elm/icon/%s/%s", group, style);
246 file = _elm_theme_group_file_find(th, buf2);
247 if (file)
248 {
249 _els_smart_icon_file_edje_set(o, file, buf2);
250 _els_smart_icon_size_get(o, &w, &h);
251 if (w > 0) return EINA_TRUE;
252 }
253 snprintf(buf2, sizeof(buf2), "elm/icon/%s/default", group);
254 file = _elm_theme_group_file_find(th, buf2);
255 if (!file) return EINA_FALSE;
256 _els_smart_icon_file_edje_set(o, file, buf2);
257 _els_smart_icon_size_get(o, &w, &h);
258 return (w > 0);
259}
260
261Eina_Bool
262_elm_theme_parse(Elm_Theme *th, const char *theme)
263{
264 Eina_List *names = NULL;
265 const char *p, *pe;
266
267 if (!th) th = &(theme_default);
268 if (theme)
269 {
270 p = theme;
271 pe = p;
272 for (;;)
273 {
274 if ((*pe == ':') || (!*pe))
275 { // p -> pe == 'name:'
276 if (pe > p)
277 {
278 char *n = malloc(pe - p + 1);
279 if (n)
280 {
281 const char *nn;
282
283 strncpy(n, p, pe - p);
284 n[pe - p] = 0;
285 nn = eina_stringshare_add(n);
286 if (nn) names = eina_list_append(names, nn);
287 free(n);
288 }
289 }
290 if (!*pe) break;
291 p = pe + 1;
292 pe = p;
293 }
294 else
295 pe++;
296 }
297 }
298 p = eina_list_data_get(eina_list_last(names));
299 if ((!p) || ((p) && (strcmp(p, "default"))))
300 {
301 p = eina_stringshare_add("default");
302 if (p) names = eina_list_append(names, p);
303 }
304 if (th->cache) eina_hash_free(th->cache);
305 th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
306 if (th->cache_data) eina_hash_free(th->cache_data);
307 th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
308
309 EINA_LIST_FREE(th->themes, p) eina_stringshare_del(p);
310
311 th->themes = names;
312 return EINA_TRUE;
313}
314
315void
316_elm_theme_shutdown(void)
317{
318 _elm_theme_clear(&(theme_default));
319}
320
321EAPI Elm_Theme *
322elm_theme_new(void)
323{
324 Elm_Theme *th = calloc(1, sizeof(Elm_Theme));
325 if (!th) return NULL;
326 th->ref = 1;
327 th->themes = eina_list_append(th->themes, eina_stringshare_add("default"));
328 themes = eina_list_append(themes, th);
329 return th;
330}
331
332EAPI void
333elm_theme_free(Elm_Theme *th)
334{
335 EINA_SAFETY_ON_NULL_RETURN(th);
336 th->ref--;
337 if (th->ref < 1)
338 {
339 _elm_theme_clear(th);
340 themes = eina_list_remove(themes, th);
341 free(th);
342 }
343}
344
345EAPI void
346elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst)
347{
348 const Eina_List *l;
349 const char *f;
350
351 if (!th) th = &(theme_default);
352 if (!thdst) thdst = &(theme_default);
353 _elm_theme_clear(thdst);
354 if (th->ref_theme)
355 {
356 thdst->ref_theme = th->ref_theme;
357 thdst->ref_theme->referrers =
358 eina_list_append(thdst->ref_theme->referrers, thdst);
359 thdst->ref_theme->ref++;
360 }
361 EINA_LIST_FOREACH(th->overlay, l, f)
362 {
363 const char *s = eina_stringshare_add(f);
364 if (s) thdst->overlay = eina_list_append(thdst->overlay, s);
365 }
366 EINA_LIST_FOREACH(th->themes, l, f)
367 {
368 const char *s = eina_stringshare_add(f);
369 if (s) thdst->themes = eina_list_append(thdst->themes, s);
370 }
371 EINA_LIST_FOREACH(th->extension, l, f)
372 {
373 const char *s = eina_stringshare_add(f);
374 if (s) thdst->extension = eina_list_append(thdst->extension, s);
375 }
376 if (th->theme) thdst->theme = eina_stringshare_add(th->theme);
377 elm_theme_flush(thdst);
378}
379
380EAPI void
381elm_theme_ref_set(Elm_Theme *th, Elm_Theme *thref)
382{
383 if (!th) th = &(theme_default);
384 if (!thref) thref = &(theme_default);
385 if (th->ref_theme == thref) return;
386 _elm_theme_clear(th);
387 if (thref)
388 {
389 thref->referrers = eina_list_append(thref->referrers, th);
390 thref->ref++;
391 }
392 th->ref_theme = thref;
393 elm_theme_flush(th);
394}
395
396EAPI Elm_Theme *
397elm_theme_ref_get(Elm_Theme *th)
398{
399 if (!th) th = &(theme_default);
400 return th->ref_theme;
401}
402
403EAPI Elm_Theme *
404elm_theme_default_get(void)
405{
406 return &theme_default;
407}
408
409EAPI void
410elm_theme_overlay_add(Elm_Theme *th, const char *item)
411{
412 const char *f = eina_stringshare_add(item);
413
414 if (!th) th = &(theme_default);
415 if (f) th->overlay = eina_list_prepend(th->overlay, f);
416 elm_theme_flush(th);
417}
418
419EAPI void
420elm_theme_overlay_del(Elm_Theme *th, const char *item)
421{
422 const Eina_List *l;
423 const char *f, *s;
424
425 if (!th) th = &(theme_default);
426 s = eina_stringshare_add(item);
427 EINA_LIST_FOREACH(th->overlay, l, f)
428 if (f == s)
429 {
430 eina_stringshare_del(f);
431 th->overlay = eina_list_remove_list(th->overlay, (Eina_List *)l);
432 break;
433 }
434 eina_stringshare_del(s);
435 elm_theme_flush(th);
436}
437
438EAPI const Eina_List *
439elm_theme_overlay_list_get(const Elm_Theme *th)
440{
441 if (!th) th = &(theme_default);
442 return th->overlay;
443}
444
445EAPI void
446elm_theme_extension_add(Elm_Theme *th, const char *item)
447{
448 const char *f = eina_stringshare_add(item);
449
450 if (!th) th = &(theme_default);
451 if (f) th->extension = eina_list_append(th->extension, f);
452 elm_theme_flush(th);
453}
454
455EAPI void
456elm_theme_extension_del(Elm_Theme *th, const char *item)
457{
458 const Eina_List *l;
459 const char *f, *s;
460
461 if (!th) th = &(theme_default);
462 s = eina_stringshare_add(item);
463 EINA_LIST_FOREACH(th->extension, l, f)
464 if (f == s)
465 {
466 eina_stringshare_del(f);
467 th->extension = eina_list_remove_list(th->extension, (Eina_List *)l);
468 break;
469 }
470 eina_stringshare_del(s);
471 elm_theme_flush(th);
472}
473
474EAPI const Eina_List *
475elm_theme_extension_list_get(const Elm_Theme *th)
476{
477 if (!th) th = &(theme_default);
478 return th->extension;
479}
480
481EAPI void
482elm_theme_set(Elm_Theme *th, const char *theme)
483{
484 if (!th) th = &(theme_default);
485 _elm_theme_parse(th, theme);
486 if (th->theme)
487 {
488 eina_stringshare_del(th->theme);
489 th->theme = NULL;
490 }
491 elm_theme_flush(th);
492 if (th == &(theme_default))
493 eina_stringshare_replace(&_elm_config->theme, theme);
494}
495
496EAPI const char *
497elm_theme_get(Elm_Theme *th)
498{
499 if (!th) th = &(theme_default);
500 if (!th->theme)
501 {
502 Eina_List *l;
503 const char *f;
504 char *tmp;
505 int len;
506
507 len = 0;
508 EINA_LIST_FOREACH(th->themes, l, f)
509 {
510 len += strlen(f);
511 if (l->next) len += 1;
512 }
513 tmp = alloca(len + 1);
514 tmp[0] = 0;
515 EINA_LIST_FOREACH(th->themes, l, f)
516 {
517 strcat(tmp, f);
518 if (l->next) strcat(tmp, ":");
519 }
520 th->theme = eina_stringshare_add(tmp);
521 }
522 return th->theme;
523}
524
525EAPI const Eina_List *
526elm_theme_list_get(const Elm_Theme *th)
527{
528 if (!th) th = &(theme_default);
529 return th->themes;
530}
531
532EAPI char *
533elm_theme_list_item_path_get(const char *f, Eina_Bool *in_search_path)
534{
535 static const char *home = NULL;
536 char buf[PATH_MAX];
537
538 if (!f)
539 {
540 if (in_search_path) *in_search_path = EINA_FALSE;
541 return NULL;
542 }
543
544 if (!home)
545 {
546 home = getenv("HOME");
547 if (!home) home = "";
548 }
549
550 if ((f[0] == '/') || ((f[0] == '.') && (f[1] == '/')) ||
551 ((f[0] == '.') && (f[1] == '.') && (f[2] == '/')) ||
552 ((isalpha(f[0])) && (f[1] == ':')))
553 {
554 if (in_search_path) *in_search_path = EINA_FALSE;
555 return strdup(f);
556 }
557 else if (((f[0] == '~') && (f[1] == '/')))
558 {
559 if (in_search_path) *in_search_path = EINA_FALSE;
560 snprintf(buf, sizeof(buf), "%s/%s", home, f + 2);
561 return strdup(buf);
562 }
563 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s.edj", home, f);
564 if (ecore_file_exists(buf))
565 {
566 if (in_search_path) *in_search_path = EINA_TRUE;
567 return strdup(buf);
568 }
569
570 snprintf(buf, sizeof(buf), "%s/themes/%s.edj", _elm_data_dir, f);
571 if (ecore_file_exists(buf))
572 {
573 if (in_search_path) *in_search_path = EINA_TRUE;
574 return strdup(buf);
575 }
576
577 if (in_search_path) *in_search_path = EINA_FALSE;
578 return NULL;
579}
580
581EAPI void
582elm_theme_flush(Elm_Theme *th)
583{
584 if (!th) th = &(theme_default);
585 if (th->cache) eina_hash_free(th->cache);
586 th->cache = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
587 if (th->cache_data) eina_hash_free(th->cache_data);
588 th->cache_data = eina_hash_string_superfast_new(EINA_FREE_CB(eina_stringshare_del));
589 _elm_win_rescale(th, EINA_TRUE);
590 _elm_ews_wm_rescale(th, EINA_TRUE);
591 if (th->referrers)
592 {
593 Eina_List *l;
594 Elm_Theme *th2;
595
596 EINA_LIST_FOREACH(th->referrers, l, th2) elm_theme_flush(th2);
597 }
598}
599
600EAPI void
601elm_theme_full_flush(void)
602{
603 Eina_List *l;
604 Elm_Theme *th;
605
606 EINA_LIST_FOREACH(themes, l, th)
607 {
608 elm_theme_flush(th);
609 }
610 elm_theme_flush(&(theme_default));
611}
612
613EAPI Eina_List *
614elm_theme_name_available_list_new(void)
615{
616 Eina_List *list = NULL;
617 Eina_List *dir, *l;
618 char buf[PATH_MAX], *file, *s, *th;
619 static const char *home = NULL;
620
621 if (!home)
622 {
623 home = getenv("HOME");
624 if (!home) home = "";
625 }
626
627 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes", home);
628 dir = ecore_file_ls(buf);
629 EINA_LIST_FREE(dir, file)
630 {
631 snprintf(buf, sizeof(buf), "%s/"ELEMENTARY_BASE_DIR"/themes/%s", home, file);
632 if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
633 {
634 s = strchr(file, '.');
635 if ((s) && (!strcasecmp(s, ".edj")))
636 {
637 th = strdup(file);
638 s = strchr(th, '.');
639 *s = 0;
640 list = eina_list_append(list, th);
641 }
642 }
643 free(file);
644 }
645
646 snprintf(buf, sizeof(buf), "%s/themes", _elm_data_dir);
647 dir = ecore_file_ls(buf);
648 EINA_LIST_FREE(dir, file)
649 {
650 snprintf(buf, sizeof(buf), "%s/themes/%s", _elm_data_dir, file);
651 if ((!ecore_file_is_dir(buf)) && (ecore_file_size(buf) > 0))
652 {
653 s = strchr(file, '.');
654 if ((s) && (!strcasecmp(s, ".edj")))
655 {
656 int dupp;
657
658 th = strdup(file);
659 s = strchr(th, '.');
660 *s = 0;
661 dupp = 0;
662 EINA_LIST_FOREACH(list, l, s)
663 {
664 if (!strcmp(s, th))
665 {
666 dupp = 1;
667 break;
668 }
669 }
670 if (dupp) free(th);
671 else list = eina_list_append(list, th);
672 }
673 }
674 free(file);
675 }
676 list = eina_list_sort(list, 0, EINA_COMPARE_CB(strcasecmp));
677 return list;
678}
679
680EAPI void
681elm_theme_name_available_list_free(Eina_List *list)
682{
683 char *s;
684 EINA_LIST_FREE(list, s) free(s);
685}
686
687EAPI void
688elm_object_theme_set(Evas_Object *obj, Elm_Theme *th)
689{
690 EINA_SAFETY_ON_NULL_RETURN(obj);
691 elm_widget_theme_set(obj, th);
692}
693
694EAPI Elm_Theme *
695elm_object_theme_get(const Evas_Object *obj)
696{
697 EINA_SAFETY_ON_NULL_RETURN_VAL(obj, NULL);
698 return elm_widget_theme_get(obj);
699}
700
701EAPI const char *
702elm_theme_data_get(Elm_Theme *th, const char *key)
703{
704 if (!th) th = &(theme_default);
705 return _elm_theme_data_find(th, key);
706}
diff --git a/libraries/elementary/src/lib/elm_theme.h b/libraries/elementary/src/lib/elm_theme.h
new file mode 100644
index 0000000..10c5f6a
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_theme.h
@@ -0,0 +1,436 @@
1/**
2 * @defgroup Theme Theme
3 * @ingroup Elementary
4 *
5 * Elementary uses Edje to theme its widgets, naturally. But for the most
6 * part this is hidden behind a simpler interface that lets the user set
7 * extensions and choose the style of widgets in a much easier way.
8 *
9 * Instead of thinking in terms of paths to Edje files and their groups
10 * each time you want to change the appearance of a widget, Elementary
11 * works so you can add any theme file with extensions or replace the
12 * main theme at one point in the application, and then just set the style
13 * of widgets with elm_object_style_set() and related functions. Elementary
14 * will then look in its list of themes for a matching group and apply it,
15 * and when the theme changes midway through the application, all widgets
16 * will be updated accordingly.
17 *
18 * There are three concepts you need to know to understand how Elementary
19 * theming works: default theme, extensions and overlays.
20 *
21 * Default theme, obviously enough, is the one that provides the default
22 * look of all widgets. End users can change the theme used by Elementary
23 * by setting the @c ELM_THEME environment variable before running an
24 * application, or globally for all programs using the @c elementary_config
25 * utility. Applications can change the default theme using elm_theme_set(),
26 * but this can go against the user wishes, so it's not an advised practice.
27 *
28 * Ideally, applications should find everything they need in the already
29 * provided theme, but there may be occasions when that's not enough and
30 * custom styles are required to correctly express the idea. For this
31 * cases, Elementary has extensions.
32 *
33 * Extensions allow the application developer to write styles of its own
34 * to apply to some widgets. This requires knowledge of how each widget
35 * is themed, as extensions will always replace the entire group used by
36 * the widget, so important signals and parts need to be there for the
37 * object to behave properly (see documentation of Edje for details).
38 * Once the theme for the extension is done, the application needs to add
39 * it to the list of themes Elementary will look into, using
40 * elm_theme_extension_add(), and set the style of the desired widgets as
41 * he would normally with elm_object_style_set().
42 *
43 * Overlays, on the other hand, can replace the look of all widgets by
44 * overriding the default style. Like extensions, it's up to the application
45 * developer to write the theme for the widgets it wants, the difference
46 * being that when looking for the theme, Elementary will check first the
47 * list of overlays, then the set theme and lastly the list of extensions,
48 * so with overlays it's possible to replace the default view and every
49 * widget will be affected. This is very much alike to setting the whole
50 * theme for the application and will probably clash with the end user
51 * options, not to mention the risk of ending up with not matching styles
52 * across the program. Unless there's a very special reason to use them,
53 * overlays should be avoided for the reasons exposed before.
54 *
55 * All these theme lists are handled by ::Elm_Theme instances. Elementary
56 * keeps one default internally and every function that receives one of
57 * these can be called with NULL to refer to this default (except for
58 * elm_theme_free()). It's possible to create a new instance of a
59 * ::Elm_Theme to set other theme for a specific widget (and all of its
60 * children), but this is as discouraged, if not even more so, than using
61 * overlays. Don't use this unless you really know what you are doing.
62 *
63 * But to be less negative about things, you can look at the following
64 * examples:
65 * @li @ref theme_example_01 "Using extensions"
66 * @li @ref theme_example_02 "Using overlays"
67 *
68 * @{
69 */
70/**
71 * @typedef Elm_Theme
72 *
73 * Opaque handler for the list of themes Elementary looks for when
74 * rendering widgets.
75 *
76 * Stay out of this unless you really know what you are doing. For most
77 * cases, sticking to the default is all a developer needs.
78 */
79typedef struct _Elm_Theme Elm_Theme;
80
81/**
82 * Create a new specific theme
83 *
84 * This creates an empty specific theme that only uses the default theme. A
85 * specific theme has its own private set of extensions and overlays too
86 * (which are empty by default). Specific themes do not fall back to themes
87 * of parent objects. They are not intended for this use. Use styles, overlays
88 * and extensions when needed, but avoid specific themes unless there is no
89 * other way (example: you want to have a preview of a new theme you are
90 * selecting in a "theme selector" window. The preview is inside a scroller
91 * and should display what the theme you selected will look like, but not
92 * actually apply it yet. The child of the scroller will have a specific
93 * theme set to show this preview before the user decides to apply it to all
94 * applications).
95 *
96 * @ingroup Theme
97 */
98EAPI Elm_Theme *elm_theme_new(void);
99
100/**
101 * Free a specific theme
102 *
103 * @param th The theme to free
104 *
105 * This frees a theme created with elm_theme_new().
106 *
107 * @ingroup Theme
108 */
109EAPI void elm_theme_free(Elm_Theme *th);
110
111/**
112 * Copy the theme from the source to the destination theme
113 *
114 * @param th The source theme to copy from
115 * @param thdst The destination theme to copy data to
116 *
117 * This makes a one-time static copy of all the theme config, extensions
118 * and overlays from @p th to @p thdst. If @p th references a theme, then
119 * @p thdst is also set to reference it, with all the theme settings,
120 * overlays and extensions that @p th had.
121 *
122 * @ingroup Theme
123 */
124EAPI void elm_theme_copy(Elm_Theme *th, Elm_Theme *thdst);
125
126/**
127 * Tell the source theme to reference the ref theme
128 *
129 * @param th The theme that will do the referencing
130 * @param thref The theme that is the reference source
131 *
132 * This clears @p th to be empty and then sets it to refer to @p thref
133 * so @p th acts as an override to @p thref, but where its overrides
134 * don't apply, it will fall through to @p thref for configuration.
135 *
136 * @ingroup Theme
137 */
138EAPI void elm_theme_ref_set(Elm_Theme *th, Elm_Theme *thref);
139
140/**
141 * Return the theme referred to
142 *
143 * @param th The theme to get the reference from
144 * @return The referenced theme handle
145 *
146 * This gets the theme set as the reference theme by elm_theme_ref_set().
147 * If no theme is set as a reference, NULL is returned.
148 *
149 * @ingroup Theme
150 */
151EAPI Elm_Theme *elm_theme_ref_get(Elm_Theme *th);
152
153/**
154 * Return the default theme
155 *
156 * @return The default theme handle
157 *
158 * This returns the internal default theme setup handle that all widgets
159 * use implicitly unless a specific theme is set. This is also often use
160 * as a shorthand of NULL.
161 *
162 * @ingroup Theme
163 */
164EAPI Elm_Theme *elm_theme_default_get(void);
165
166/**
167 * Prepends a theme overlay to the list of overlays
168 *
169 * @param th The theme to add to, or if NULL, the default theme
170 * @param item The Edje file path to be used
171 *
172 * Use this if your application needs to provide some custom overlay theme
173 * (An Edje file that replaces some default styles of widgets) where adding
174 * new styles, or changing system theme configuration is not possible. Do
175 * NOT use this instead of a proper system theme configuration. Use proper
176 * configuration files, profiles, environment variables etc. to set a theme
177 * so that the theme can be altered by simple configuration by a user. Using
178 * this call to achieve that effect is abusing the API and will create lots
179 * of trouble.
180 *
181 * @see elm_theme_extension_add()
182 *
183 * @ingroup Theme
184 */
185EAPI void elm_theme_overlay_add(Elm_Theme *th, const char *item);
186
187/**
188 * Delete a theme overlay from the list of overlays
189 *
190 * @param th The theme to delete from, or if NULL, the default theme
191 * @param item The name of the theme overlay
192 *
193 * @see elm_theme_overlay_add()
194 *
195 * @ingroup Theme
196 */
197EAPI void elm_theme_overlay_del(Elm_Theme *th, const char *item);
198
199/**
200 * Get the list of registered overlays for the given theme
201 *
202 * @param th The theme from which to get the overlays
203 * @return List of theme overlays. Do not free it.
204 *
205 * @see elm_theme_overlay_add()
206 *
207 * @ingroup Theme
208 */
209EAPI const Eina_List *elm_theme_overlay_list_get(const Elm_Theme *th);
210
211/**
212 * Appends a theme extension to the list of extensions.
213 *
214 * @param th The theme to add to, or if NULL, the default theme
215 * @param item The Edje file path to be used
216 *
217 * This is intended when an application needs more styles of widgets or new
218 * widget themes that the default does not provide (or may not provide). The
219 * application has "extended" usage by coming up with new custom style names
220 * for widgets for specific uses, but as these are not "standard", they are
221 * not guaranteed to be provided by a default theme. This means the
222 * application is required to provide these extra elements itself in specific
223 * Edje files. This call adds one of those Edje files to the theme search
224 * path to be search after the default theme. The use of this call is
225 * encouraged when default styles do not meet the needs of the application.
226 * Use this call instead of elm_theme_overlay_add() for almost all cases.
227 *
228 * @see elm_object_style_set()
229 *
230 * @ingroup Theme
231 */
232EAPI void elm_theme_extension_add(Elm_Theme *th, const char *item);
233
234/**
235 * Deletes a theme extension from the list of extensions.
236 *
237 * @param th The theme to delete from, or if NULL, the default theme
238 * @param item The name of the theme extension
239 *
240 * @see elm_theme_extension_add()
241 *
242 * @ingroup Theme
243 */
244EAPI void elm_theme_extension_del(Elm_Theme *th, const char *item);
245
246/**
247 * Get the list of registered extensions for the given theme
248 *
249 * @param th The theme from which to get the extensions
250 * @return List of theme extensions. Do not free it.
251 *
252 * @see elm_theme_extension_add()
253 *
254 * @ingroup Theme
255 */
256EAPI const Eina_List *elm_theme_extension_list_get(const Elm_Theme *th);
257
258/**
259 * Set the theme search order for the given theme
260 *
261 * @param th The theme to set the search order, or if NULL, the default theme
262 * @param theme Theme search string
263 *
264 * This sets the search string for the theme in path-notation from first
265 * theme to search, to last, delimited by the : character. Example:
266 *
267 * "shiny:/path/to/file.edj:default"
268 *
269 * See the ELM_THEME environment variable for more information.
270 *
271 * @see elm_theme_get()
272 * @see elm_theme_list_get()
273 *
274 * @ingroup Theme
275 */
276EAPI void elm_theme_set(Elm_Theme *th, const char *theme);
277
278/**
279 * Return the theme search order
280 *
281 * @param th The theme to get the search order, or if NULL, the default theme
282 * @return The internal search order path
283 *
284 * This function returns a colon separated string of theme elements as
285 * returned by elm_theme_list_get().
286 *
287 * @see elm_theme_set()
288 * @see elm_theme_list_get()
289 *
290 * @ingroup Theme
291 */
292EAPI const char *elm_theme_get(Elm_Theme *th);
293
294/**
295 * Return a list of theme elements to be used in a theme.
296 *
297 * @param th Theme to get the list of theme elements from.
298 * @return The internal list of theme elements
299 *
300 * This returns the internal list of theme elements (will only be valid as
301 * long as the theme is not modified by elm_theme_set() or theme is not
302 * freed by elm_theme_free(). This is a list of strings which must not be
303 * altered as they are also internal. If @p th is NULL, then the default
304 * theme element list is returned.
305 *
306 * A theme element can consist of a full or relative path to a .edj file,
307 * or a name, without extension, for a theme to be searched in the known
308 * theme paths for Elementary.
309 *
310 * @see elm_theme_set()
311 * @see elm_theme_get()
312 *
313 * @ingroup Theme
314 */
315EAPI const Eina_List *elm_theme_list_get(const Elm_Theme *th);
316
317/**
318 * Return the full path for a theme element
319 *
320 * @param f The theme element name
321 * @param in_search_path Pointer to a boolean to indicate if item is in the search path or not
322 * @return The full path to the file found.
323 *
324 * This returns a string you should free with free() on success, NULL on
325 * failure. This will search for the given theme element, and if it is a
326 * full or relative path element or a simple search-able name. The returned
327 * path is the full path to the file, if searched, and the file exists, or it
328 * is simply the full path given in the element or a resolved path if
329 * relative to home. The @p in_search_path boolean pointed to is set to
330 * EINA_TRUE if the file was a search-able file and is in the search path,
331 * and EINA_FALSE otherwise.
332 *
333 * @ingroup Theme
334 */
335EAPI char *elm_theme_list_item_path_get(const char *f, Eina_Bool *in_search_path);
336
337/**
338 * Flush the current theme.
339 *
340 * @param th Theme to flush
341 *
342 * This flushes caches that let elementary know where to find theme elements
343 * in the given theme. If @p th is NULL, then the default theme is flushed.
344 * Call this function if source theme data has changed in such a way as to
345 * make any caches Elementary kept invalid.
346 *
347 * @ingroup Theme
348 */
349EAPI void elm_theme_flush(Elm_Theme *th);
350
351/**
352 * This flushes all themes (default and specific ones).
353 *
354 * This will flush all themes in the current application context, by calling
355 * elm_theme_flush() on each of them.
356 *
357 * @ingroup Theme
358 */
359EAPI void elm_theme_full_flush(void);
360
361/**
362 * Return a list of theme elements in the theme search path
363 *
364 * @return A list of strings that are the theme element names.
365 *
366 * This lists all available theme files in the standard Elementary search path
367 * for theme elements, and returns them in alphabetical order as theme
368 * element names in a list of strings. Free this with
369 * elm_theme_name_available_list_free() when you are done with the list.
370 *
371 * @ingroup Theme
372 */
373EAPI Eina_List *elm_theme_name_available_list_new(void);
374
375/**
376 * Free the list returned by elm_theme_name_available_list_new()
377 *
378 * This frees the list of themes returned by
379 * elm_theme_name_available_list_new(). Once freed the list should no longer
380 * be used. a new list mys be created.
381 *
382 * @ingroup Theme
383 */
384EAPI void elm_theme_name_available_list_free(Eina_List *list);
385
386/**
387 * Set a specific theme to be used for this object and its children
388 *
389 * @param obj The object to set the theme on
390 * @param th The theme to set
391 *
392 * This sets a specific theme that will be used for the given object and any
393 * child objects it has. If @p th is NULL then the theme to be used is
394 * cleared and the object will inherit its theme from its parent (which
395 * ultimately will use the default theme if no specific themes are set).
396 *
397 * Use special themes with great care as this will annoy users and make
398 * configuration difficult. Avoid any custom themes at all if it can be
399 * helped.
400 *
401 * @ingroup Theme
402 */
403EAPI void elm_object_theme_set(Evas_Object *obj, Elm_Theme *th);
404
405/**
406 * Get the specific theme to be used
407 *
408 * @param obj The object to get the specific theme from
409 * @return The specific theme set.
410 *
411 * This will return a specific theme set, or NULL if no specific theme is
412 * set on that object. It will not return inherited themes from parents, only
413 * the specific theme set for that specific object. See elm_object_theme_set()
414 * for more information.
415 *
416 * @ingroup Theme
417 */
418EAPI Elm_Theme *elm_object_theme_get(const Evas_Object *obj);
419
420/**
421 * Get a data item from a theme
422 *
423 * @param th The theme, or NULL for default theme
424 * @param key The data key to search with
425 * @return The data value, or NULL on failure
426 *
427 * This function is used to return data items from edc in @p th, an overlay, or an extension.
428 * It works the same way as edje_file_data_get() except that the return is stringshared.
429 *
430 * @ingroup Theme
431 */
432EAPI const char *elm_theme_data_get(Elm_Theme *th, const char *key);
433
434/**
435 * @}
436 */
diff --git a/libraries/elementary/src/lib/elm_thumb.c b/libraries/elementary/src/lib/elm_thumb.c
new file mode 100644
index 0000000..fee178d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_thumb.c
@@ -0,0 +1,728 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include <assert.h>
4
5typedef struct _Widget_Data Widget_Data;
6
7struct _Widget_Data
8{
9 Evas_Object *self;
10 Evas_Object *frame;
11 Evas_Object *view;
12 const char *file;
13 const char *key;
14 struct
15 {
16 const char *file;
17 const char *key;
18#ifdef HAVE_ELEMENTARY_ETHUMB
19 const char *thumb_path;
20 const char *thumb_key;
21 Ethumb_Client_Async *request;
22
23 Ethumb_Thumb_Format format;
24
25 Eina_Bool retry : 1;
26#endif
27 } thumb;
28 Ecore_Event_Handler *eeh;
29 Elm_Thumb_Animation_Setting anim_setting;
30 Eina_Bool on_hold : 1;
31 Eina_Bool is_video : 1;
32 Eina_Bool was_video : 1;
33 Eina_Bool edit : 1;
34};
35
36static const char *widtype = NULL;
37
38static const char SIG_CLICKED[] = "clicked";
39static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
40static const char SIG_GENERATE_ERROR[] = "generate,error";
41static const char SIG_GENERATE_START[] = "generate,start";
42static const char SIG_GENERATE_STOP[] = "generate,stop";
43static const char SIG_LOAD_ERROR[] = "load,error";
44static const char SIG_PRESS[] = "press";
45
46static const Evas_Smart_Cb_Description _signals[] =
47{
48 {SIG_CLICKED, ""},
49 {SIG_CLICKED_DOUBLE, ""},
50 {SIG_GENERATE_ERROR, ""},
51 {SIG_GENERATE_START, ""},
52 {SIG_GENERATE_STOP, ""},
53 {SIG_LOAD_ERROR, ""},
54 {SIG_PRESS, ""},
55 {NULL, NULL}
56};
57
58#define EDJE_SIGNAL_GENERATE_START "elm,thumb,generate,start"
59#define EDJE_SIGNAL_GENERATE_STOP "elm,thumb,generate,stop"
60#define EDJE_SIGNAL_GENERATE_ERROR "elm,thumb,generate,error"
61#define EDJE_SIGNAL_LOAD_ERROR "elm,thumb,load,error"
62#define EDJE_SIGNAL_PULSE_START "elm,state,pulse,start"
63#define EDJE_SIGNAL_PULSE_STOP "elm,state,pulse,stop"
64
65struct _Ethumb_Client *_elm_ethumb_client = NULL;
66Eina_Bool _elm_ethumb_connected = EINA_FALSE;
67#ifdef HAVE_ELEMENTARY_ETHUMB
68static Eina_List *retry = NULL;
69static int pending_request = 0;
70#endif
71
72EAPI int ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
73
74static void
75_del_hook(Evas_Object *obj)
76{
77 Widget_Data *wd = elm_widget_data_get(obj);
78
79#ifdef HAVE_ELEMENTARY_ETHUMB
80 if (wd->thumb.request)
81 {
82 ethumb_client_thumb_async_cancel(_elm_ethumb_client, wd->thumb.request);
83 wd->thumb.request = NULL;
84 }
85 if (wd->thumb.retry)
86 {
87 retry = eina_list_remove(retry, wd);
88 wd->thumb.retry = EINA_FALSE;
89 }
90
91 eina_stringshare_del(wd->thumb.thumb_path);
92 eina_stringshare_del(wd->thumb.thumb_key);
93#endif
94
95 eina_stringshare_del(wd->file);
96 eina_stringshare_del(wd->key);
97 if (wd->eeh) ecore_event_handler_del(wd->eeh);
98 free(wd);
99}
100
101static void
102_theme_hook(Evas_Object *obj)
103{
104 Widget_Data *wd = elm_widget_data_get(obj);
105 _elm_theme_object_set(obj, wd->frame, "thumb", "base",
106 elm_widget_style_get(obj));
107}
108
109#ifdef HAVE_ELEMENTARY_ETHUMB
110static void
111_mouse_down_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
112{
113 Widget_Data *wd = data;
114 Evas_Event_Mouse_Down *ev = event_info;
115
116 if (ev->button != 1)
117 return;
118 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
119 wd->on_hold = EINA_TRUE;
120 else
121 wd->on_hold = EINA_FALSE;
122 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
123 evas_object_smart_callback_call(wd->self, SIG_CLICKED_DOUBLE, NULL);
124 else
125 evas_object_smart_callback_call(wd->self, SIG_PRESS, NULL);
126}
127
128static void
129_mouse_up_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
130{
131 Widget_Data *wd = data;
132 Evas_Event_Mouse_Up *ev = event_info;
133
134 if (ev->button != 1)
135 return;
136 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
137 wd->on_hold = EINA_TRUE;
138 else
139 wd->on_hold = EINA_FALSE;
140 if (!wd->on_hold)
141 evas_object_smart_callback_call(wd->self, SIG_CLICKED, NULL);
142 wd->on_hold = EINA_FALSE;
143}
144
145static void
146_thumb_ready(Widget_Data *wd, const char *thumb_path, const char *thumb_key)
147{
148 Evas_Coord mw, mh;
149 Evas_Coord aw, ah;
150
151 evas_object_image_size_get(wd->view, &aw, &ah);
152 evas_object_size_hint_aspect_set(wd->view,
153 EVAS_ASPECT_CONTROL_BOTH,
154 aw, ah);
155 edje_object_part_swallow(wd->frame, "elm.swallow.content", wd->view);
156 edje_object_size_min_get(wd->frame, &mw, &mh);
157 edje_object_size_min_restricted_calc(wd->frame, &mw, &mh, mw, mh);
158 evas_object_size_hint_min_set(wd->self, mw, mh);
159 eina_stringshare_replace(&(wd->thumb.file), thumb_path);
160 eina_stringshare_replace(&(wd->thumb.key), thumb_key);
161 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_STOP, "elm");
162 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
163 evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
164}
165
166static void
167_thumb_loaded(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
168{
169 Widget_Data *wd = data;
170 const char *thumb_path;
171 const char *thumb_key;
172
173 evas_object_image_file_get(wd->view, &thumb_path, &thumb_key);
174
175 _thumb_ready(wd, thumb_path, thumb_key);
176}
177
178/* As we do use stat to check if a thumbnail is available, it's possible
179 that we end up accessing before the file is completly written on disk.
180 By retrying each time a thumbnail is finished we should be fine or not.
181*/
182static Eina_Bool
183_retry_thumb(Widget_Data *wd)
184{
185 int r;
186
187 if ((wd->is_video) && (wd->thumb.format == ETHUMB_THUMB_EET))
188 {
189 edje_object_file_set(wd->view, NULL, NULL);
190 if (!edje_object_file_set(wd->view,
191 wd->thumb.thumb_path,
192 "movie/thumb"))
193 {
194 if (pending_request == 0)
195 ERR("could not set file=%s key=%s for %s",
196 wd->thumb.thumb_path,
197 wd->thumb.thumb_key,
198 wd->file);
199 goto view_err;
200 }
201 }
202 else
203 {
204 evas_object_image_file_set(wd->view, NULL, NULL);
205 evas_object_image_file_set(wd->view,
206 wd->thumb.thumb_path,
207 wd->thumb.thumb_key);
208 r = evas_object_image_load_error_get(wd->view);
209 if (r != EVAS_LOAD_ERROR_NONE)
210 {
211 if (pending_request == 0)
212 ERR("%s: %s", wd->thumb.thumb_path, evas_load_error_str(r));
213 goto view_err;
214 }
215
216 evas_object_event_callback_add(wd->view,
217 EVAS_CALLBACK_IMAGE_PRELOADED,
218 _thumb_loaded, wd);
219 evas_object_image_preload(wd->view, EINA_TRUE);
220 return EINA_TRUE;
221 }
222
223 _thumb_ready(wd, wd->thumb.thumb_path, wd->thumb.thumb_key);
224
225 eina_stringshare_del(wd->thumb.thumb_path);
226 wd->thumb.thumb_path = NULL;
227
228 eina_stringshare_del(wd->thumb.thumb_key);
229 wd->thumb.thumb_key = NULL;
230
231 return EINA_TRUE;
232
233 view_err:
234 return EINA_FALSE;
235}
236
237static void
238_finished_thumb(Widget_Data *wd,
239 const char *thumb_path,
240 const char *thumb_key)
241{
242 Eina_List *l, *ll;
243 Evas *evas;
244 int r;
245
246 evas = evas_object_evas_get(wd->self);
247 if ((wd->view) && (wd->is_video ^ wd->was_video))
248 {
249 evas_object_del(wd->view);
250 wd->view = NULL;
251 }
252 wd->was_video = wd->is_video;
253
254 if ((wd->is_video) &&
255 (ethumb_client_format_get(_elm_ethumb_client) == ETHUMB_THUMB_EET))
256 {
257 if (!wd->view)
258 {
259 wd->view = edje_object_add(evas);
260 if (!wd->view)
261 {
262 ERR("could not create edje object");
263 goto err;
264 }
265 elm_widget_sub_object_add(wd->self, wd->view);
266 }
267
268 if (!edje_object_file_set(wd->view, thumb_path, thumb_key))
269 {
270 wd->thumb.thumb_path = eina_stringshare_ref(thumb_path);
271 wd->thumb.thumb_key = eina_stringshare_ref(thumb_key);
272 wd->thumb.format = ethumb_client_format_get(_elm_ethumb_client);
273 wd->thumb.retry = EINA_TRUE;
274
275 retry = eina_list_append(retry, wd);
276 return ;
277 }
278 }
279 else
280 {
281 if (!wd->view)
282 {
283 wd->view = evas_object_image_filled_add(evas);
284 if (!wd->view)
285 {
286 ERR("could not create image object");
287 goto err;
288 }
289 evas_object_event_callback_add(wd->view,
290 EVAS_CALLBACK_IMAGE_PRELOADED,
291 _thumb_loaded, wd);
292 elm_widget_sub_object_add(wd->self, wd->view);
293 evas_object_hide(wd->view);
294 }
295
296 evas_object_image_file_set(wd->view, thumb_path, thumb_key);
297 r = evas_object_image_load_error_get(wd->view);
298 if (r != EVAS_LOAD_ERROR_NONE)
299 {
300 WRN("%s: %s", thumb_path, evas_load_error_str(r));
301 wd->thumb.thumb_path = eina_stringshare_ref(thumb_path);
302 wd->thumb.thumb_key = eina_stringshare_ref(thumb_key);
303 wd->thumb.format = ethumb_client_format_get(_elm_ethumb_client);
304 wd->thumb.retry = EINA_TRUE;
305
306 retry = eina_list_append(retry, wd);
307 return ;
308 }
309
310 evas_object_image_preload(wd->view, 0);
311 return ;
312 }
313
314 _thumb_ready(wd, thumb_path, thumb_key);
315
316 EINA_LIST_FOREACH_SAFE(retry, l, ll, wd)
317 if (_retry_thumb(wd))
318 retry = eina_list_remove_list(retry, l);
319
320 if (pending_request == 0)
321 EINA_LIST_FREE(retry, wd)
322 {
323 eina_stringshare_del(wd->thumb.thumb_path);
324 wd->thumb.thumb_path = NULL;
325
326 eina_stringshare_del(wd->thumb.thumb_key);
327 wd->thumb.thumb_key = NULL;
328
329 evas_object_del(wd->view);
330 wd->view = NULL;
331
332 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm");
333 evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL);
334 }
335
336 return;
337
338err:
339 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_LOAD_ERROR, "elm");
340 evas_object_smart_callback_call(wd->self, SIG_LOAD_ERROR, NULL);
341}
342
343static void
344_elm_thumb_done(Ethumb_Client *client __UNUSED__, const char *thumb_path, const char *thumb_key, void *data)
345{
346 Widget_Data *wd = data;
347
348 assert(wd->thumb.request);
349
350 pending_request--;
351 wd->thumb.request = NULL;
352
353 _finished_thumb(wd, thumb_path, thumb_key);
354}
355
356static void
357_elm_thumb_error(Ethumb_Client *client __UNUSED__, void *data)
358{
359 Widget_Data *wd = data;
360
361 assert(wd->thumb.request);
362
363 pending_request--;
364 wd->thumb.request = NULL;
365
366 ERR("could not generate thumbnail for %s (key: %s)", wd->thumb.file, wd->thumb.key ? wd->thumb.key : "");
367
368 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_ERROR, "elm");
369 evas_object_smart_callback_call(wd->self, SIG_GENERATE_ERROR, NULL);
370}
371
372static void
373_thumb_apply(Widget_Data *wd)
374{
375 if (wd->thumb.request)
376 {
377 ethumb_client_thumb_async_cancel(_elm_ethumb_client, wd->thumb.request);
378 wd->thumb.request = NULL;
379 }
380 if (wd->thumb.retry)
381 {
382 retry = eina_list_remove(retry, wd);
383 wd->thumb.retry = EINA_FALSE;
384 }
385
386 if (!wd->file) return;
387
388 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_PULSE_START, "elm");
389 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_START, "elm");
390 evas_object_smart_callback_call(wd->self, SIG_GENERATE_START, NULL);
391
392 pending_request++;
393 ethumb_client_file_set(_elm_ethumb_client, wd->file, wd->key);
394 wd->thumb.request = ethumb_client_thumb_async_get(_elm_ethumb_client,
395 _elm_thumb_done,
396 _elm_thumb_error,
397 wd);
398}
399
400static Eina_Bool
401_thumb_apply_cb(void *data, int type __UNUSED__, void *ev __UNUSED__)
402{
403 _thumb_apply(data);
404 return ECORE_CALLBACK_RENEW;
405}
406
407static void
408_thumb_show(Widget_Data *wd)
409{
410 evas_object_show(wd->frame);
411
412 if (elm_thumb_ethumb_client_connected_get())
413 {
414 _thumb_apply(wd);
415 return;
416 }
417
418 if (!wd->eeh)
419 wd->eeh = ecore_event_handler_add(ELM_ECORE_EVENT_ETHUMB_CONNECT,
420 _thumb_apply_cb, wd);
421}
422
423static void
424_thumb_show_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
425{
426 _thumb_show(data);
427}
428
429static void
430_thumb_hide_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
431{
432 Widget_Data *wd = data;
433
434 evas_object_hide(wd->frame);
435
436 if (wd->thumb.request)
437 {
438 ethumb_client_thumb_async_cancel(_elm_ethumb_client, wd->thumb.request);
439 wd->thumb.request = NULL;
440
441 edje_object_signal_emit(wd->frame, EDJE_SIGNAL_GENERATE_STOP, "elm");
442 evas_object_smart_callback_call(wd->self, SIG_GENERATE_STOP, NULL);
443 }
444
445 if (wd->thumb.retry)
446 {
447 retry = eina_list_remove(retry, wd);
448 wd->thumb.retry = EINA_FALSE;
449 }
450
451 if (wd->eeh)
452 {
453 ecore_event_handler_del(wd->eeh);
454 wd->eeh = NULL;
455 }
456}
457
458#endif
459
460#ifdef ELM_ETHUMB
461static int _elm_need_ethumb = 0;
462
463static void _on_die_cb(void *, Ethumb_Client *);
464
465static void
466_connect_cb(void *data __UNUSED__, Ethumb_Client *c, Eina_Bool success)
467{
468 if (success)
469 {
470 ethumb_client_on_server_die_callback_set(c, _on_die_cb, NULL, NULL);
471 _elm_ethumb_connected = EINA_TRUE;
472 ecore_event_add(ELM_ECORE_EVENT_ETHUMB_CONNECT, NULL, NULL, NULL);
473 }
474 else
475 _elm_ethumb_client = NULL;
476}
477
478static void
479_on_die_cb(void *data __UNUSED__, Ethumb_Client *c __UNUSED__)
480{
481 ethumb_client_disconnect(_elm_ethumb_client);
482 _elm_ethumb_client = NULL;
483 _elm_ethumb_connected = EINA_FALSE;
484 _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
485}
486#endif
487
488void
489_elm_unneed_ethumb(void)
490{
491#ifdef ELM_ETHUMB
492 if (--_elm_need_ethumb) return;
493
494 ethumb_client_disconnect(_elm_ethumb_client);
495 _elm_ethumb_client = NULL;
496 ethumb_client_shutdown();
497 ELM_ECORE_EVENT_ETHUMB_CONNECT = 0;
498#endif
499}
500
501static Eina_Bool
502_elm_thumb_dropcb(void *data __UNUSED__, Evas_Object *o, Elm_Selection_Data *drop)
503{
504 if ((!o) || (!drop) || (!drop->data)) return EINA_FALSE;
505 elm_thumb_file_set(o, drop->data, NULL);
506 return EINA_TRUE;
507}
508
509EAPI Eina_Bool
510elm_need_ethumb(void)
511{
512#ifdef ELM_ETHUMB
513 if (_elm_need_ethumb++) return EINA_TRUE;
514 ELM_ECORE_EVENT_ETHUMB_CONNECT = ecore_event_type_new();
515 ethumb_client_init();
516 _elm_ethumb_client = ethumb_client_connect(_connect_cb, NULL, NULL);
517 return EINA_TRUE;
518#else
519 return EINA_FALSE;
520#endif
521}
522
523EAPI Evas_Object *
524elm_thumb_add(Evas_Object *parent)
525{
526 Evas *e;
527 Widget_Data *wd;
528 Evas_Object *obj;
529 Evas_Coord minw, minh;
530
531 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
532
533 ELM_SET_WIDTYPE(widtype, "thumb");
534 elm_widget_type_set(obj, "thumb");
535 elm_widget_sub_object_add(parent, obj);
536 elm_widget_data_set(obj, wd);
537 elm_widget_del_hook_set(obj, _del_hook);
538 elm_widget_theme_hook_set(obj, _theme_hook);
539 elm_widget_can_focus_set(obj, EINA_FALSE);
540
541 wd->frame = edje_object_add(e);
542 _elm_theme_object_set(obj, wd->frame, "thumb", "base", "default");
543 elm_widget_resize_object_set(obj, wd->frame);
544
545 edje_object_size_min_calc(obj, &minw, &minh);
546 evas_object_size_hint_min_set(obj, minw, minh);
547
548 wd->self = obj;
549 wd->view = NULL;
550 wd->file = NULL;
551 wd->key = NULL;
552 wd->eeh = NULL;
553 wd->on_hold = EINA_FALSE;
554 wd->is_video = EINA_FALSE;
555 wd->was_video = EINA_FALSE;
556
557#ifdef HAVE_ELEMENTARY_ETHUMB
558 wd->thumb.thumb_path = NULL;
559 wd->thumb.thumb_key = NULL;
560 wd->thumb.request = NULL;
561 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_DOWN,
562 _mouse_down_cb, wd);
563 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_UP,
564 _mouse_up_cb, wd);
565 evas_object_event_callback_add(obj, EVAS_CALLBACK_SHOW,
566 _thumb_show_cb, wd);
567 evas_object_event_callback_add(obj, EVAS_CALLBACK_HIDE,
568 _thumb_hide_cb, wd);
569#endif
570
571 // TODO: convert Elementary to subclassing of Evas_Smart_Class
572 // TODO: and save some bytes, making descriptions per-class and not instance!
573 evas_object_smart_callbacks_descriptions_set(obj, _signals);
574 return obj;
575}
576
577EAPI void
578elm_thumb_reload(Evas_Object *obj)
579{
580 ELM_CHECK_WIDTYPE(obj, widtype);
581 Widget_Data *wd = elm_widget_data_get(obj);
582
583 eina_stringshare_replace(&(wd->thumb.file), NULL);
584 eina_stringshare_replace(&(wd->thumb.key), NULL);
585
586#ifdef HAVE_ELEMENTARY_ETHUMB
587 if (evas_object_visible_get(obj))
588 _thumb_show(wd);
589#endif
590}
591
592EAPI void
593elm_thumb_file_set(Evas_Object *obj, const char *file, const char *key)
594{
595 ELM_CHECK_WIDTYPE(obj, widtype);
596 Eina_Bool file_replaced, key_replaced;
597 Widget_Data *wd = elm_widget_data_get(obj);
598
599 file_replaced = eina_stringshare_replace(&(wd->file), file);
600 key_replaced = eina_stringshare_replace(&(wd->key), key);
601
602 if (file_replaced)
603 {
604 int prefix_size;
605 const char **ext, *ptr;
606 static const char *extensions[] =
607 {
608 ".avi", ".mp4", ".ogv", ".mov", ".mpg", ".wmv", NULL
609 };
610
611 prefix_size = eina_stringshare_strlen(wd->file) - 4;
612 if (prefix_size >= 0)
613 {
614 ptr = wd->file + prefix_size;
615 wd->is_video = EINA_FALSE;
616 for (ext = extensions; *ext; ext++)
617 if (!strcasecmp(ptr, *ext))
618 {
619 wd->is_video = EINA_TRUE;
620 break;
621 }
622 }
623 }
624
625 eina_stringshare_replace(&(wd->thumb.file), NULL);
626 eina_stringshare_replace(&(wd->thumb.key), NULL);
627
628#ifdef HAVE_ELEMENTARY_ETHUMB
629 if (((file_replaced) || (key_replaced)) && (evas_object_visible_get(obj)))
630 _thumb_show(wd);
631#else
632 (void)key_replaced;
633#endif
634}
635
636EAPI void
637elm_thumb_file_get(const Evas_Object *obj, const char **file, const char **key)
638{
639 ELM_CHECK_WIDTYPE(obj, widtype);
640 Widget_Data *wd = elm_widget_data_get(obj);
641
642 if (file)
643 *file = wd->file;
644 if (key)
645 *key = wd->key;
646}
647
648EAPI void
649elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key)
650{
651 ELM_CHECK_WIDTYPE(obj, widtype);
652 Widget_Data *wd = elm_widget_data_get(obj);
653
654 if (file)
655 *file = wd->thumb.file;
656 if (key)
657 *key = wd->thumb.key;
658}
659
660EAPI void
661elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting setting)
662{
663 ELM_CHECK_WIDTYPE(obj, widtype);
664 Widget_Data *wd = elm_widget_data_get(obj);
665
666 EINA_SAFETY_ON_TRUE_RETURN(setting >= ELM_THUMB_ANIMATION_LAST);
667
668 wd->anim_setting = setting;
669 if (setting == ELM_THUMB_ANIMATION_LOOP)
670 edje_object_signal_emit(wd->view, "animate_loop", "");
671 else if (setting == ELM_THUMB_ANIMATION_START)
672 edje_object_signal_emit(wd->view, "animate", "");
673 else if (setting == ELM_THUMB_ANIMATION_STOP)
674 edje_object_signal_emit(wd->view, "animate_stop", "");
675}
676
677EAPI Elm_Thumb_Animation_Setting
678elm_thumb_animate_get(const Evas_Object *obj)
679{
680 ELM_CHECK_WIDTYPE(obj, widtype) ELM_THUMB_ANIMATION_LAST;
681 Widget_Data *wd = elm_widget_data_get(obj);
682
683 return wd->anim_setting;
684}
685
686EAPI void *
687elm_thumb_ethumb_client_get(void)
688{
689 return _elm_ethumb_client;
690}
691
692EAPI Eina_Bool
693elm_thumb_ethumb_client_connected_get(void)
694{
695 return _elm_ethumb_connected;
696}
697
698EAPI Eina_Bool
699elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit)
700{
701 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
702 Widget_Data *wd = elm_widget_data_get(obj);
703
704 if (!wd) return EINA_FALSE;
705 edit = !!edit;
706 if (wd->edit == edit) return EINA_TRUE;
707
708 wd->edit = edit;
709 if (wd->edit)
710 elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE,
711 _elm_thumb_dropcb, obj);
712 else
713 elm_drop_target_del(obj);
714
715 return EINA_TRUE;
716}
717
718EAPI Eina_Bool
719elm_thumb_editable_get(const Evas_Object *obj)
720{
721 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
722 Widget_Data *wd = elm_widget_data_get(obj);
723
724 if (!wd) return EINA_FALSE;
725 return wd->edit;
726}
727
728/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/elm_thumb.h b/libraries/elementary/src/lib/elm_thumb.h
new file mode 100644
index 0000000..8aa0593
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_thumb.h
@@ -0,0 +1,263 @@
1/**
2 * @defgroup Thumb Thumb
3 * @ingroup Elementary
4 *
5 * @image html img/widget/thumb/preview-00.png
6 * @image latex img/widget/thumb/preview-00.eps
7 *
8 * A thumb object is used for displaying the thumbnail of an image or video.
9 * You must have compiled Elementary with Ethumb_Client support and the DBus
10 * service must be present and auto-activated in order to have thumbnails to
11 * be generated. You must also have a Session bus, not System bus.
12 *
13 * Once the thumbnail object becomes visible, it will check if there is a
14 * previously generated thumbnail image for the file set on it. If not, it
15 * will start generating this thumbnail.
16 *
17 * Different config settings will cause different thumbnails to be generated
18 * even on the same file.
19 *
20 * Generated thumbnails are stored under @c $HOME/.thumbnails/. Check the
21 * Ethumb documentation to change this path, and to see other configuration
22 * options.
23 *
24 * Signals that you can add callbacks for are:
25 *
26 * - "clicked" - This is called when a user has clicked the thumb without dragging
27 * around.
28 * - "clicked,double" - This is called when a user has double-clicked the thumb.
29 * - "press" - This is called when a user has pressed down the thumb.
30 * - "generate,start" - The thumbnail generation started.
31 * - "generate,stop" - The generation process stopped.
32 * - "generate,error" - The generation failed.
33 * - "load,error" - The thumbnail image loading failed.
34 *
35 * available styles:
36 * - default
37 * - noframe
38 *
39 * An example of use of thumbnail:
40 *
41 * - @ref thumb_example_01
42 */
43
44/**
45 * @addtogroup Thumb
46 * @{
47 */
48
49/**
50 * @enum _Elm_Thumb_Animation_Setting
51 * @typedef Elm_Thumb_Animation_Setting
52 *
53 * Used to set if a video thumbnail is animating or not.
54 *
55 * @ingroup Thumb
56 */
57typedef enum
58{
59 ELM_THUMB_ANIMATION_START = 0, /**< Play animation once */
60 ELM_THUMB_ANIMATION_LOOP, /**< Keep playing animation until stop is requested */
61 ELM_THUMB_ANIMATION_STOP, /**< Stop playing the animation */
62 ELM_THUMB_ANIMATION_LAST
63} Elm_Thumb_Animation_Setting;
64
65/**
66 * Add a new thumb object to the parent.
67 *
68 * @param parent The parent object.
69 * @return The new object or NULL if it cannot be created.
70 *
71 * @see elm_thumb_file_set()
72 * @see elm_thumb_ethumb_client_get()
73 *
74 * @ingroup Thumb
75 */
76EAPI Evas_Object *elm_thumb_add(Evas_Object *parent);
77
78/**
79 * Reload thumbnail if it was generated before.
80 *
81 * @param obj The thumb object to reload
82 *
83 * This is useful if the ethumb client configuration changed, like its
84 * size, aspect or any other property one set in the handle returned
85 * by elm_thumb_ethumb_client_get().
86 *
87 * If the options didn't change, the thumbnail won't be generated again, but
88 * the old one will still be used.
89 *
90 * @see elm_thumb_file_set()
91 *
92 * @ingroup Thumb
93 */
94EAPI void elm_thumb_reload(Evas_Object *obj);
95
96/**
97 * Set the file that will be used as thumbnail.
98 *
99 * @param obj The thumb object.
100 * @param file The path to file that will be used as thumb.
101 * @param key The key used in case of an EET file.
102 *
103 * The file can be an image or a video (in that case, acceptable extensions are:
104 * avi, mp4, ogv, mov, mpg and wmv). To start the video animation, use the
105 * function elm_thumb_animate().
106 *
107 * @see elm_thumb_file_get()
108 * @see elm_thumb_reload()
109 * @see elm_thumb_animate()
110 *
111 * @ingroup Thumb
112 */
113EAPI void elm_thumb_file_set(Evas_Object *obj, const char *file, const char *key);
114
115/**
116 * Get the image or video path and key used to generate the thumbnail.
117 *
118 * @param obj The thumb object.
119 * @param file Pointer to filename.
120 * @param key Pointer to key.
121 *
122 * @see elm_thumb_file_set()
123 * @see elm_thumb_path_get()
124 *
125 * @ingroup Thumb
126 */
127EAPI void elm_thumb_file_get(const Evas_Object *obj, const char **file, const char **key);
128
129/**
130 * Get the path and key to the image or video thumbnail generated by ethumb.
131 *
132 * One just needs to make sure that the thumbnail was generated before getting
133 * its path; otherwise, the path will be NULL. One way to do that is by asking
134 * for the path when/after the "generate,stop" smart callback is called.
135 *
136 * @param obj The thumb object.
137 * @param file Pointer to thumb path.
138 * @param key Pointer to thumb key.
139 *
140 * @see elm_thumb_file_get()
141 *
142 * @ingroup Thumb
143 */
144EAPI void elm_thumb_path_get(const Evas_Object *obj, const char **file, const char **key);
145
146/**
147 * Set the animation state for the thumb object. If its content is an animated
148 * video, you may start/stop the animation or tell it to play continuously and
149 * looping.
150 *
151 * @param obj The thumb object.
152 * @param s The animation setting.
153 *
154 * @see elm_thumb_file_set()
155 *
156 * @ingroup Thumb
157 */
158EAPI void elm_thumb_animate_set(Evas_Object *obj, Elm_Thumb_Animation_Setting s);
159
160/**
161 * Get the animation state for the thumb object.
162 *
163 * @param obj The thumb object.
164 * @return getting The animation setting or @c ELM_THUMB_ANIMATION_LAST,
165 * on errors.
166 *
167 * @see elm_thumb_animate_set()
168 *
169 * @ingroup Thumb
170 */
171EAPI Elm_Thumb_Animation_Setting elm_thumb_animate_get(const Evas_Object *obj);
172
173/**
174 * Get the ethumb_client handle so custom configuration can be made.
175 *
176 * @return Ethumb_Client instance or NULL.
177 *
178 * This must be called before the objects are created to be sure no object is
179 * visible and no generation started.
180 *
181 * Example of usage:
182 *
183 * @code
184 * #include <Elementary.h>
185 * #ifndef ELM_LIB_QUICKLAUNCH
186 * EAPI_MAIN int
187 * elm_main(int argc, char **argv)
188 * {
189 * Ethumb_Client *client;
190 *
191 * elm_need_ethumb();
192 *
193 * // ... your code
194 *
195 * client = elm_thumb_ethumb_client_get();
196 * if (!client)
197 * {
198 * ERR("could not get ethumb_client");
199 * return 1;
200 * }
201 * ethumb_client_size_set(client, 100, 100);
202 * ethumb_client_crop_align_set(client, 0.5, 0.5);
203 * // ... your code
204 *
205 * // Create elm_thumb objects here
206 *
207 * elm_run();
208 * elm_shutdown();
209 * return 0;
210 * }
211 * #endif
212 * ELM_MAIN()
213 * @endcode
214 *
215 * @note There's only one client handle for Ethumb, so once a configuration
216 * change is done to it, any other request for thumbnails (for any thumbnail
217 * object) will use that configuration. Thus, this configuration is global.
218 *
219 * @ingroup Thumb
220 */
221EAPI void *elm_thumb_ethumb_client_get(void);
222
223/**
224 * Get the ethumb_client connection state.
225 *
226 * @return EINA_TRUE if the client is connected to the server or EINA_FALSE
227 * otherwise.
228 */
229EAPI Eina_Bool elm_thumb_ethumb_client_connected_get(void);
230
231/**
232 * Make the thumbnail 'editable'.
233 *
234 * @param obj Thumb object.
235 * @param edit Turn on or off editability. Default is @c EINA_FALSE.
236 *
237 * This means the thumbnail is a valid drag target for drag and drop, and can be
238 * cut or pasted too.
239 *
240 * @see elm_thumb_editable_get()
241 *
242 * @ingroup Thumb
243 */
244EAPI Eina_Bool elm_thumb_editable_set(Evas_Object *obj, Eina_Bool edit);
245
246/**
247 * Make the thumbnail 'editable'.
248 *
249 * @param obj Thumb object.
250 * @return Editability.
251 *
252 * This means the thumbnail is a valid drag target for drag and drop, and can be
253 * cut or pasted too.
254 *
255 * @see elm_thumb_editable_set()
256 *
257 * @ingroup Thumb
258 */
259EAPI Eina_Bool elm_thumb_editable_get(const Evas_Object *obj);
260
261/**
262 * @}
263 */
diff --git a/libraries/elementary/src/lib/elm_toolbar.c b/libraries/elementary/src/lib/elm_toolbar.c
new file mode 100644
index 0000000..2a883c1
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_toolbar.c
@@ -0,0 +1,2061 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4#include "els_box.h"
5#include "els_icon.h"
6
7typedef struct _Widget_Data Widget_Data;
8typedef struct _Elm_Toolbar_Item Elm_Toolbar_Item;
9
10struct _Widget_Data
11{
12 Evas_Object *scr, *bx;
13 Evas_Object *menu_parent;
14 Eina_Inlist *items;
15 Elm_Toolbar_Item *more_item, *selected_item;
16 Elm_Toolbar_Shrink_Mode shrink_mode;
17 Elm_Icon_Lookup_Order lookup_order;
18 int icon_size;
19 unsigned int item_count;
20 double align;
21 Elm_Object_Select_Mode select_mode;
22 Eina_Bool homogeneous : 1;
23 Eina_Bool vertical : 1;
24 Eina_Bool long_press : 1;
25 Ecore_Timer *long_timer;
26 Ecore_Job *resize_job;
27};
28
29struct _Elm_Toolbar_Item
30{
31 ELM_WIDGET_ITEM;
32 EINA_INLIST;
33 const char *label;
34 const char *icon_str;
35 Evas_Object *icon;
36 Evas_Object *object;
37 Evas_Object *o_menu;
38 Evas_Smart_Cb func;
39 struct
40 {
41 int priority;
42 Eina_Bool visible : 1;
43 } prio;
44 Eina_Bool selected : 1;
45 Eina_Bool separator : 1;
46 Eina_Bool menu : 1;
47 Eina_List *states;
48 Eina_List *current_state;
49};
50
51#define ELM_TOOLBAR_ITEM_FROM_INLIST(item) \
52 ((item) ? EINA_INLIST_CONTAINER_GET(item, Elm_Toolbar_Item) : NULL)
53
54struct _Elm_Toolbar_Item_State
55{
56 const char *label;
57 const char *icon_str;
58 Evas_Object *icon;
59 Evas_Smart_Cb func;
60 const void *data;
61};
62
63static const char *widtype = NULL;
64static void _item_show(Elm_Toolbar_Item *it);
65static void _item_select(Elm_Toolbar_Item *it);
66static void _item_unselect(Elm_Toolbar_Item *it);
67static void _del_pre_hook(Evas_Object *obj);
68static void _del_hook(Evas_Object *obj);
69static void _mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
70static void _mirrored_set_item(Evas_Object *obj, Elm_Toolbar_Item *it, Eina_Bool mirrored);
71static void _theme_hook(Evas_Object *obj);
72static void _sizing_eval(Evas_Object *obj);
73static void _resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
74static void _menu_move_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
75static void _menu_hide(void *data, Evas *e, Evas_Object *obj, void *event_info);
76static void _layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data);
77static 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 *sig);
78static void _item_label_set(Elm_Toolbar_Item *item, const char *label, const char *sig);
79
80static const char SIG_CLICKED[] = "clicked";
81static const char SIG_LONGPRESSED[] = "longpressed";
82static const char SIG_CLICKED_DOUBLE[] = "clicked,double";
83
84static const Evas_Smart_Cb_Description _signals[] = {
85 {SIG_CLICKED, ""},
86 {SIG_LONGPRESSED, ""},
87 {SIG_CLICKED_DOUBLE, ""},
88 {NULL, NULL}
89};
90
91static void
92_item_disable_hook(Elm_Object_Item *it)
93{
94 Widget_Data *wd;
95 Elm_Toolbar_Item *toolbar_it = (Elm_Toolbar_Item *)it;
96
97 wd = elm_widget_data_get(WIDGET(toolbar_it));
98 if (!wd) return;
99
100 if (elm_widget_item_disabled_get(toolbar_it))
101 {
102 edje_object_signal_emit(VIEW(toolbar_it), "elm,state,disabled", "elm");
103 elm_widget_signal_emit(toolbar_it->icon, "elm,state,disabled", "elm");
104 }
105 else
106 {
107 edje_object_signal_emit(VIEW(toolbar_it), "elm,state,enabled", "elm");
108 elm_widget_signal_emit(toolbar_it->icon, "elm,state,enabled", "elm");
109 }
110 _resize(WIDGET(toolbar_it), NULL, NULL, NULL);
111}
112
113static Eina_Bool
114_item_icon_set(Evas_Object *icon_obj, const char *type, const char *icon)
115{
116 char icon_str[512];
117
118 if ((!type) || (!*type)) goto end;
119 if ((!icon) || (!*icon)) return EINA_FALSE;
120 if ((snprintf(icon_str, sizeof(icon_str), "%s%s", type, icon) > 0)
121 && (elm_icon_standard_set(icon_obj, icon_str)))
122 return EINA_TRUE;
123end:
124 if (elm_icon_standard_set(icon_obj, icon))
125 return EINA_TRUE;
126 WRN("couldn't find icon definition for '%s'", icon);
127 return EINA_FALSE;
128}
129
130static int
131_elm_toolbar_icon_size_get(Widget_Data *wd)
132{
133 const char *icon_size = edje_object_data_get(
134 elm_smart_scroller_edje_object_get(wd->scr), "icon_size");
135 if (icon_size)
136 return atoi(icon_size);
137 return _elm_config->icon_size;
138}
139
140static void
141_item_show(Elm_Toolbar_Item *it)
142{
143 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
144 Evas_Coord x, y, w, h, bx, by;
145
146 if (!wd) return;
147 evas_object_geometry_get(wd->bx, &bx, &by, NULL, NULL);
148 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
149 elm_smart_scroller_child_region_show(wd->scr, x - bx, y - by, w, h);
150}
151
152static void
153_item_unselect(Elm_Toolbar_Item *item)
154{
155 Widget_Data *wd;
156 if ((!item) || (!item->selected)) return;
157 wd = elm_widget_data_get(WIDGET(item));
158 if (!wd) return;
159 item->selected = EINA_FALSE;
160 wd->selected_item = NULL;
161 edje_object_signal_emit(VIEW(item), "elm,state,unselected", "elm");
162 elm_widget_signal_emit(item->icon, "elm,state,unselected", "elm");
163}
164
165static void
166_item_select(Elm_Toolbar_Item *it)
167{
168 Elm_Toolbar_Item *it2;
169 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
170 Evas_Object *obj2;
171 Eina_Bool sel;
172
173 if (!wd) return;
174 if (elm_widget_item_disabled_get(it) || (it->separator) || (it->object)) return;
175 sel = it->selected;
176
177 if (wd->select_mode != ELM_OBJECT_SELECT_MODE_NONE)
178 {
179 if (sel)
180 {
181 if (wd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) return;
182 _item_unselect(it);
183 }
184 else
185 {
186 it2 = (Elm_Toolbar_Item *)
187 elm_toolbar_selected_item_get(WIDGET(it));
188 _item_unselect(it2);
189
190 it->selected = EINA_TRUE;
191 wd->selected_item = it;
192 edje_object_signal_emit(VIEW(it), "elm,state,selected", "elm");
193 elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
194 _item_show(it);
195 }
196 }
197 obj2 = WIDGET(it);
198 if (it->menu && (!sel))
199 {
200 evas_object_show(it->o_menu);
201 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_RESIZE,
202 _menu_move_resize, it);
203 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOVE,
204 _menu_move_resize, it);
205
206 _menu_move_resize(it, NULL, NULL, NULL);
207 }
208 if (it->func) it->func((void *)(it->base.data), WIDGET(it), it);
209 evas_object_smart_callback_call(obj2, SIG_CLICKED, it);
210}
211
212static void
213_menu_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
214{
215 Elm_Toolbar_Item *selected;
216 Elm_Toolbar_Item *it = data;
217 selected = (Elm_Toolbar_Item *) elm_toolbar_selected_item_get(WIDGET(it));
218 _item_unselect(selected);
219}
220
221static void
222_menu_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
223{
224 // avoid hide being emitted during object deletion
225 evas_object_event_callback_del_full
226 (obj, EVAS_CALLBACK_HIDE, _menu_hide, data);
227}
228
229static void
230_menu_move_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
231{
232 Elm_Toolbar_Item *it = data;
233 Evas_Coord x,y,w,h;
234 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
235
236 if ((!wd) || (!wd->menu_parent)) return;
237 evas_object_geometry_get(VIEW(it), &x, &y, &w, &h);
238 elm_menu_move(it->o_menu, x, y+h);
239}
240
241static void
242_item_del(Elm_Toolbar_Item *it)
243{
244 Elm_Toolbar_Item_State *it_state;
245 _item_unselect(it);
246 EINA_LIST_FREE(it->states, it_state)
247 {
248 if (it->icon == it_state->icon)
249 it->icon = NULL;
250 eina_stringshare_del(it_state->label);
251 eina_stringshare_del(it_state->icon_str);
252 if (it_state->icon) evas_object_del(it_state->icon);
253 free(it_state);
254 }
255 eina_stringshare_del(it->label);
256 eina_stringshare_del(it->icon_str);
257 if (it->icon) evas_object_del(it->icon);
258 if (it->object) evas_object_del(it->object);
259 //TODO: See if checking for wd->menu_parent is necessary before deleting menu
260 if (it->o_menu) evas_object_del(it->o_menu);
261}
262
263static void
264_del_pre_hook(Evas_Object *obj)
265{
266 Widget_Data *wd = elm_widget_data_get(obj);
267 Elm_Toolbar_Item *it, *next;
268
269 if (!wd) return;
270 it = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
271 while (it)
272 {
273 next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(it)->next);
274 _item_del(it);
275 elm_widget_item_free(it);
276 it = next;
277 }
278 if (wd->more_item)
279 {
280 _item_del(wd->more_item);
281 elm_widget_item_free(wd->more_item);
282 }
283 if (wd->long_timer)
284 {
285 ecore_timer_del(wd->long_timer);
286 wd->long_timer = NULL;
287 }
288}
289
290static void
291_del_hook(Evas_Object *obj)
292{
293 Widget_Data *wd = elm_widget_data_get(obj);
294
295 if (!wd) return;
296 free(wd);
297}
298
299
300static void
301_mirrored_set_item(Evas_Object *obj __UNUSED__, Elm_Toolbar_Item *it, Eina_Bool mirrored)
302{
303 edje_object_mirrored_set(VIEW(it), mirrored);
304 elm_widget_mirrored_set(it->o_menu, mirrored);
305}
306
307static void
308_theme_hook_item(Evas_Object *obj, Elm_Toolbar_Item *it, double scale, int icon_size)
309{
310 Widget_Data *wd = elm_widget_data_get(obj);
311 Evas_Object *view = VIEW(it);
312 Evas_Coord mw, mh;
313 const char *style = elm_widget_style_get(obj);
314
315 _mirrored_set_item(obj, it, elm_widget_mirrored_get(obj));
316 edje_object_scale_set(view, scale);
317 if (!it->separator && !it->object)
318 {
319 _elm_theme_object_set(obj, view, "toolbar", "item", style);
320 if (it->selected)
321 {
322 edje_object_signal_emit(view, "elm,state,selected", "elm");
323 elm_widget_signal_emit(it->icon, "elm,state,selected", "elm");
324 }
325 if (elm_widget_item_disabled_get(it))
326 {
327 edje_object_signal_emit(view, "elm,state,disabled", "elm");
328 elm_widget_signal_emit(it->icon, "elm,state,disabled", "elm");
329 }
330 if (it->icon)
331 {
332 int ms = 0;
333
334 ms = ((double)icon_size * scale);
335 evas_object_size_hint_min_set(it->icon, ms, ms);
336 evas_object_size_hint_max_set(it->icon, ms, ms);
337 edje_object_part_swallow(view, "elm.swallow.icon", it->icon);
338 }
339 edje_object_part_text_escaped_set(view, "elm.text", it->label);
340 }
341 else
342 {
343 if (!it->object)
344 {
345 _elm_theme_object_set(obj, view, "toolbar", "separator", style);
346 if (wd->vertical)
347 {
348 evas_object_size_hint_weight_set(view, EVAS_HINT_EXPAND, -1.0);
349 evas_object_size_hint_align_set(view, EVAS_HINT_FILL, 0.5);
350 }
351 else
352 {
353 evas_object_size_hint_weight_set(view, -1.0, EVAS_HINT_EXPAND);
354 evas_object_size_hint_align_set(view, 0.5, EVAS_HINT_FILL);
355 }
356 }
357 else
358 {
359 _elm_theme_object_set(obj, view, "toolbar", "object", style);
360 edje_object_part_swallow(view, "elm.swallow.object", it->object);
361 }
362 }
363
364 mw = mh = -1;
365 if (!it->separator && !it->object)
366 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
367 edje_object_size_min_restricted_calc(view, &mw, &mh, mw, mh);
368 if (!it->separator && !it->object)
369 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
370 evas_object_size_hint_min_set(view, mw, mh);
371}
372
373static void
374_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
375{
376 Widget_Data *wd = elm_widget_data_get(obj);
377 Elm_Toolbar_Item *it;
378
379 EINA_INLIST_FOREACH(wd->items, it)
380 _mirrored_set_item(obj, it, mirrored);
381 if (wd->more_item)
382 _mirrored_set_item(obj, wd->more_item, mirrored);
383}
384
385static void
386_theme_hook(Evas_Object *obj)
387{
388 Widget_Data *wd = elm_widget_data_get(obj);
389 Elm_Toolbar_Item *it;
390 double scale = 0;
391
392 if (!wd) return;
393 _elm_widget_mirrored_reload(obj);
394 elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", elm_widget_style_get(obj));
395 _mirrored_set(obj, elm_widget_mirrored_get(obj));
396 scale = (elm_widget_scale_get(obj) * _elm_config->scale);
397 edje_object_scale_set(wd->scr, scale);
398 wd->icon_size = _elm_toolbar_icon_size_get(wd);
399 EINA_INLIST_FOREACH(wd->items, it)
400 _theme_hook_item(obj, it, scale, wd->icon_size);
401 if (wd->more_item)
402 _theme_hook_item(obj, wd->more_item, scale, wd->icon_size);
403 _sizing_eval(obj);
404}
405
406static void
407_item_text_set_hook(Elm_Object_Item *it,
408 const char *part,
409 const char *label)
410{
411 if (part && strcmp(part, "default")) return;
412 _item_label_set(((Elm_Toolbar_Item *)it), label, "elm,state,label_set");
413}
414
415static const char *
416_item_text_get_hook(const Elm_Object_Item *it, const char *part)
417{
418 if (part && strcmp(part, "default")) return NULL;
419 return ((Elm_Toolbar_Item *)it)->label;
420}
421
422static void
423_item_content_set_hook(Elm_Object_Item *it,
424 const char *part,
425 Evas_Object *content)
426{
427 double scale;
428 if (part && strcmp(part, "object")) return;
429 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *) it;
430 Evas_Object *obj = WIDGET(item);
431 Widget_Data *wd = elm_widget_data_get(obj);
432 if (!wd || !obj) return;
433 if (item->object == content) return;
434
435 if (item->object) evas_object_del(item->object);
436
437 item->object = content;
438 if (item->object)
439 elm_widget_sub_object_add(obj, item->object);
440 scale = (elm_widget_scale_get(obj) * _elm_config->scale);
441 _theme_hook_item(obj, item, scale, wd->icon_size);
442}
443
444static Evas_Object *
445_item_content_get_hook(const Elm_Object_Item *it, const char *part)
446{
447 if (part && strcmp(part, "object")) return NULL;
448 return ((Elm_Toolbar_Item *) it)->object;
449}
450
451static Evas_Object *
452_item_content_unset_hook(Elm_Object_Item *it, const char *part)
453{
454 Evas_Object *o;
455 double scale;
456
457 if (part && strcmp(part, "object")) return NULL;
458 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *) it;
459 Evas_Object *obj = WIDGET(item);
460 Widget_Data *wd = elm_widget_data_get(obj);
461
462 edje_object_part_unswallow(VIEW(it), item->object);
463 elm_widget_sub_object_del(obj, item->object);
464 o = item->object;
465 item->object = NULL;
466 scale = (elm_widget_scale_get(obj) * _elm_config->scale);
467 _theme_hook_item(obj, item, scale, wd->icon_size);
468 return o;
469}
470
471static void
472_translate_hook(Evas_Object *obj)
473{
474 evas_object_smart_callback_call(obj, "language,changed", NULL);
475}
476
477static void
478_sizing_eval(Evas_Object *obj)
479{
480 Widget_Data *wd = elm_widget_data_get(obj);
481 Evas_Coord minw = -1, minh = -1, minw_bx = -1, minh_bx = -1;
482 Evas_Coord vw = 0, vh = 0;
483 Evas_Coord w, h;
484
485 if (!wd) return;
486 evas_object_smart_need_recalculate_set(wd->bx, EINA_TRUE);
487 evas_object_smart_calculate(wd->bx);
488 edje_object_size_min_calc(elm_smart_scroller_edje_object_get(wd->scr),
489 &minw, &minh);
490 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
491 if (w < minw) w = minw;
492 if (h < minh) h = minh;
493 evas_object_resize(wd->scr, w, h);
494
495 evas_object_size_hint_min_get(wd->bx, &minw_bx, &minh_bx);
496// if (wd->vertical && (h > minh)) minh = h;
497// if ((!wd->vertical) && (w > minw)) minw = w;
498 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
499 if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_NONE)
500 {
501 if (wd->vertical)
502 {
503 minw = minw_bx + (w - vw);
504 minh = minh_bx + (h - vh);
505 }
506 else
507 {
508 minw = minw_bx + (w - vw);
509 minh = minh_bx + (h - vh);
510 }
511 }
512 else if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
513 {
514 minw = minw_bx + (w - vw);
515 minh = minh_bx + (h - vh);
516 if (minw_bx < vw) minw_bx = vw;
517 if (minh_bx < vh) minh_bx = vh;
518 }
519 else
520 {
521 if (wd->vertical)
522 {
523 minw = minw_bx + (w - vw);
524 minh = h - vh;
525 }
526 else
527 {
528 minw = w - vw;
529 minh = minh_bx + (h - vh);
530 }
531// if (wd->vertical) minh = h - vh;
532// else minw = w - vw;
533// minh = minh + (h - vh);
534 }
535 evas_object_resize(wd->bx, minw_bx, minh_bx);
536 evas_object_size_hint_min_set(obj, minw, minh);
537 evas_object_size_hint_max_set(obj, -1, -1);
538}
539
540static void
541_item_menu_create(Widget_Data *wd, Elm_Toolbar_Item *item)
542{
543 item->o_menu = elm_menu_add(VIEW(item));
544 item->menu = EINA_TRUE;
545 if (wd->menu_parent)
546 elm_menu_parent_set(item->o_menu, wd->menu_parent);
547 evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_HIDE,
548 _menu_hide, item);
549 evas_object_event_callback_add(item->o_menu, EVAS_CALLBACK_DEL,
550 _menu_del, item);
551}
552
553static void
554_item_menu_destroy(Elm_Toolbar_Item *item)
555{
556 if (item->o_menu)
557 {
558 evas_object_del(item->o_menu);
559 item->o_menu = NULL;
560 }
561 item->menu = EINA_FALSE;
562}
563
564static int
565_toolbar_item_prio_compare_cb(const void *i1, const void *i2)
566{
567 const Elm_Toolbar_Item *eti1 = i1;
568 const Elm_Toolbar_Item *eti2 = i2;
569
570 if (!eti2) return 1;
571 if (!eti1) return -1;
572
573 return eti2->prio.priority - eti1->prio.priority;
574}
575
576static void
577_fix_items_visibility(Widget_Data *wd, Evas_Coord *iw, Evas_Coord vw)
578{
579 Elm_Toolbar_Item *it;
580 Eina_List *sorted = NULL;
581 Evas_Coord ciw = 0, cih = 0;
582
583 EINA_INLIST_FOREACH(wd->items, it)
584 {
585 sorted = eina_list_sorted_insert(sorted,
586 _toolbar_item_prio_compare_cb, it);
587 }
588
589 if (wd->more_item)
590 {
591 evas_object_geometry_get(wd->VIEW(more_item), NULL, NULL, &ciw, &cih);
592 if (wd->vertical) *iw += cih;
593 else *iw += ciw;
594 }
595 EINA_LIST_FREE(sorted, it)
596 {
597 evas_object_geometry_get(VIEW(it), NULL, NULL, &ciw, &cih);
598 if (wd->vertical) *iw += cih;
599 else *iw += ciw;
600 it->prio.visible = (*iw <= vw);
601 }
602}
603
604static void
605_elm_toolbar_item_menu_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
606{
607 Elm_Toolbar_Item *it = data;
608 if (it->func) it->func((void *)(it->base.data), WIDGET(it), it);
609}
610
611static void
612_resize_job(void *data)
613{
614 Evas_Object *obj = (Evas_Object *)data;
615 Widget_Data *wd = elm_widget_data_get(obj);
616 Evas_Coord mw, mh, vw = 0, vh = 0, w = 0, h = 0;
617 Elm_Toolbar_Item *it;
618
619 if (!wd) return;
620 wd->resize_job = NULL;
621 elm_smart_scroller_child_viewport_size_get(wd->scr, &vw, &vh);
622 evas_object_size_hint_min_get(wd->bx, &mw, &mh);
623 evas_object_geometry_get(wd->bx, NULL, NULL, &w, &h);
624 if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
625 {
626 Evas_Coord iw = 0, ih = 0, more_w = 0, more_h = 0;
627
628 if (wd->vertical)
629 {
630 evas_object_resize(wd->bx, w, vh);
631 _fix_items_visibility(wd, &ih, vh);
632 }
633 else
634 {
635 evas_object_resize(wd->bx, vw, h);
636 _fix_items_visibility(wd, &iw, vw);
637 }
638 evas_object_geometry_get(wd->VIEW(more_item), NULL, NULL,
639 &more_w, &more_h);
640 if (wd->vertical)
641 {
642 if ((ih - more_h) <= vh) ih -= more_h;
643 }
644 else
645 {
646 if ((iw - more_w) <= vw) iw -= more_w;
647 }
648
649 /* All items are removed from the box object, since removing individual
650 * items won't trigger a resize. Items are be readded below. */
651 evas_object_box_remove_all(wd->bx, EINA_FALSE);
652 if (((wd->vertical) && (ih > vh)) ||
653 ((!wd->vertical) && (iw > vw)))
654 {
655 Evas_Object *menu;
656
657 _item_menu_destroy(wd->more_item);
658 _item_menu_create(wd, wd->more_item);
659 menu = elm_toolbar_item_menu_get((Elm_Object_Item *)wd->more_item);
660 EINA_INLIST_FOREACH(wd->items, it)
661 {
662 if (!it->prio.visible)
663 {
664 if (it->separator)
665 elm_menu_item_separator_add(menu, NULL);
666 else
667 {
668 Elm_Object_Item *menu_it;
669 menu_it = elm_menu_item_add
670 (menu, NULL, it->icon_str, it->label,
671 _elm_toolbar_item_menu_cb, it);
672 elm_object_item_disabled_set
673 (menu_it, elm_widget_item_disabled_get(it));
674 if (it->o_menu)
675 elm_menu_clone(it->o_menu, menu, menu_it);
676 }
677 evas_object_hide(VIEW(it));
678 }
679 else
680 {
681 evas_object_box_append(wd->bx, VIEW(it));
682 evas_object_show(VIEW(it));
683 }
684 }
685 evas_object_box_append(wd->bx, wd->VIEW(more_item));
686 evas_object_show(wd->VIEW(more_item));
687 }
688 else
689 {
690 /* All items are visible, show them all (except for the "More"
691 * button, of course). */
692 EINA_INLIST_FOREACH(wd->items, it)
693 {
694 evas_object_show(VIEW(it));
695 evas_object_box_append(wd->bx, VIEW(it));
696 }
697 evas_object_hide(wd->VIEW(more_item));
698 }
699 }
700 else if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
701 {
702 Evas_Coord iw = 0, ih = 0;
703
704 if (wd->vertical)
705 {
706 evas_object_resize(wd->bx, w, vh);
707 _fix_items_visibility(wd, &ih, vh);
708 }
709 else
710 {
711 evas_object_resize(wd->bx, vw, h);
712 _fix_items_visibility(wd, &iw, vw);
713 }
714 evas_object_box_remove_all(wd->bx, EINA_FALSE);
715 if (((wd->vertical) && (ih > vh)) ||
716 ((!wd->vertical) && (iw > vw)))
717 {
718 EINA_INLIST_FOREACH(wd->items, it)
719 {
720 if (!it->prio.visible)
721 evas_object_hide(VIEW(it));
722 else
723 {
724 evas_object_box_append(wd->bx, VIEW(it));
725 evas_object_show(VIEW(it));
726 }
727 }
728 }
729 else
730 {
731 /* All items are visible, show them all */
732 EINA_INLIST_FOREACH(wd->items, it)
733 {
734 evas_object_show(VIEW(it));
735 evas_object_box_append(wd->bx, VIEW(it));
736 }
737 }
738 }
739 else if (wd->shrink_mode == ELM_TOOLBAR_SHRINK_EXPAND)
740 {
741 if ((vw >= mw) && (vh >= mh))
742 evas_object_resize(wd->bx, vw, vh);
743 else if (vw < mw)
744 evas_object_resize(wd->bx, mw, vh);
745 else if (vh < mh)
746 evas_object_resize(wd->bx, vw, mh);
747 }
748 else
749 {
750 if (wd->vertical)
751 {
752 if ((vh >= mh) && (h != vh)) evas_object_resize(wd->bx, w, vh);
753 }
754 else
755 {
756 if ((vw >= mw) && (w != vw)) evas_object_resize(wd->bx, vw, h);
757 }
758 EINA_INLIST_FOREACH(wd->items, it)
759 {
760 if (it->selected)
761 {
762 _item_show(it);
763 break;
764 }
765 }
766 }
767
768 _mirrored_set(obj, elm_widget_mirrored_get(obj));
769}
770
771static void
772_resize_item(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
773{
774 _sizing_eval(data);
775 _resize(data, NULL, NULL, NULL);
776}
777
778static void
779_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
780{
781 Widget_Data *wd = elm_widget_data_get(data);
782 if (!wd->resize_job)
783 wd->resize_job = ecore_job_add(_resize_job, data);
784}
785
786static void
787_select_filter(Elm_Toolbar_Item *it, Evas_Object *obj __UNUSED__, const char *emission, const char *source __UNUSED__)
788{
789 int button;
790 char buf[sizeof("elm,action,click,") + 1];
791
792 button = atoi(emission + sizeof("mouse,clicked,") - 1);
793 if (button == 1) return; /* regular left click event */
794 snprintf(buf, sizeof(buf), "elm,action,click,%d", button);
795 edje_object_signal_emit(VIEW(it), buf, "elm");
796}
797
798static void
799_select(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
800{
801 Elm_Toolbar_Item *it = data;
802
803 if ((_elm_config->access_mode == ELM_ACCESS_MODE_OFF) ||
804 (_elm_access_2nd_click_timeout(VIEW(it))))
805 {
806 if (_elm_config->access_mode != ELM_ACCESS_MODE_OFF)
807 _elm_access_say(E_("Selected"));
808 _item_select(it);
809 }
810}
811
812static Eina_Bool
813_long_press(Elm_Toolbar_Item *it)
814{
815 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
816 wd->long_timer = NULL;
817 wd->long_press = EINA_TRUE;
818 evas_object_smart_callback_call(WIDGET(it), SIG_LONGPRESSED, it);
819 return ECORE_CALLBACK_CANCEL;
820}
821
822static void
823_mouse_down(Elm_Toolbar_Item *it, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Down *ev)
824{
825 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
826 if (!wd) return;
827 if (ev->button != 1) return;
828 if (ev->flags & EVAS_BUTTON_DOUBLE_CLICK)
829 evas_object_smart_callback_call(WIDGET(it), SIG_CLICKED_DOUBLE, it);
830 wd->long_press = EINA_FALSE;
831 if (wd->long_timer) ecore_timer_interval_set(wd->long_timer, _elm_config->longpress_timeout);
832 else wd->long_timer = ecore_timer_add(_elm_config->longpress_timeout, (Ecore_Task_Cb)_long_press, it);
833}
834
835static void
836_mouse_up(Elm_Toolbar_Item *it, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Up *ev)
837{
838 Widget_Data *wd = elm_widget_data_get(WIDGET(it));
839 if (!wd) return;
840 if (ev->button != 1) return;
841 if (wd->long_timer)
842 {
843 ecore_timer_del(wd->long_timer);
844 wd->long_timer = NULL;
845 }
846}
847
848static void
849_mouse_in(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
850{
851 Elm_Toolbar_Item *it = data;
852 edje_object_signal_emit(VIEW(it), "elm,state,highlighted", "elm");
853 elm_widget_signal_emit(it->icon, "elm,state,highlighted", "elm");
854}
855
856static void
857_mouse_out(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
858{
859 Elm_Toolbar_Item *it = data;
860 edje_object_signal_emit(VIEW(it), "elm,state,unhighlighted", "elm");
861 elm_widget_signal_emit(it->icon, "elm,state,unhighlighted", "elm");
862}
863
864static void
865_layout(Evas_Object *o, Evas_Object_Box_Data *priv, void *data)
866{
867 Evas_Object *obj = (Evas_Object *) data;
868 Widget_Data *wd = elm_widget_data_get(obj);
869 if (!wd) return;
870 _els_box_layout(o, priv, !wd->vertical, wd->homogeneous,
871 elm_widget_mirrored_get(obj));
872}
873
874static char *
875_access_info_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Elm_Widget_Item *item)
876{
877 Elm_Toolbar_Item *it = (Elm_Toolbar_Item *)item;
878 const char *txt = item->access_info;
879 if (!txt) txt = it->label;
880 if (txt) return strdup(txt);
881 return NULL;
882}
883
884static char *
885_access_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, Elm_Widget_Item *item __UNUSED__)
886{
887 Elm_Toolbar_Item *it = (Elm_Toolbar_Item *)item;
888 if (it->separator)
889 return strdup(E_("Separator"));
890 else if (elm_widget_item_disabled_get(it))
891 return strdup(E_("State: Disabled"));
892 else if (it->selected)
893 return strdup(E_("State: Selected"));
894 else if (it->menu)
895 return strdup(E_("Has menu"));
896 return NULL;
897}
898
899static Eina_Bool
900_item_del_pre_hook(Elm_Object_Item *it)
901{
902 Widget_Data *wd;
903 Evas_Object *obj2;
904 Elm_Toolbar_Item *item, *next;
905 item = (Elm_Toolbar_Item *)it;
906
907 wd = elm_widget_data_get(WIDGET(item));
908 if (!wd) return EINA_FALSE;
909
910 obj2 = WIDGET(item);
911 next = ELM_TOOLBAR_ITEM_FROM_INLIST(EINA_INLIST_GET(item)->next);
912 wd->items = eina_inlist_remove(wd->items, EINA_INLIST_GET(item));
913 wd->item_count--;
914 if (!next) next = ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
915 if ((wd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS) &&
916 item->selected && next) _item_select(next);
917 _item_del(item);
918 _theme_hook(obj2);
919
920 return EINA_TRUE;
921}
922
923static Elm_Toolbar_Item *
924_item_new(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
925{
926 Widget_Data *wd = elm_widget_data_get(obj);
927 Evas_Object *icon_obj;
928 Evas_Coord mw, mh;
929 Elm_Toolbar_Item *it;
930
931 icon_obj = elm_icon_add(obj);
932 elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
933 if (!icon_obj) return NULL;
934 it = elm_widget_item_new(obj, Elm_Toolbar_Item);
935 if (!it)
936 {
937 evas_object_del(icon_obj);
938 return NULL;
939 }
940
941 elm_widget_item_del_pre_hook_set(it, _item_del_pre_hook);
942 elm_widget_item_disable_hook_set(it, _item_disable_hook);
943 elm_widget_item_text_set_hook_set(it, _item_text_set_hook);
944 elm_widget_item_text_get_hook_set(it, _item_text_get_hook);
945 elm_widget_item_content_set_hook_set(it, _item_content_set_hook);
946 elm_widget_item_content_get_hook_set(it, _item_content_get_hook);
947 elm_widget_item_content_unset_hook_set(it, _item_content_unset_hook);
948
949 it->label = eina_stringshare_add(label);
950 it->prio.visible = 1;
951 it->prio.priority = 0;
952 it->func = func;
953 it->separator = EINA_FALSE;
954 it->object = NULL;
955 it->base.data = data;
956 VIEW(it) = edje_object_add(evas_object_evas_get(obj));
957 _elm_access_item_register(&it->base, VIEW(it));
958 _elm_access_text_set(_elm_access_item_get(&it->base),
959 ELM_ACCESS_TYPE, E_("Tool Item"));
960 _elm_access_callback_set(_elm_access_item_get(&it->base),
961 ELM_ACCESS_INFO, _access_info_cb, it);
962 _elm_access_callback_set(_elm_access_item_get(&it->base),
963 ELM_ACCESS_STATE, _access_state_cb, it);
964
965 if (_item_icon_set(icon_obj, "toolbar/", icon))
966 {
967 it->icon = icon_obj;
968 it->icon_str = eina_stringshare_add(icon);
969 }
970 else
971 {
972 it->icon = NULL;
973 it->icon_str = NULL;
974 evas_object_del(icon_obj);
975 }
976
977 _elm_theme_object_set(obj, VIEW(it), "toolbar", "item",
978 elm_widget_style_get(obj));
979 edje_object_signal_callback_add(VIEW(it), "elm,action,click", "elm",
980 _select, it);
981 edje_object_signal_callback_add(VIEW(it), "mouse,clicked,*", "*",
982 (Edje_Signal_Cb)_select_filter, it);
983 edje_object_signal_callback_add(VIEW(it), "elm,mouse,in", "elm",
984 _mouse_in, it);
985 edje_object_signal_callback_add(VIEW(it), "elm,mouse,out", "elm",
986 _mouse_out, it);
987 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_DOWN,
988 (Evas_Object_Event_Cb)_mouse_down, it);
989 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_MOUSE_UP,
990 (Evas_Object_Event_Cb)_mouse_up, it);
991 elm_widget_sub_object_add(obj, VIEW(it));
992 if (it->icon)
993 {
994 int ms = 0;
995
996 ms = ((double)wd->icon_size * _elm_config->scale);
997 evas_object_size_hint_min_set(it->icon, ms, ms);
998 evas_object_size_hint_max_set(it->icon, ms, ms);
999 edje_object_part_swallow(VIEW(it), "elm.swallow.icon", it->icon);
1000 evas_object_show(it->icon);
1001 elm_widget_sub_object_add(obj, it->icon);
1002 }
1003 edje_object_part_text_escaped_set(VIEW(it), "elm.text", it->label);
1004 mw = mh = -1;
1005 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1006 edje_object_size_min_restricted_calc(VIEW(it), &mw, &mh, mw, mh);
1007 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1008 if (wd->shrink_mode != ELM_TOOLBAR_SHRINK_EXPAND)
1009 {
1010 if (wd->vertical)
1011 {
1012 evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND, -1.0);
1013 evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, 0.5);
1014 }
1015 else
1016 {
1017 evas_object_size_hint_weight_set(VIEW(it), -1.0, EVAS_HINT_EXPAND);
1018 evas_object_size_hint_align_set(VIEW(it), 0.5, EVAS_HINT_FILL);
1019 }
1020 }
1021 else
1022 {
1023 evas_object_size_hint_weight_set(VIEW(it), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1024 evas_object_size_hint_align_set(VIEW(it), EVAS_HINT_FILL, EVAS_HINT_FILL);
1025 }
1026 evas_object_size_hint_min_set(VIEW(it), mw, mh);
1027 evas_object_size_hint_max_set(VIEW(it), -1, -1);
1028 evas_object_event_callback_add(VIEW(it), EVAS_CALLBACK_RESIZE,
1029 _resize_item, obj);
1030 if ((!wd->items) && (wd->select_mode == ELM_OBJECT_SELECT_MODE_ALWAYS))
1031 _item_select(it);
1032 wd->item_count++;
1033 return it;
1034}
1035
1036static void
1037_elm_toolbar_item_label_update(Elm_Toolbar_Item *item)
1038{
1039 Evas_Coord mw = -1, mh = -1;
1040 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1041 edje_object_part_text_escaped_set(VIEW(item), "elm.text", item->label);
1042
1043 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1044 edje_object_size_min_restricted_calc(VIEW(item), &mw, &mh, mw, mh);
1045 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1046 if (wd->shrink_mode != ELM_TOOLBAR_SHRINK_EXPAND)
1047 {
1048 if (wd->vertical)
1049 {
1050 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, -1.0);
1051 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, 0.5);
1052 }
1053 else
1054 {
1055 evas_object_size_hint_weight_set(VIEW(item), -1.0, EVAS_HINT_EXPAND);
1056 evas_object_size_hint_align_set(VIEW(item), 0.5, EVAS_HINT_FILL);
1057 }
1058 }
1059 else
1060 {
1061 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1062 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
1063 }
1064 evas_object_size_hint_min_set(VIEW(item), mw, mh);
1065}
1066
1067static void
1068_elm_toolbar_item_label_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1069{
1070 Elm_Toolbar_Item *item = data;
1071 _elm_toolbar_item_label_update(item);
1072 edje_object_signal_callback_del(obj, emission, source,
1073 _elm_toolbar_item_label_set_cb);
1074 edje_object_signal_emit (VIEW(item), "elm,state,label,reset", "elm");
1075}
1076
1077static void
1078_item_label_set(Elm_Toolbar_Item *item, const char *label, const char *sig)
1079{
1080 const char *s;
1081
1082 if ((label) && (item->label) && (!strcmp(label, item->label))) return;
1083
1084 eina_stringshare_replace(&item->label, label);
1085 s = edje_object_data_get(VIEW(item), "transition_animation_on");
1086 if ((s) && (atoi(s)))
1087 {
1088 edje_object_part_text_escaped_set(VIEW(item), "elm.text_new", item->label);
1089 edje_object_signal_emit (VIEW(item), sig, "elm");
1090 edje_object_signal_callback_add(VIEW(item),
1091 "elm,state,label_set,done", "elm",
1092 _elm_toolbar_item_label_set_cb, item);
1093 }
1094 else
1095 _elm_toolbar_item_label_update(item);
1096 _resize(WIDGET(item), NULL, NULL, NULL);
1097}
1098
1099static void
1100_elm_toolbar_item_icon_update(Elm_Toolbar_Item *item)
1101{
1102 Elm_Toolbar_Item_State *it_state;
1103 Eina_List *l;
1104 Evas_Coord mw = -1, mh = -1;
1105 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1106 Evas_Object *old_icon = edje_object_part_swallow_get(VIEW(item),
1107 "elm.swallow.icon");
1108 elm_widget_sub_object_del(VIEW(item), old_icon);
1109 evas_object_hide(old_icon);
1110 edje_object_part_swallow(VIEW(item), "elm.swallow.icon", item->icon);
1111 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1112 edje_object_size_min_restricted_calc(VIEW(item), &mw, &mh, mw, mh);
1113 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1114 if (wd->shrink_mode != ELM_TOOLBAR_SHRINK_EXPAND)
1115 {
1116 if (wd->vertical)
1117 {
1118 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, -1.0);
1119 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, 0.5);
1120 }
1121 else
1122 {
1123 evas_object_size_hint_weight_set(VIEW(item), -1.0, EVAS_HINT_EXPAND);
1124 evas_object_size_hint_align_set(VIEW(item), 0.5, EVAS_HINT_FILL);
1125 }
1126 }
1127 else
1128 {
1129 evas_object_size_hint_weight_set(VIEW(item), EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
1130 evas_object_size_hint_align_set(VIEW(item), EVAS_HINT_FILL, EVAS_HINT_FILL);
1131 }
1132 evas_object_size_hint_min_set(VIEW(item), mw, mh);
1133
1134 EINA_LIST_FOREACH(item->states, l, it_state)
1135 {
1136 if (it_state->icon == old_icon) return;
1137 }
1138 evas_object_del(old_icon);
1139}
1140
1141static void
1142_elm_toolbar_item_icon_set_cb (void *data, Evas_Object *obj, const char *emission, const char *source)
1143{
1144 Elm_Toolbar_Item *item = data;
1145 edje_object_part_unswallow(VIEW(item), item->icon);
1146 _elm_toolbar_item_icon_update(item);
1147 edje_object_signal_callback_del(obj, emission, source,
1148 _elm_toolbar_item_icon_set_cb);
1149 edje_object_signal_emit (VIEW(item), "elm,state,icon,reset", "elm");
1150}
1151
1152static void
1153_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 *sig)
1154{
1155 Evas_Object *old_icon;
1156 int ms = 0;
1157 const char *s;
1158
1159 if (icon_str)
1160 eina_stringshare_replace(&item->icon_str, icon_str);
1161 else
1162 {
1163 eina_stringshare_del(item->icon_str);
1164 item->icon_str = NULL;
1165 }
1166 item->icon = icon_obj;
1167 if (icon_obj)
1168 {
1169 ms = (icon_size * _elm_config->scale);
1170 evas_object_size_hint_min_set(item->icon, ms, ms);
1171 evas_object_size_hint_max_set(item->icon, ms, ms);
1172 evas_object_show(item->icon);
1173 elm_widget_sub_object_add(obj, item->icon);
1174 }
1175 s = edje_object_data_get(VIEW(item), "transition_animation_on");
1176 if ((s) && (atoi(s)))
1177 {
1178 old_icon = edje_object_part_swallow_get(VIEW(item),
1179 "elm.swallow.icon_new");
1180 if (old_icon)
1181 {
1182 elm_widget_sub_object_del(VIEW(item), old_icon);
1183 evas_object_hide(old_icon);
1184 }
1185 edje_object_part_swallow(VIEW(item), "elm.swallow.icon_new",
1186 item->icon);
1187 edje_object_signal_emit (VIEW(item), sig, "elm");
1188 edje_object_signal_callback_add(VIEW(item),
1189 "elm,state,icon_set,done", "elm",
1190 _elm_toolbar_item_icon_set_cb, item);
1191 }
1192 else
1193 _elm_toolbar_item_icon_update(item);
1194 _resize(obj, NULL, NULL, NULL);
1195}
1196
1197static void
1198_elm_toolbar_item_state_cb(void *data __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1199{
1200 Elm_Toolbar_Item *it = event_info;
1201 Elm_Toolbar_Item_State *it_state;
1202
1203 it_state = eina_list_data_get(it->current_state);
1204 if (it_state->func)
1205 it_state->func((void *)it_state->data, obj, event_info);
1206}
1207
1208static Elm_Toolbar_Item_State *
1209_item_state_new(const char *label, const char *icon_str, Evas_Object *icon, Evas_Smart_Cb func, const void *data)
1210{
1211 Elm_Toolbar_Item_State *it_state;
1212 it_state = ELM_NEW(Elm_Toolbar_Item_State);
1213 it_state->label = eina_stringshare_add(label);
1214 it_state->icon_str = eina_stringshare_add(icon_str);
1215 it_state->icon = icon;
1216 it_state->func = func;
1217 it_state->data = data;
1218 return it_state;
1219}
1220
1221EAPI Evas_Object *
1222elm_toolbar_add(Evas_Object *parent)
1223{
1224 Evas_Object *obj;
1225 Evas *e;
1226 Widget_Data *wd;
1227
1228 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
1229
1230 ELM_SET_WIDTYPE(widtype, "toolbar");
1231 elm_widget_type_set(obj, "toolbar");
1232 elm_widget_sub_object_add(parent, obj);
1233 elm_widget_data_set(obj, wd);
1234 elm_widget_del_pre_hook_set(obj, _del_pre_hook);
1235 elm_widget_del_hook_set(obj, _del_hook);
1236 elm_widget_theme_hook_set(obj, _theme_hook);
1237 elm_widget_translate_hook_set(obj, _translate_hook);
1238 elm_widget_can_focus_set(obj, EINA_TRUE);
1239
1240 wd->more_item = NULL;
1241 wd->selected_item = NULL;
1242 wd->scr = elm_smart_scroller_add(e);
1243 elm_smart_scroller_widget_set(wd->scr, obj);
1244 elm_smart_scroller_object_theme_set(obj, wd->scr, "toolbar", "base", "default");
1245 elm_smart_scroller_bounce_allow_set(wd->scr,
1246 _elm_config->thumbscroll_bounce_enable,
1247 EINA_FALSE);
1248 elm_widget_resize_object_set(obj, wd->scr);
1249 elm_smart_scroller_policy_set(wd->scr,
1250 ELM_SMART_SCROLLER_POLICY_AUTO,
1251 ELM_SMART_SCROLLER_POLICY_OFF);
1252
1253
1254 wd->icon_size = _elm_toolbar_icon_size_get(wd);
1255
1256
1257 wd->homogeneous = EINA_TRUE;
1258 wd->align = 0.5;
1259
1260 wd->bx = evas_object_box_add(e);
1261 evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
1262 evas_object_box_layout_set(wd->bx, _layout, obj, NULL);
1263 elm_widget_sub_object_add(obj, wd->bx);
1264 elm_smart_scroller_child_set(wd->scr, wd->bx);
1265 evas_object_show(wd->bx);
1266
1267 elm_toolbar_shrink_mode_set(obj, _elm_config->toolbar_shrink_mode);
1268 evas_object_event_callback_add(wd->scr, EVAS_CALLBACK_RESIZE, _resize, obj);
1269 evas_object_event_callback_add(wd->bx, EVAS_CALLBACK_RESIZE, _resize, obj);
1270 elm_toolbar_icon_order_lookup_set(obj, ELM_ICON_LOOKUP_THEME_FDO);
1271
1272 evas_object_smart_callbacks_descriptions_set(obj, _signals);
1273
1274 _sizing_eval(obj);
1275 return obj;
1276}
1277
1278EAPI void
1279elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size)
1280{
1281 ELM_CHECK_WIDTYPE(obj, widtype);
1282 Widget_Data *wd = elm_widget_data_get(obj);
1283 if (!wd) return;
1284 if (wd->icon_size == icon_size) return;
1285 wd->icon_size = icon_size;
1286 _theme_hook(obj);
1287}
1288
1289EAPI int
1290elm_toolbar_icon_size_get(const Evas_Object *obj)
1291{
1292 ELM_CHECK_WIDTYPE(obj, widtype) 0;
1293 Widget_Data *wd = elm_widget_data_get(obj);
1294 if (!wd) return 0;
1295 return wd->icon_size;
1296}
1297
1298EAPI Elm_Object_Item *
1299elm_toolbar_item_append(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1300{
1301 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1302 Widget_Data *wd = elm_widget_data_get(obj);
1303 if (!wd) return NULL;
1304
1305 Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1306 if (!it) return NULL;
1307 double scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1308
1309 wd->items = eina_inlist_append(wd->items, EINA_INLIST_GET(it));
1310 evas_object_box_append(wd->bx, VIEW(it));
1311 evas_object_show(VIEW(it));
1312
1313 _theme_hook_item(obj, it, scale, wd->icon_size);
1314 _sizing_eval(obj);
1315
1316 return (Elm_Object_Item *)it;
1317}
1318
1319EAPI Elm_Object_Item *
1320elm_toolbar_item_prepend(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1321{
1322 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1323 Widget_Data *wd = elm_widget_data_get(obj);
1324 if (!wd) return NULL;
1325
1326 Elm_Toolbar_Item *it = _item_new(obj, icon, label, func, data);
1327 if (!it) return NULL;
1328 double scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1329
1330 wd->items = eina_inlist_prepend(wd->items, EINA_INLIST_GET(it));
1331 evas_object_box_prepend(wd->bx, VIEW(it));
1332 evas_object_show(VIEW(it));
1333 _theme_hook_item(obj, it, scale, wd->icon_size);
1334 _sizing_eval(obj);
1335
1336 return (Elm_Object_Item *)it;
1337}
1338
1339EAPI Elm_Object_Item *
1340elm_toolbar_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1341{
1342 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1343 ELM_OBJ_ITEM_CHECK_OR_RETURN(before, NULL);
1344 Widget_Data *wd;
1345 Elm_Toolbar_Item *it, *_before;
1346
1347 wd = elm_widget_data_get(obj);
1348 if (!wd) return NULL;
1349 _before = (Elm_Toolbar_Item *) before;
1350 it = _item_new(obj, icon, label, func, data);
1351 if (!it) return NULL;
1352 double scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1353
1354 wd->items = eina_inlist_prepend_relative(wd->items, EINA_INLIST_GET(it),
1355 EINA_INLIST_GET(_before));
1356 evas_object_box_insert_before(wd->bx, VIEW(it), VIEW(_before));
1357 evas_object_show(VIEW(it));
1358 _theme_hook_item(obj, it, scale, wd->icon_size);
1359 _sizing_eval(obj);
1360
1361 return (Elm_Object_Item *)it;
1362}
1363
1364EAPI Elm_Object_Item *
1365elm_toolbar_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1366{
1367 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1368 ELM_OBJ_ITEM_CHECK_OR_RETURN(after, NULL);
1369 Widget_Data *wd;
1370 Elm_Toolbar_Item *it, *_after;
1371
1372 wd = elm_widget_data_get(obj);
1373 if (!wd) return NULL;
1374 _after = (Elm_Toolbar_Item *) after;
1375 it = _item_new(obj, icon, label, func, data);
1376 if (!it) return NULL;
1377 double scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1378
1379 wd->items = eina_inlist_append_relative(wd->items, EINA_INLIST_GET(it),
1380 EINA_INLIST_GET(_after));
1381 evas_object_box_insert_after(wd->bx, VIEW(it), VIEW(_after));
1382 evas_object_show(VIEW(it));
1383 _theme_hook_item(obj, it, scale, wd->icon_size);
1384 _sizing_eval(obj);
1385
1386 return (Elm_Object_Item *)it;
1387}
1388
1389EAPI Elm_Object_Item *
1390elm_toolbar_first_item_get(const Evas_Object *obj)
1391{
1392 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1393 Widget_Data *wd = elm_widget_data_get(obj);
1394 if (!wd || !wd->items) return NULL;
1395 return (Elm_Object_Item *) ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items);
1396}
1397
1398EAPI Elm_Object_Item *
1399elm_toolbar_last_item_get(const Evas_Object *obj)
1400{
1401 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1402 Widget_Data *wd = elm_widget_data_get(obj);
1403 if (!wd || !wd->items) return NULL;
1404 return (Elm_Object_Item *) ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items->last);
1405}
1406
1407EAPI Elm_Object_Item *
1408elm_toolbar_item_next_get(const Elm_Object_Item *it)
1409{
1410 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1411 return (Elm_Object_Item *) ELM_TOOLBAR_ITEM_FROM_INLIST(
1412 EINA_INLIST_GET(((Elm_Toolbar_Item *)it))->next);
1413}
1414
1415EAPI Elm_Object_Item *
1416elm_toolbar_item_prev_get(const Elm_Object_Item *it)
1417{
1418 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1419 return (Elm_Object_Item *) ELM_TOOLBAR_ITEM_FROM_INLIST(
1420 EINA_INLIST_GET(((Elm_Toolbar_Item *)it))->prev);
1421}
1422
1423EAPI void
1424elm_toolbar_item_priority_set(Elm_Object_Item *it, int priority)
1425{
1426 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1427 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1428 if (item->prio.priority == priority) return;
1429 item->prio.priority = priority;
1430 _resize(WIDGET(item), NULL, NULL, NULL);
1431}
1432
1433EAPI int
1434elm_toolbar_item_priority_get(const Elm_Object_Item *it)
1435{
1436 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, 0);
1437 return ((Elm_Toolbar_Item *)it)->prio.priority;
1438}
1439
1440EAPI Elm_Object_Item *
1441elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label)
1442{
1443 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1444 Elm_Toolbar_Item *it;
1445 Widget_Data *wd = elm_widget_data_get(obj);
1446 if (!wd) return NULL;
1447
1448 EINA_INLIST_FOREACH(wd->items, it)
1449 {
1450 if (!strcmp(it->label, label))
1451 return (Elm_Object_Item *)it;
1452 }
1453 return NULL;
1454}
1455
1456EAPI void
1457elm_toolbar_item_selected_set(Elm_Object_Item *it, Eina_Bool selected)
1458{
1459 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1460 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1461 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1462 if (!wd) return;
1463
1464 if (item->selected == selected) return;
1465 if (selected) _item_select(item);
1466 else _item_unselect(item);
1467}
1468
1469EAPI Eina_Bool
1470elm_toolbar_item_selected_get(const Elm_Object_Item *it)
1471{
1472 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1473 return ((Elm_Toolbar_Item *)it)->selected;
1474}
1475
1476EAPI Elm_Object_Item *
1477elm_toolbar_selected_item_get(const Evas_Object *obj)
1478{
1479 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1480 Widget_Data *wd = elm_widget_data_get(obj);
1481 if (!wd) return NULL;
1482 return (Elm_Object_Item *) wd->selected_item;
1483}
1484
1485EAPI void
1486elm_toolbar_item_icon_set(Elm_Object_Item *it, const char *icon)
1487{
1488 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1489
1490 Evas_Object *icon_obj;
1491 Widget_Data *wd;
1492 Evas_Object *obj;
1493 Elm_Toolbar_Item * item = (Elm_Toolbar_Item *)it;
1494
1495 obj = WIDGET(item);
1496 wd = elm_widget_data_get(obj);
1497 if (!wd) return;
1498 if ((icon) && (item->icon_str) && (!strcmp(icon, item->icon_str))) return;
1499
1500 icon_obj = elm_icon_add(obj);
1501 if (!icon_obj) return;
1502 if (_item_icon_set(icon_obj, "toolbar/", icon))
1503 _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, icon, wd->icon_size,
1504 "elm,state,icon_set");
1505 else
1506 {
1507 _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0,
1508 "elm,state,icon_set");
1509 evas_object_del(icon_obj);
1510 }
1511}
1512
1513EAPI const char *
1514elm_toolbar_item_icon_get(const Elm_Object_Item *it)
1515{
1516 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1517 return ((Elm_Toolbar_Item *)it)->icon_str;
1518}
1519
1520EAPI Evas_Object *
1521elm_toolbar_item_object_get(const Elm_Object_Item *it)
1522{
1523 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1524
1525 Widget_Data *wd;
1526 Evas_Object *obj;
1527 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1528
1529 obj = WIDGET(item);
1530 wd = elm_widget_data_get(obj);
1531 if (!wd) return NULL;
1532
1533 return VIEW(item);
1534}
1535
1536EAPI Evas_Object *
1537elm_toolbar_item_icon_object_get(Elm_Object_Item *it)
1538{
1539 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1540 return ((Elm_Toolbar_Item *)it)->icon;
1541}
1542
1543EAPI Eina_Bool
1544elm_toolbar_item_icon_memfile_set(Elm_Object_Item *it, const void *img, size_t size, const char *format, const char *key)
1545{
1546 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1547
1548 Evas_Object *icon_obj;
1549 Widget_Data *wd;
1550 Evas_Object *obj;
1551 Eina_Bool ret;
1552 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1553
1554 obj = WIDGET(item);
1555 wd = elm_widget_data_get(obj);
1556 if (!wd) return EINA_FALSE;
1557
1558 if (img && size)
1559 {
1560 icon_obj = _els_smart_icon_add(evas_object_evas_get(obj));
1561 evas_object_repeat_events_set(icon_obj, EINA_TRUE);
1562 ret = _els_smart_icon_memfile_set(icon_obj, img, size, format, key);
1563 if (!ret)
1564 {
1565 evas_object_del(icon_obj);
1566 return EINA_FALSE;
1567 }
1568 _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, NULL, wd->icon_size,
1569 "elm,state,icon_set");
1570 }
1571 else
1572 _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0, "elm,state,icon_set");
1573 return EINA_TRUE;
1574}
1575
1576EAPI Eina_Bool
1577elm_toolbar_item_icon_file_set(Elm_Object_Item *it, const char *file, const char *key)
1578{
1579 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1580
1581 Evas_Object *icon_obj;
1582 Widget_Data *wd;
1583 Evas_Object *obj;
1584 Eina_Bool ret;
1585 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1586
1587 obj = WIDGET(item);
1588 wd = elm_widget_data_get(obj);
1589 if (!wd) return EINA_FALSE;
1590
1591 if (file)
1592 {
1593 icon_obj = _els_smart_icon_add(evas_object_evas_get(obj));
1594 evas_object_repeat_events_set(icon_obj, EINA_TRUE);
1595 ret = _els_smart_icon_file_key_set(icon_obj, file, key);
1596 if (!ret)
1597 {
1598 evas_object_del(icon_obj);
1599 return EINA_FALSE;
1600 }
1601 _elm_toolbar_item_icon_obj_set(obj, item, icon_obj, NULL, wd->icon_size,
1602 "elm,state,icon_set");
1603 }
1604 else
1605 _elm_toolbar_item_icon_obj_set(obj, item, NULL, NULL, 0, "elm,state,icon_set");
1606 return EINA_TRUE;
1607}
1608
1609EAPI void
1610elm_toolbar_item_separator_set(Elm_Object_Item *it, Eina_Bool separator)
1611{
1612 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1613 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1614 Evas_Object *obj = WIDGET(item);
1615 Widget_Data *wd = elm_widget_data_get(obj);
1616 double scale;
1617 if (item->separator == separator) return;
1618 item->separator = separator;
1619 scale = (elm_widget_scale_get(obj) * _elm_config->scale);
1620 _theme_hook_item(obj, item, scale, wd->icon_size);
1621}
1622
1623EAPI Eina_Bool
1624elm_toolbar_item_separator_get(const Elm_Object_Item *it)
1625{
1626 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1627 return ((Elm_Toolbar_Item *)it)->separator;
1628}
1629
1630EAPI void
1631elm_toolbar_shrink_mode_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode)
1632{
1633 ELM_CHECK_WIDTYPE(obj, widtype);
1634 Widget_Data *wd = elm_widget_data_get(obj);
1635 Eina_Bool bounce;
1636
1637 if (!wd) return;
1638 wd->shrink_mode = shrink_mode;
1639 bounce = (_elm_config->thumbscroll_bounce_enable) &&
1640 (shrink_mode == ELM_TOOLBAR_SHRINK_SCROLL);
1641 elm_smart_scroller_bounce_allow_set(wd->scr, bounce, EINA_FALSE);
1642
1643 if (wd->more_item)
1644 {
1645 _item_del(wd->more_item);
1646 elm_widget_item_free(wd->more_item);
1647 wd->more_item = NULL;
1648 }
1649
1650 if (shrink_mode == ELM_TOOLBAR_SHRINK_MENU)
1651 {
1652 elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
1653 ELM_SMART_SCROLLER_POLICY_OFF);
1654 wd->more_item = _item_new(obj, "more_menu", "More", NULL, NULL);
1655 }
1656 else if (shrink_mode == ELM_TOOLBAR_SHRINK_HIDE)
1657 elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_OFF,
1658 ELM_SMART_SCROLLER_POLICY_OFF);
1659 else
1660 elm_smart_scroller_policy_set(wd->scr, ELM_SMART_SCROLLER_POLICY_AUTO,
1661 ELM_SMART_SCROLLER_POLICY_OFF);
1662 _sizing_eval(obj);
1663}
1664
1665EAPI Elm_Toolbar_Shrink_Mode
1666elm_toolbar_shrink_mode_get(const Evas_Object *obj)
1667{
1668 ELM_CHECK_WIDTYPE(obj, widtype) ELM_TOOLBAR_SHRINK_NONE;
1669 Widget_Data *wd = elm_widget_data_get(obj);
1670
1671 if (!wd) return ELM_TOOLBAR_SHRINK_NONE;
1672 return wd->shrink_mode;
1673}
1674
1675EAPI void
1676elm_toolbar_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous)
1677{
1678 ELM_CHECK_WIDTYPE(obj, widtype);
1679 Widget_Data *wd = elm_widget_data_get(obj);
1680
1681 if (!wd) return;
1682 wd->homogeneous = !!homogeneous;
1683 evas_object_smart_calculate(wd->bx);
1684}
1685
1686EAPI Eina_Bool
1687elm_toolbar_homogeneous_get(const Evas_Object *obj)
1688{
1689 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1690 Widget_Data *wd = elm_widget_data_get(obj);
1691
1692 if (!wd) return EINA_FALSE;
1693 return wd->homogeneous;
1694}
1695
1696EAPI void
1697elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent)
1698{
1699 Elm_Toolbar_Item *it;
1700 ELM_CHECK_WIDTYPE(obj, widtype);
1701 Widget_Data *wd = elm_widget_data_get(obj);
1702
1703 if (!wd) return;
1704 EINA_SAFETY_ON_NULL_RETURN(parent);
1705 wd->menu_parent = parent;
1706 EINA_INLIST_FOREACH(wd->items, it)
1707 {
1708 if (it->o_menu)
1709 elm_menu_parent_set(it->o_menu, wd->menu_parent);
1710 }
1711 if ((wd->more_item) && (wd->more_item->o_menu))
1712 elm_menu_parent_set(wd->more_item->o_menu, wd->menu_parent);
1713}
1714
1715EAPI Evas_Object *
1716elm_toolbar_menu_parent_get(const Evas_Object *obj)
1717{
1718 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1719 Widget_Data *wd = elm_widget_data_get(obj);
1720
1721 if (!wd) return NULL;
1722 return wd->menu_parent;
1723}
1724
1725EAPI void
1726elm_toolbar_align_set(Evas_Object *obj, double align)
1727{
1728 ELM_CHECK_WIDTYPE(obj, widtype);
1729 Widget_Data *wd = elm_widget_data_get(obj);
1730
1731 if (!wd) return;
1732 if (wd->vertical)
1733 {
1734 if (wd->align != align)
1735 evas_object_size_hint_align_set(wd->bx, 0.5, align);
1736 }
1737 else
1738 {
1739 if (wd->align != align)
1740 evas_object_size_hint_align_set(wd->bx, align, 0.5);
1741 }
1742 wd->align = align;
1743}
1744
1745EAPI double
1746elm_toolbar_align_get(const Evas_Object *obj)
1747{
1748 ELM_CHECK_WIDTYPE(obj, widtype) 0.0;
1749 Widget_Data *wd = elm_widget_data_get(obj);
1750
1751 if (!wd) return 0.0;
1752 return wd->align;
1753}
1754
1755EAPI void
1756elm_toolbar_item_menu_set(Elm_Object_Item *it, Eina_Bool menu)
1757{
1758 ELM_OBJ_ITEM_CHECK_OR_RETURN(it);
1759 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1760 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1761 if (!wd) return;
1762
1763 if (item->menu == menu) return;
1764 if (menu) _item_menu_create(wd, item);
1765 else _item_menu_destroy(item);
1766}
1767
1768EAPI Evas_Object *
1769elm_toolbar_item_menu_get(const Elm_Object_Item *it)
1770{
1771 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1772 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1773 if (!item->menu) return NULL;
1774 Widget_Data *wd = elm_widget_data_get(WIDGET(item));
1775 if (!wd) return NULL;
1776 return item->o_menu;
1777}
1778
1779EAPI Elm_Toolbar_Item_State *
1780elm_toolbar_item_state_add(Elm_Object_Item *it, const char *icon, const char *label, Evas_Smart_Cb func, const void *data)
1781{
1782 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1783
1784 Elm_Toolbar_Item_State *it_state;
1785 Evas_Object *icon_obj;
1786 Evas_Object *obj;
1787 Widget_Data *wd;
1788 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1789 obj = WIDGET(item);
1790 wd = elm_widget_data_get(WIDGET(item));
1791 if (!wd) return NULL;
1792
1793 if (!item->states)
1794 {
1795 it_state = _item_state_new(item->label, item->icon_str, item->icon,
1796 item->func, item->base.data);
1797 item->states = eina_list_append(item->states, it_state);
1798 item->current_state = item->states;
1799 }
1800
1801 icon_obj = elm_icon_add(obj);
1802 elm_icon_order_lookup_set(icon_obj, wd->lookup_order);
1803 if (!icon_obj) goto error_state_add;
1804
1805 if (!_item_icon_set(icon_obj, "toolbar/", icon))
1806 {
1807 evas_object_del(icon_obj);
1808 icon_obj = NULL;
1809 icon = NULL;
1810 }
1811
1812 it_state = _item_state_new(label, icon, icon_obj, func, data);
1813 item->states = eina_list_append(item->states, it_state);
1814 item->func = _elm_toolbar_item_state_cb;
1815 item->base.data = NULL;
1816
1817 return it_state;
1818
1819error_state_add:
1820 if (item->states && !eina_list_next(item->states))
1821 {
1822 eina_stringshare_del(item->label);
1823 eina_stringshare_del(item->icon_str);
1824 free(eina_list_data_get(item->states));
1825 eina_list_free(item->states);
1826 item->states = NULL;
1827 }
1828 return NULL;
1829}
1830
1831EAPI Eina_Bool
1832elm_toolbar_item_state_del(Elm_Object_Item *it, Elm_Toolbar_Item_State *state)
1833{
1834 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1835
1836 Eina_List *del_state;
1837 Elm_Toolbar_Item_State *it_state;
1838 Elm_Toolbar_Item *item;
1839
1840 if (!state) return EINA_FALSE;
1841
1842 item = (Elm_Toolbar_Item *)it;
1843 if (!item->states) return EINA_FALSE;
1844
1845 del_state = eina_list_data_find_list(item->states, state);
1846 if (del_state == item->states) return EINA_FALSE;
1847 if (del_state == item->current_state)
1848 elm_toolbar_item_state_unset(it);
1849
1850 eina_stringshare_del(state->label);
1851 eina_stringshare_del(state->icon_str);
1852 if (state->icon) evas_object_del(state->icon);
1853 free(state);
1854 item->states = eina_list_remove_list(item->states, del_state);
1855 if (item->states && !eina_list_next(item->states))
1856 {
1857 it_state = eina_list_data_get(item->states);
1858 item->base.data = it_state->data;
1859 item->func = it_state->func;
1860 eina_stringshare_del(it_state->label);
1861 eina_stringshare_del(it_state->icon_str);
1862 free(eina_list_data_get(item->states));
1863 eina_list_free(item->states);
1864 item->states = NULL;
1865 }
1866 return EINA_TRUE;
1867}
1868
1869EAPI Eina_Bool
1870elm_toolbar_item_state_set(Elm_Object_Item *it, Elm_Toolbar_Item_State *state)
1871{
1872 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, EINA_FALSE);
1873
1874 Widget_Data *wd;
1875 Eina_List *next_state;
1876 Elm_Toolbar_Item_State *it_state;
1877 Evas_Object *obj;
1878 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1879
1880 obj = WIDGET(item);
1881 wd = elm_widget_data_get(obj);
1882 if (!wd) return EINA_FALSE;
1883 if (!item->states) return EINA_FALSE;
1884
1885 if (state)
1886 {
1887 next_state = eina_list_data_find_list(item->states, state);
1888 if (!next_state) return EINA_FALSE;
1889 }
1890 else
1891 next_state = item->states;
1892
1893 if (next_state == item->current_state) return EINA_TRUE;
1894
1895 it_state = eina_list_data_get(next_state);
1896 if (eina_list_data_find(item->current_state, state))
1897 {
1898 _item_label_set(item, it_state->label, "elm,state,label_set,forward");
1899 _elm_toolbar_item_icon_obj_set(obj, item, it_state->icon, it_state->icon_str,
1900 wd->icon_size, "elm,state,icon_set,forward");
1901 }
1902 else
1903 {
1904 _item_label_set(item, it_state->label, "elm,state,label_set,backward");
1905 _elm_toolbar_item_icon_obj_set(obj,
1906 item,
1907 it_state->icon,
1908 it_state->icon_str,
1909 wd->icon_size,
1910 "elm,state,icon_set,backward");
1911 }
1912 if (elm_widget_item_disabled_get(item))
1913 elm_widget_signal_emit(item->icon, "elm,state,disabled", "elm");
1914 else
1915 elm_widget_signal_emit(item->icon, "elm,state,enabled", "elm");
1916
1917 item->current_state = next_state;
1918 return EINA_TRUE;
1919}
1920
1921EAPI void
1922elm_toolbar_item_state_unset(Elm_Object_Item *it)
1923{
1924 elm_toolbar_item_state_set(it, NULL);
1925}
1926
1927EAPI Elm_Toolbar_Item_State *
1928elm_toolbar_item_state_get(const Elm_Object_Item *it)
1929{
1930 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1931 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1932
1933 if ((!item->states) || (!item->current_state)) return NULL;
1934 if (item->current_state == item->states) return NULL;
1935
1936 return eina_list_data_get(item->current_state);
1937}
1938
1939EAPI Elm_Toolbar_Item_State *
1940elm_toolbar_item_state_next(Elm_Object_Item *it)
1941{
1942 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1943
1944 Widget_Data *wd;
1945 Evas_Object *obj;
1946 Eina_List *next_state;
1947 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1948
1949 obj = WIDGET(item);
1950 wd = elm_widget_data_get(obj);
1951 if (!wd) return NULL;
1952 if (!item->states) return NULL;
1953
1954 next_state = eina_list_next(item->current_state);
1955 if (!next_state)
1956 next_state = eina_list_next(item->states);
1957 return eina_list_data_get(next_state);
1958}
1959
1960EAPI Elm_Toolbar_Item_State *
1961elm_toolbar_item_state_prev(Elm_Object_Item *it)
1962{
1963 ELM_OBJ_ITEM_CHECK_OR_RETURN(it, NULL);
1964
1965 Widget_Data *wd;
1966 Evas_Object *obj;
1967 Eina_List *prev_state;
1968 Elm_Toolbar_Item *item = (Elm_Toolbar_Item *)it;
1969
1970 obj = WIDGET(item);
1971 wd = elm_widget_data_get(obj);
1972 if (!wd) return NULL;
1973 if (!item->states) return NULL;
1974
1975 prev_state = eina_list_prev(item->current_state);
1976 if ((!prev_state) || (prev_state == item->states))
1977 prev_state = eina_list_last(item->states);
1978 return eina_list_data_get(prev_state);
1979}
1980
1981EAPI void
1982elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order)
1983{
1984 ELM_CHECK_WIDTYPE(obj, widtype);
1985 Elm_Toolbar_Item *it;
1986 Widget_Data *wd = elm_widget_data_get(obj);
1987 if (!wd) return;
1988
1989 wd->lookup_order = order;
1990 EINA_INLIST_FOREACH(wd->items, it)
1991 elm_icon_order_lookup_set(it->icon, order);
1992 if (wd->more_item)
1993 elm_icon_order_lookup_set(wd->more_item->icon, order);
1994}
1995
1996EAPI Elm_Icon_Lookup_Order
1997elm_toolbar_icon_order_lookup_get(const Evas_Object *obj)
1998{
1999 ELM_CHECK_WIDTYPE(obj, widtype) ELM_ICON_LOOKUP_THEME_FDO;
2000 Widget_Data *wd = elm_widget_data_get(obj);
2001 if (!wd) return ELM_ICON_LOOKUP_THEME_FDO;
2002 return wd->lookup_order;
2003}
2004
2005EAPI void
2006elm_toolbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal)
2007{
2008 ELM_CHECK_WIDTYPE(obj, widtype);
2009 Widget_Data *wd = elm_widget_data_get(obj);
2010 if (!wd) return;
2011 wd->vertical = !horizontal;
2012 if (wd->vertical)
2013 evas_object_size_hint_align_set(wd->bx, 0.5, wd->align);
2014 else
2015 evas_object_size_hint_align_set(wd->bx, wd->align, 0.5);
2016 _sizing_eval(obj);
2017}
2018
2019EAPI Eina_Bool
2020elm_toolbar_horizontal_get(const Evas_Object *obj)
2021{
2022 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2023 Widget_Data *wd = elm_widget_data_get(obj);
2024 if (!wd) return EINA_FALSE;
2025 return !wd->vertical;
2026}
2027
2028EAPI unsigned int
2029elm_toolbar_items_count(const Evas_Object *obj)
2030{
2031 ELM_CHECK_WIDTYPE(obj, widtype) 0;
2032 Widget_Data *wd = elm_widget_data_get(obj);
2033 if (!wd) return 0;
2034 return wd->item_count;
2035}
2036
2037EAPI void
2038elm_toolbar_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode)
2039{
2040 ELM_CHECK_WIDTYPE(obj, widtype);
2041 Widget_Data *wd = elm_widget_data_get(obj);
2042 if (!wd) return;
2043 if (mode >= ELM_OBJECT_SELECT_MODE_MAX)
2044 return;
2045 if ((mode == ELM_OBJECT_SELECT_MODE_ALWAYS) &&
2046 (wd->select_mode != ELM_OBJECT_SELECT_MODE_ALWAYS) &&
2047 wd->items)
2048 _item_select(ELM_TOOLBAR_ITEM_FROM_INLIST(wd->items));
2049 if (wd->select_mode != mode)
2050 wd->select_mode = mode;
2051}
2052
2053EAPI Elm_Object_Select_Mode
2054elm_toolbar_select_mode_get(const Evas_Object *obj)
2055{
2056 ELM_CHECK_WIDTYPE(obj, widtype) ELM_OBJECT_SELECT_MODE_MAX;
2057 Widget_Data *wd = elm_widget_data_get(obj);
2058 if (!wd) return ELM_OBJECT_SELECT_MODE_MAX;
2059 return wd->select_mode;
2060}
2061
diff --git a/libraries/elementary/src/lib/elm_toolbar.h b/libraries/elementary/src/lib/elm_toolbar.h
new file mode 100644
index 0000000..6b01030
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_toolbar.h
@@ -0,0 +1,900 @@
1/**
2 * @defgroup Toolbar Toolbar
3 * @ingroup Elementary
4 *
5 * @image html img/widget/toolbar/preview-00.png
6 * @image latex img/widget/toolbar/preview-00.eps width=\textwidth
7 *
8 * @image html img/toolbar.png
9 * @image latex img/toolbar.eps width=\textwidth
10 *
11 * A toolbar is a widget that displays a list of items inside
12 * a box. It can be scrollable, show a menu with items that don't fit
13 * to toolbar size or even crop them.
14 *
15 * Only one item can be selected at a time.
16 *
17 * Items can have multiple states, or show menus when selected by the user.
18 *
19 * Smart callbacks one can listen to:
20 * - "clicked" - when the user clicks on a toolbar item and becomes selected.
21 * - "longpressed" - when the toolbar is pressed for a certain amount of time.
22 * - "language,changed" - when the program language changes.
23 *
24 * Available styles for it:
25 * - @c "default"
26 * - @c "transparent" - no background or shadow, just show the content
27 *
28 * Default text parts of the toolbar items that you can use for are:
29 * @li "default" - label of the toolbar item
30 *
31 * Supported elm_object_item common APIs.
32 * @li @ref elm_object_item_disabled_set
33 * @li @ref elm_object_item_disabled_get
34 * @li @ref elm_object_item_part_text_set
35 * @li @ref elm_object_item_part_text_get
36 *
37 * List of examples:
38 * @li @ref toolbar_example_01
39 * @li @ref toolbar_example_02
40 * @li @ref toolbar_example_03
41 */
42
43/**
44 * @addtogroup Toolbar
45 * @{
46 */
47
48/**
49 * @enum _Elm_Toolbar_Shrink_Mode
50 * @typedef Elm_Toolbar_Shrink_Mode
51 *
52 * Set toolbar's items display behavior, it can be scrollable,
53 * show a menu with exceeding items, or simply hide them.
54 *
55 * @note Default value is #ELM_TOOLBAR_SHRINK_MENU. It reads value
56 * from elm config.
57 *
58 * Values <b> don't </b> work as bitmask, only one can be chosen.
59 *
60 * @see elm_toolbar_shrink_mode_set()
61 * @see elm_toolbar_shrink_mode_get()
62 *
63 * @ingroup Toolbar
64 */
65typedef enum
66{
67 ELM_TOOLBAR_SHRINK_NONE, /**< Set toolbar minimum size to fit all the items. */
68 ELM_TOOLBAR_SHRINK_HIDE, /**< Hide exceeding items. */
69 ELM_TOOLBAR_SHRINK_SCROLL, /**< Allow accessing exceeding items through a scroller. */
70 ELM_TOOLBAR_SHRINK_MENU, /**< Inserts a button to pop up a menu with exceeding items. */
71 ELM_TOOLBAR_SHRINK_EXPAND, /**< Expand all items according the size of the toolbar. */
72 ELM_TOOLBAR_SHRINK_LAST /**< Indicates error if returned by elm_toolbar_shrink_mode_get() */
73} Elm_Toolbar_Shrink_Mode;
74
75typedef struct _Elm_Toolbar_Item_State Elm_Toolbar_Item_State; /**< State of a Elm_Toolbar_Item. Can be created with elm_toolbar_item_state_add() and removed with elm_toolbar_item_state_del(). */
76
77/**
78 * Add a new toolbar widget to the given parent Elementary
79 * (container) object.
80 *
81 * @param parent The parent object.
82 * @return a new toolbar widget handle or @c NULL, on errors.
83 *
84 * This function inserts a new toolbar widget on the canvas.
85 *
86 * @ingroup Toolbar
87 */
88EAPI Evas_Object *elm_toolbar_add(Evas_Object *parent);
89
90/**
91 * Set the icon size, in pixels, to be used by toolbar items.
92 *
93 * @param obj The toolbar object
94 * @param icon_size The icon size in pixels
95 *
96 * @note Default value is @c 32. It reads value from elm config.
97 *
98 * @see elm_toolbar_icon_size_get()
99 *
100 * @ingroup Toolbar
101 */
102EAPI void elm_toolbar_icon_size_set(Evas_Object *obj, int icon_size);
103
104/**
105 * Get the icon size, in pixels, to be used by toolbar items.
106 *
107 * @param obj The toolbar object.
108 * @return The icon size in pixels.
109 *
110 * @see elm_toolbar_icon_size_set() for details.
111 *
112 * @ingroup Toolbar
113 */
114EAPI int elm_toolbar_icon_size_get(const Evas_Object *obj);
115
116/**
117 * Sets icon lookup order, for toolbar items' icons.
118 *
119 * @param obj The toolbar object.
120 * @param order The icon lookup order.
121 *
122 * Icons added before calling this function will not be affected.
123 * The default lookup order is #ELM_ICON_LOOKUP_THEME_FDO.
124 *
125 * @see elm_toolbar_icon_order_lookup_get()
126 *
127 * @ingroup Toolbar
128 */
129EAPI void elm_toolbar_icon_order_lookup_set(Evas_Object *obj, Elm_Icon_Lookup_Order order);
130
131/**
132 * Gets the icon lookup order.
133 *
134 * @param obj The toolbar object.
135 * @return The icon lookup order.
136 *
137 * @see elm_toolbar_icon_order_lookup_set() for details.
138 *
139 * @ingroup Toolbar
140 */
141EAPI Elm_Icon_Lookup_Order elm_toolbar_icon_order_lookup_get(const Evas_Object *obj);
142
143/**
144 * Append item to the toolbar.
145 *
146 * @param obj The toolbar object.
147 * @param icon A string with icon name or the absolute path of an image file.
148 * @param label The label of the item.
149 * @param func The function to call when the item is clicked.
150 * @param data The data to associate with the item for related callbacks.
151 * @return The created item or @c NULL upon failure.
152 *
153 * A new item will be created and appended to the toolbar, i.e., will
154 * be set as @b last item.
155 *
156 * Items created with this method can be deleted with
157 * elm_object_item_del().
158 *
159 * Associated @p data can be properly freed when item is deleted if a
160 * callback function is set with elm_object_item_del_cb_set().
161 *
162 * If a function is passed as argument, it will be called every time this item
163 * is selected, i.e., the user clicks over an unselected item.
164 * If such function isn't needed, just passing
165 * @c NULL as @p func is enough. The same should be done for @p data.
166 *
167 * Toolbar will load icon image from fdo or current theme.
168 * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
169 * If an absolute path is provided it will load it direct from a file.
170 *
171 * @see elm_toolbar_item_icon_set()
172 * @see elm_object_item_del()
173 *
174 * @ingroup Toolbar
175 */
176EAPI Elm_Object_Item *elm_toolbar_item_append(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data);
177
178/**
179 * Prepend item to the toolbar.
180 *
181 * @param obj The toolbar object.
182 * @param icon A string with icon name or the absolute path of an image file.
183 * @param label The label of the item.
184 * @param func The function to call when the item is clicked.
185 * @param data The data to associate with the item for related callbacks.
186 * @return The created item or @c NULL upon failure.
187 *
188 * A new item will be created and prepended to the toolbar, i.e., will
189 * be set as @b first item.
190 *
191 * Items created with this method can be deleted with
192 * elm_object_item_del().
193 *
194 * Associated @p data can be properly freed when item is deleted if a
195 * callback function is set with elm_object_item_del_cb_set().
196 *
197 * If a function is passed as argument, it will be called every time this item
198 * is selected, i.e., the user clicks over an unselected item.
199 * If such function isn't needed, just passing
200 * @c NULL as @p func is enough. The same should be done for @p data.
201 *
202 * Toolbar will load icon image from fdo or current theme.
203 * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
204 * If an absolute path is provided it will load it direct from a file.
205 *
206 * @see elm_toolbar_item_icon_set()
207 * @see elm_object_item_del()
208 *
209 * @ingroup Toolbar
210 */
211EAPI Elm_Object_Item *elm_toolbar_item_prepend(Evas_Object *obj, const char *icon, const char *label, Evas_Smart_Cb func, const void *data);
212
213/**
214 * Insert a new item into the toolbar object before item @p before.
215 *
216 * @param obj The toolbar object.
217 * @param before The toolbar item to insert before.
218 * @param icon A string with icon name or the absolute path of an image file.
219 * @param label The label of the item.
220 * @param func The function to call when the item is clicked.
221 * @param data The data to associate with the item for related callbacks.
222 * @return The created item or @c NULL upon failure.
223 *
224 * A new item will be created and added to the toolbar. Its position in
225 * this toolbar will be just before item @p before.
226 *
227 * Items created with this method can be deleted with
228 * elm_object_item_del().
229 *
230 * Associated @p data can be properly freed when item is deleted if a
231 * callback function is set with elm_object_item_del_cb_set().
232 *
233 * If a function is passed as argument, it will be called every time this item
234 * is selected, i.e., the user clicks over an unselected item.
235 * If such function isn't needed, just passing
236 * @c NULL as @p func is enough. The same should be done for @p data.
237 *
238 * Toolbar will load icon image from fdo or current theme.
239 * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
240 * If an absolute path is provided it will load it direct from a file.
241 *
242 * @see elm_toolbar_item_icon_set()
243 * @see elm_object_item_del()
244 *
245 * @ingroup Toolbar
246 */
247EAPI Elm_Object_Item *elm_toolbar_item_insert_before(Evas_Object *obj, Elm_Object_Item *before, const char *icon, const char *label, Evas_Smart_Cb func, const void *data);
248
249/**
250 * Insert a new item into the toolbar object after item @p after.
251 *
252 * @param obj The toolbar object.
253 * @param after The toolbar item to insert after.
254 * @param icon A string with icon name or the absolute path of an image file.
255 * @param label The label of the item.
256 * @param func The function to call when the item is clicked.
257 * @param data The data to associate with the item for related callbacks.
258 * @return The created item or @c NULL upon failure.
259 *
260 * A new item will be created and added to the toolbar. Its position in
261 * this toolbar will be just after item @p after.
262 *
263 * Items created with this method can be deleted with
264 * elm_object_item_del().
265 *
266 * Associated @p data can be properly freed when item is deleted if a
267 * callback function is set with elm_object_item_del_cb_set().
268 *
269 * If a function is passed as argument, it will be called every time this item
270 * is selected, i.e., the user clicks over an unselected item.
271 * If such function isn't needed, just passing
272 * @c NULL as @p func is enough. The same should be done for @p data.
273 *
274 * Toolbar will load icon image from fdo or current theme.
275 * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
276 * If an absolute path is provided it will load it direct from a file.
277 *
278 * @see elm_toolbar_item_icon_set()
279 * @see elm_object_item_del()
280 *
281 * @ingroup Toolbar
282 */
283EAPI Elm_Object_Item *elm_toolbar_item_insert_after(Evas_Object *obj, Elm_Object_Item *after, const char *icon, const char *label, Evas_Smart_Cb func, const void *data);
284
285/**
286 * Get the first item in the given toolbar widget's list of
287 * items.
288 *
289 * @param obj The toolbar object
290 * @return The first item or @c NULL, if it has no items (and on
291 * errors)
292 *
293 * @see elm_toolbar_item_append()
294 * @see elm_toolbar_last_item_get()
295 *
296 * @ingroup Toolbar
297 */
298EAPI Elm_Object_Item *elm_toolbar_first_item_get(const Evas_Object *obj);
299
300/**
301 * Get the last item in the given toolbar widget's list of
302 * items.
303 *
304 * @param obj The toolbar object
305 * @return The last item or @c NULL, if it has no items (and on
306 * errors)
307 *
308 * @see elm_toolbar_item_prepend()
309 * @see elm_toolbar_first_item_get()
310 *
311 * @ingroup Toolbar
312 */
313EAPI Elm_Object_Item *elm_toolbar_last_item_get(const Evas_Object *obj);
314
315/**
316 * Get the item after @p item in toolbar.
317 *
318 * @param it The toolbar item.
319 * @return The item after @p item, or @c NULL if none or on failure.
320 *
321 * @note If it is the last item, @c NULL will be returned.
322 *
323 * @see elm_toolbar_item_append()
324 *
325 * @ingroup Toolbar
326 */
327EAPI Elm_Object_Item *elm_toolbar_item_next_get(const Elm_Object_Item *it);
328
329/**
330 * Get the item before @p item in toolbar.
331 *
332 * @param it The toolbar item.
333 * @return The item before @p item, or @c NULL if none or on failure.
334 *
335 * @note If it is the first item, @c NULL will be returned.
336 *
337 * @see elm_toolbar_item_prepend()
338 *
339 * @ingroup Toolbar
340 */
341EAPI Elm_Object_Item *elm_toolbar_item_prev_get(const Elm_Object_Item *it);
342
343/**
344 * Set the priority of a toolbar item.
345 *
346 * @param it The toolbar item.
347 * @param priority The item priority. The default is zero.
348 *
349 * This is used only when the toolbar shrink mode is set to
350 * #ELM_TOOLBAR_SHRINK_MENU or #ELM_TOOLBAR_SHRINK_HIDE.
351 * When space is less than required, items with low priority
352 * will be removed from the toolbar and added to a dynamically-created menu,
353 * while items with higher priority will remain on the toolbar,
354 * with the same order they were added.
355 *
356 * @see elm_toolbar_item_priority_get()
357 *
358 * @ingroup Toolbar
359 */
360EAPI void elm_toolbar_item_priority_set(Elm_Object_Item *it, int priority);
361
362/**
363 * Get the priority of a toolbar item.
364 *
365 * @param it The toolbar item.
366 * @return The @p item priority, or @c 0 on failure.
367 *
368 * @see elm_toolbar_item_priority_set() for details.
369 *
370 * @ingroup Toolbar
371 */
372EAPI int elm_toolbar_item_priority_get(const Elm_Object_Item *it);
373
374/**
375 * Returns a pointer to a toolbar item by its label.
376 *
377 * @param obj The toolbar object.
378 * @param label The label of the item to find.
379 *
380 * @return The pointer to the toolbar item matching @p label or @c NULL
381 * on failure.
382 *
383 * @ingroup Toolbar
384 */
385EAPI Elm_Object_Item *elm_toolbar_item_find_by_label(const Evas_Object *obj, const char *label);
386
387/*
388 * Get whether the @p item is selected or not.
389 *
390 * @param it The toolbar item.
391 * @return @c EINA_TRUE means item is selected. @c EINA_FALSE indicates
392 * it's not. If @p obj is @c NULL, @c EINA_FALSE is returned.
393 *
394 * @see elm_toolbar_selected_item_set() for details.
395 * @see elm_toolbar_item_selected_get()
396 *
397 * @ingroup Toolbar
398 */
399EAPI Eina_Bool elm_toolbar_item_selected_get(const Elm_Object_Item *it);
400
401/**
402 * Set the selected state of an item.
403 *
404 * @param it The toolbar item
405 * @param selected The selected state
406 *
407 * This sets the selected state of the given item @p it.
408 * @c EINA_TRUE for selected, @c EINA_FALSE for not selected.
409 *
410 * If a new item is selected the previously selected will be unselected.
411 * Previously selected item can be get with function
412 * elm_toolbar_selected_item_get().
413 *
414 * Selected items will be highlighted.
415 *
416 * @see elm_toolbar_item_selected_get()
417 * @see elm_toolbar_selected_item_get()
418 *
419 * @ingroup Toolbar
420 */
421EAPI void elm_toolbar_item_selected_set(Elm_Object_Item *it, Eina_Bool selected);
422
423/**
424 * Get the selected item.
425 *
426 * @param obj The toolbar object.
427 * @return The selected toolbar item.
428 *
429 * The selected item can be unselected with function
430 * elm_toolbar_item_selected_set().
431 *
432 * The selected item always will be highlighted on toolbar.
433 *
434 * @see elm_toolbar_selected_items_get()
435 *
436 * @ingroup Toolbar
437 */
438EAPI Elm_Object_Item *elm_toolbar_selected_item_get(const Evas_Object *obj);
439
440/**
441 * Set the icon associated with @p item.
442 *
443 * @param it The toolbar item.
444 * @param icon A string with icon name or the absolute path of an image file.
445 *
446 * Toolbar will load icon image from fdo or current theme.
447 * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
448 * If an absolute path is provided it will load it direct from a file.
449 *
450 * @see elm_toolbar_icon_order_lookup_set()
451 * @see elm_toolbar_icon_order_lookup_get()
452 *
453 * @ingroup Toolbar
454 */
455EAPI void elm_toolbar_item_icon_set(Elm_Object_Item *it, const char *icon);
456
457/**
458 * Get the string used to set the icon of @p item.
459 *
460 * @param it The toolbar item.
461 * @return The string associated with the icon object.
462 *
463 * @see elm_toolbar_item_icon_set() for details.
464 *
465 * @ingroup Toolbar
466 */
467EAPI const char *elm_toolbar_item_icon_get(const Elm_Object_Item *it);
468
469/**
470 * Get the object of @p item.
471 *
472 * @param it The toolbar item.
473 * @return The object
474 *
475 * @ingroup Toolbar
476 */
477EAPI Evas_Object *elm_toolbar_item_object_get(const Elm_Object_Item *it);
478
479/**
480 * Get the icon object of @p item.
481 *
482 * @param it The toolbar item.
483 * @return The icon object
484 *
485 * @see elm_toolbar_item_icon_set(), elm_toolbar_item_icon_file_set(),
486 * or elm_toolbar_item_icon_memfile_set() for details.
487 *
488 * @ingroup Toolbar
489 */
490EAPI Evas_Object *elm_toolbar_item_icon_object_get(Elm_Object_Item *it);
491
492/**
493 * Set the icon associated with @p item to an image in a binary buffer.
494 *
495 * @param it The toolbar item.
496 * @param img The binary data that will be used as an image
497 * @param size The size of binary data @p img
498 * @param format Optional format of @p img to pass to the image loader
499 * @param key Optional key of @p img to pass to the image loader (eg. if @p img is an edje file)
500 *
501 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
502 *
503 * @note The icon image set by this function can be changed by
504 * elm_toolbar_item_icon_set().
505 *
506 * @ingroup Toolbar
507 */
508EAPI Eina_Bool elm_toolbar_item_icon_memfile_set(Elm_Object_Item *it, const void *img, size_t size, const char *format, const char *key);
509
510/**
511 * Set the icon associated with @p item to an image in a binary buffer.
512 *
513 * @param it The toolbar item.
514 * @param file The file that contains the image
515 * @param key Optional key of @p img to pass to the image loader (eg. if @p img is an edje file)
516 *
517 * @return (@c EINA_TRUE = success, @c EINA_FALSE = error)
518 *
519 * @note The icon image set by this function can be changed by
520 * elm_toolbar_item_icon_set().
521 *
522 * @ingroup Toolbar
523 */
524EAPI Eina_Bool elm_toolbar_item_icon_file_set(Elm_Object_Item *it, const char *file, const char *key);
525
526/**
527 * Set or unset item as a separator.
528 *
529 * @param it The toolbar item.
530 * @param separator @c EINA_TRUE to set item @p item as separator or
531 * @c EINA_FALSE to unset, i.e., item will be used as a regular item.
532 *
533 * Items aren't set as separator by default.
534 *
535 * If set as separator it will display separator theme, so won't display
536 * icons or label.
537 *
538 * @see elm_toolbar_item_separator_get()
539 *
540 * @ingroup Toolbar
541 */
542EAPI void elm_toolbar_item_separator_set(Elm_Object_Item *it, Eina_Bool separator);
543
544/**
545 * Get a value whether item is a separator or not.
546 *
547 * @param it The toolbar item.
548 * @return @c EINA_TRUE means item @p it is a separator. @c EINA_FALSE
549 * indicates it's not. If @p it is @c NULL, @c EINA_FALSE is returned.
550 *
551 * @see elm_toolbar_item_separator_set() for details.
552 *
553 * @ingroup Toolbar
554 */
555EAPI Eina_Bool elm_toolbar_item_separator_get(const Elm_Object_Item *it);
556
557/**
558 * Set the shrink state of toolbar @p obj.
559 *
560 * @param obj The toolbar object.
561 * @param shrink_mode Toolbar's items display behavior.
562 *
563 * The toolbar won't scroll if #ELM_TOOLBAR_SHRINK_NONE,
564 * but will enforce a minimum size so all the items will fit, won't scroll
565 * and won't show the items that don't fit if #ELM_TOOLBAR_SHRINK_HIDE,
566 * will scroll if #ELM_TOOLBAR_SHRINK_SCROLL, and will create a button to
567 * pop up excess elements with #ELM_TOOLBAR_SHRINK_MENU.
568 *
569 * @ingroup Toolbar
570 */
571EAPI void elm_toolbar_shrink_mode_set(Evas_Object *obj, Elm_Toolbar_Shrink_Mode shrink_mode);
572
573/**
574 * Get the shrink mode of toolbar @p obj.
575 *
576 * @param obj The toolbar object.
577 * @return Toolbar's items display behavior.
578 *
579 * @see elm_toolbar_shrink_mode_set() for details.
580 *
581 * @ingroup Toolbar
582 */
583EAPI Elm_Toolbar_Shrink_Mode elm_toolbar_shrink_mode_get(const Evas_Object *obj);
584
585/**
586 * Enable/disable homogeneous mode.
587 *
588 * @param obj The toolbar object
589 * @param homogeneous Assume the items within the toolbar are of the
590 * same size (EINA_TRUE = on, EINA_FALSE = off). Default is @c EINA_FALSE.
591 *
592 * This will enable the homogeneous mode where items are of the same size.
593 * @see elm_toolbar_homogeneous_get()
594 *
595 * @ingroup Toolbar
596 */
597EAPI void elm_toolbar_homogeneous_set(Evas_Object *obj, Eina_Bool homogeneous);
598
599/**
600 * Get whether the homogeneous mode is enabled.
601 *
602 * @param obj The toolbar object.
603 * @return Assume the items within the toolbar are of the same height
604 * and width (EINA_TRUE = on, EINA_FALSE = off).
605 *
606 * @see elm_toolbar_homogeneous_set()
607 *
608 * @ingroup Toolbar
609 */
610EAPI Eina_Bool elm_toolbar_homogeneous_get(const Evas_Object *obj);
611
612/**
613 * Set the parent object of the toolbar items' menus.
614 *
615 * @param obj The toolbar object.
616 * @param parent The parent of the menu objects.
617 *
618 * Each item can be set as item menu, with elm_toolbar_item_menu_set().
619 *
620 * For more details about setting the parent for toolbar menus, see
621 * elm_menu_parent_set().
622 *
623 * @see elm_menu_parent_set() for details.
624 * @see elm_toolbar_item_menu_set() for details.
625 *
626 * @ingroup Toolbar
627 */
628EAPI void elm_toolbar_menu_parent_set(Evas_Object *obj, Evas_Object *parent);
629
630/**
631 * Get the parent object of the toolbar items' menus.
632 *
633 * @param obj The toolbar object.
634 * @return The parent of the menu objects.
635 *
636 * @see elm_toolbar_menu_parent_set() for details.
637 *
638 * @ingroup Toolbar
639 */
640EAPI Evas_Object *elm_toolbar_menu_parent_get(const Evas_Object *obj);
641
642/**
643 * Set the alignment of the items.
644 *
645 * @param obj The toolbar object.
646 * @param align The new alignment, a float between <tt> 0.0 </tt>
647 * and <tt> 1.0 </tt>.
648 *
649 * Alignment of toolbar items, from <tt> 0.0 </tt> to indicates to align
650 * left, to <tt> 1.0 </tt>, to align to right. <tt> 0.5 </tt> centralize
651 * items.
652 *
653 * Centered items by default.
654 *
655 * @see elm_toolbar_align_get()
656 *
657 * @ingroup Toolbar
658 */
659EAPI void elm_toolbar_align_set(Evas_Object *obj, double align);
660
661/**
662 * Get the alignment of the items.
663 *
664 * @param obj The toolbar object.
665 * @return toolbar items alignment, a float between <tt> 0.0 </tt> and
666 * <tt> 1.0 </tt>.
667 *
668 * @see elm_toolbar_align_set() for details.
669 *
670 * @ingroup Toolbar
671 */
672EAPI double elm_toolbar_align_get(const Evas_Object *obj);
673
674/**
675 * Set whether the toolbar item opens a menu.
676 *
677 * @param it The toolbar item.
678 * @param menu If @c EINA_TRUE, @p item will opens a menu when selected.
679 *
680 * A toolbar item can be set to be a menu, using this function.
681 *
682 * Once it is set to be a menu, it can be manipulated through the
683 * menu-like function elm_toolbar_menu_parent_set() and the other
684 * elm_menu functions, using the Evas_Object @c menu returned by
685 * elm_toolbar_item_menu_get().
686 *
687 * So, items to be displayed in this item's menu should be added with
688 * elm_menu_item_add().
689 *
690 * The following code exemplifies the most basic usage:
691 * @code
692 * tb = elm_toolbar_add(win)
693 * item = elm_toolbar_item_append(tb, "refresh", "Menu", NULL, NULL);
694 * elm_toolbar_item_menu_set(item, EINA_TRUE);
695 * elm_toolbar_menu_parent_set(tb, win);
696 * menu = elm_toolbar_item_menu_get(item);
697 * elm_menu_item_add(menu, NULL, "edit-cut", "Cut", NULL, NULL);
698 * menu_item = elm_menu_item_add(menu, NULL, "edit-copy", "Copy", NULL,
699 * NULL);
700 * @endcode
701 *
702 * @see elm_toolbar_item_menu_get()
703 *
704 * @ingroup Toolbar
705 */
706EAPI void elm_toolbar_item_menu_set(Elm_Object_Item *it, Eina_Bool menu);
707
708/**
709 * Get toolbar item's menu.
710 *
711 * @param it The toolbar item.
712 * @return Item's menu object or @c NULL on failure.
713 *
714 * If @p item wasn't set as menu item with elm_toolbar_item_menu_set(),
715 * this function will set it.
716 *
717 * @see elm_toolbar_item_menu_set() for details.
718 *
719 * @ingroup Toolbar
720 */
721EAPI Evas_Object *elm_toolbar_item_menu_get(const Elm_Object_Item *it);
722
723/**
724 * Add a new state to @p item.
725 *
726 * @param it The toolbar item.
727 * @param icon A string with icon name or the absolute path of an image file.
728 * @param label The label of the new state.
729 * @param func The function to call when the item is clicked when this
730 * state is selected.
731 * @param data The data to associate with the state.
732 * @return The toolbar item state, or @c NULL upon failure.
733 *
734 * Toolbar will load icon image from fdo or current theme.
735 * This behavior can be set by elm_toolbar_icon_order_lookup_set() function.
736 * If an absolute path is provided it will load it direct from a file.
737 *
738 * States created with this function can be removed with
739 * elm_toolbar_item_state_del().
740 *
741 * @see elm_toolbar_item_state_del()
742 * @see elm_toolbar_item_state_sel()
743 * @see elm_toolbar_item_state_get()
744 *
745 * @ingroup Toolbar
746 */
747EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_add(Elm_Object_Item *it, const char *icon, const char *label, Evas_Smart_Cb func, const void *data);
748
749/**
750 * Delete a previously added state to @p item.
751 *
752 * @param it The toolbar item.
753 * @param state The state to be deleted.
754 * @return @c EINA_TRUE on success or @c EINA_FALSE on failure.
755 *
756 * @see elm_toolbar_item_state_add()
757 */
758EAPI Eina_Bool elm_toolbar_item_state_del(Elm_Object_Item *it, Elm_Toolbar_Item_State *state);
759
760/**
761 * Set @p state as the current state of @p it.
762 *
763 * @param it The toolbar item.
764 * @param state The state to use.
765 * @return @c EINA_TRUE on success or @c EINA_FALSE on failure.
766 *
767 * If @p state is @c NULL, it won't select any state and the default item's
768 * icon and label will be used. It's the same behaviour than
769 * elm_toolbar_item_state_unset().
770 *
771 * @see elm_toolbar_item_state_unset()
772 *
773 * @ingroup Toolbar
774 */
775EAPI Eina_Bool elm_toolbar_item_state_set(Elm_Object_Item *it, Elm_Toolbar_Item_State *state);
776
777/**
778 * Unset the state of @p it.
779 *
780 * @param it The toolbar item.
781 *
782 * The default icon and label from this item will be displayed.
783 *
784 * @see elm_toolbar_item_state_set() for more details.
785 *
786 * @ingroup Toolbar
787 */
788EAPI void elm_toolbar_item_state_unset(Elm_Object_Item *it);
789
790/**
791 * Get the current state of @p it.
792 *
793 * @param it The toolbar item.
794 * @return The selected state or @c NULL if none is selected or on failure.
795 *
796 * @see elm_toolbar_item_state_set() for details.
797 * @see elm_toolbar_item_state_unset()
798 * @see elm_toolbar_item_state_add()
799 *
800 * @ingroup Toolbar
801 */
802EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_get(const Elm_Object_Item *it);
803
804/**
805 * Get the state after selected state in toolbar's @p item.
806 *
807 * @param it The toolbar item to change state.
808 * @return The state after current state, or @c NULL on failure.
809 *
810 * If last state is selected, this function will return first state.
811 *
812 * @see elm_toolbar_item_state_set()
813 * @see elm_toolbar_item_state_add()
814 *
815 * @ingroup Toolbar
816 */
817EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_next(Elm_Object_Item *it);
818
819/**
820 * Get the state before selected state in toolbar's @p item.
821 *
822 * @param it The toolbar item to change state.
823 * @return The state before current state, or @c NULL on failure.
824 *
825 * If first state is selected, this function will return last state.
826 *
827 * @see elm_toolbar_item_state_set()
828 * @see elm_toolbar_item_state_add()
829 *
830 * @ingroup Toolbar
831 */
832EAPI Elm_Toolbar_Item_State *elm_toolbar_item_state_prev(Elm_Object_Item *it);
833
834
835/**
836 * Change a toolbar's orientation
837 * @param obj The toolbar object
838 * @param horizontal If @c EINA_TRUE, the toolbar is horizontal
839 * By default, a toolbar will be horizontal. Use this function to create a vertical toolbar.
840 * @ingroup Toolbar
841 */
842EAPI void elm_toolbar_horizontal_set(Evas_Object *obj, Eina_Bool horizontal);
843
844/**
845 * Get a toolbar's orientation
846 * @param obj The toolbar object
847 * @return If @c EINA_TRUE, the toolbar is horizontal
848 * By default, a toolbar will be horizontal. Use this function to determine whether a toolbar is vertical.
849 * @ingroup Toolbar
850 */
851EAPI Eina_Bool elm_toolbar_horizontal_get(const Evas_Object *obj);
852
853/**
854 * Get the number of items in a toolbar
855 * @param obj The toolbar object
856 * @return The number of items in @p obj toolbar
857 * @ingroup Toolbar
858 */
859EAPI unsigned int elm_toolbar_items_count(const Evas_Object *obj);
860
861/**
862 * Set the toolbar select mode.
863 *
864 * @param obj The toolbar object
865 * @param mode The select mode
866 *
867 * elm_toolbar_select_mode_set() changes item select mode in the toolbar widget.
868 * - ELM_OBJECT_SELECT_MODE_DEFAULT : Items will only call their selection func and
869 * callback when first becoming selected. Any further clicks will
870 * do nothing, unless you set always select mode.
871 * - ELM_OBJECT_SELECT_MODE_ALWAYS : This means that, even if selected,
872 * every click will make the selected callbacks be called.
873 * - ELM_OBJECT_SELECT_MODE_NONE : This will turn off the ability to select items
874 * entirely and they will neither appear selected nor call selected
875 * callback functions.
876 *
877 * @see elm_toolbar_select_mode_get()
878 *
879 * @ingroup Toolbar
880 */
881EAPI void
882elm_toolbar_select_mode_set(Evas_Object *obj, Elm_Object_Select_Mode mode);
883
884/**
885 * Get the toolbar select mode.
886 *
887 * @param obj The toolbar object
888 * @return The select mode
889 * (If getting mode is failed, it returns ELM_OBJECT_SELECT_MODE_MAX)
890 *
891 * @see elm_toolbar_select_mode_set()
892 *
893 * @ingroup Toolbar
894 */
895EAPI Elm_Object_Select_Mode
896elm_toolbar_select_mode_get(const Evas_Object *obj);
897
898/**
899 * @}
900 */
diff --git a/libraries/elementary/src/lib/elm_tooltip.h b/libraries/elementary/src/lib/elm_tooltip.h
new file mode 100644
index 0000000..3daf1c7
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_tooltip.h
@@ -0,0 +1,100 @@
1/**
2 * @defgroup Tooltips Tooltips
3 * @ingroup Elementary
4 *
5 * The Tooltip is an (internal, for now) smart object used to show a
6 * content in a frame on mouse hover of objects(or widgets), with
7 * tips/information about them.
8 *
9 * @{
10 */
11
12/**
13 * Called back when a widget's tooltip is activated and needs content.
14 * @param data user-data given to elm_object_tooltip_content_cb_set()
15 * @param obj owner widget.
16 * @param tooltip The tooltip object (affix content to this!)
17 */
18typedef Evas_Object *(*Elm_Tooltip_Content_Cb)(void *data, Evas_Object *obj, Evas_Object *tooltip);
19
20/**
21 * Called back when a widget's item tooltip is activated and needs content.
22 * @param data user-data given to elm_object_tooltip_content_cb_set()
23 * @param obj owner widget.
24 * @param tooltip The tooltip object (affix content to this!)
25 * @param item context dependent item. As an example, if tooltip was
26 * set on elm_list item, then it is of this type.
27 */
28typedef Evas_Object *(*Elm_Tooltip_Item_Content_Cb)(void *data, Evas_Object *obj, Evas_Object *tooltip, void *item);
29
30EAPI void elm_object_tooltip_show(Evas_Object *obj);
31EAPI void elm_object_tooltip_hide(Evas_Object *obj);
32
33/**
34 * Set the text to be displayed inside the tooltip.
35 *
36 * @param obj The tooltip object.
37 * @param text The text to be displayed.
38 *
39 * @ingroup Tooltips
40 */
41EAPI void elm_object_tooltip_text_set(Evas_Object *obj, const char *text);
42EAPI void elm_object_tooltip_domain_translatable_text_set(Evas_Object *obj, const char *domain, const char *text);
43#define elm_object_tooltip_translatable_text_set(obj, text) elm_object_tooltip_domain_translatable_text_set((obj), NULL, (text))
44EAPI void elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb);
45EAPI void elm_object_tooltip_unset(Evas_Object *obj);
46
47/**
48 * Sets a different style for this object tooltip.
49 *
50 * @note before you set a style you should define a tooltip with
51 * elm_object_tooltip_content_cb_set() or
52 * elm_object_tooltip_text_set().
53 *
54 * @param obj an object with tooltip already set.
55 * @param style the theme style to use (default, transparent, ...)
56 *
57 * @ingroup Tooltips
58 */
59EAPI void elm_object_tooltip_style_set(Evas_Object *obj, const char *style);
60
61/**
62 * Get the style for this object tooltip.
63 *
64 * @param obj an object with tooltip already set.
65 * @return style the theme style in use, defaults to "default". If the
66 * object does not have a tooltip set, then NULL is returned.
67 *
68 * @ingroup Tooltips
69 */
70EAPI const char *elm_object_tooltip_style_get(const Evas_Object *obj);
71
72/**
73 * @brief Disable size restrictions on an object's tooltip
74 * @param obj The tooltip's anchor object
75 * @param disable If EINA_TRUE, size restrictions are disabled
76 * @return EINA_FALSE on failure, EINA_TRUE on success
77 *
78 * This function allows a tooltip to expand beyond its parent window's canvas.
79 * It will instead be limited only by the size of the display.
80 *
81 * @ingroup Tooltips
82 */
83EAPI Eina_Bool elm_object_tooltip_window_mode_set(Evas_Object *obj, Eina_Bool disable);
84
85/**
86 * @brief Retrieve size restriction state of an object's tooltip
87 * @param obj The tooltip's anchor object
88 * @return If EINA_TRUE, size restrictions are disabled
89 *
90 * This function returns whether a tooltip is allowed to expand beyond
91 * its parent window's canvas.
92 * It will instead be limited only by the size of the display.
93 *
94 * @ingroup Tooltips
95 */
96EAPI Eina_Bool elm_object_tooltip_window_mode_get(const Evas_Object *obj);
97
98/**
99 * @}
100 */
diff --git a/libraries/elementary/src/lib/elm_transit.c b/libraries/elementary/src/lib/elm_transit.c
new file mode 100644
index 0000000..70c7d83
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_transit.c
@@ -0,0 +1,2357 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define ELM_TRANSIT_CHECK_OR_RETURN(transit, ...) \
5 do { \
6 if (!transit) { \
7 CRITICAL("Elm_Transit " # transit " is NULL!"); \
8 return __VA_ARGS__; \
9 } \
10 if (!EINA_MAGIC_CHECK(transit, ELM_TRANSIT_MAGIC)) { \
11 EINA_MAGIC_FAIL(transit, ELM_TRANSIT_MAGIC); \
12 return __VA_ARGS__; \
13 } \
14 if (transit->deleted){ \
15 ERR("Elm_Transit " # transit " has already been deleted!"); \
16 return __VA_ARGS__; \
17 } \
18 } while (0)
19
20
21#define _TRANSIT_FOCAL 2000
22
23struct _Elm_Transit
24{
25#define ELM_TRANSIT_MAGIC 0xd27f190a
26 EINA_MAGIC;
27
28 Ecore_Animator *animator;
29 Eina_Inlist *effect_list;
30 Eina_List *objs;
31 Elm_Transit *prev_chain_transit;
32 Eina_List *next_chain_transits;
33 Elm_Transit_Tween_Mode tween_mode;
34 struct
35 {
36 Elm_Transit_Del_Cb func;
37 void *arg;
38 } del_data;
39 struct
40 {
41 double delayed;
42 double paused;
43 double duration;
44 double begin;
45 double current;
46 } time;
47 struct
48 {
49 int count;
50 int current;
51 Eina_Bool reverse;
52 } repeat;
53 double progress;
54 unsigned int effects_pending_del;
55 int walking;
56 Eina_Bool auto_reverse : 1;
57 Eina_Bool event_enabled : 1;
58 Eina_Bool deleted : 1;
59 Eina_Bool state_keep : 1;
60 Eina_Bool finished : 1;
61};
62
63struct _Elm_Transit_Effect_Module
64{
65 EINA_INLIST;
66 Elm_Transit_Effect_Transition_Cb transition_cb;
67 Elm_Transit_Effect_End_Cb end_cb;
68 Elm_Transit_Effect *effect;
69 Eina_Bool deleted : 1;
70};
71
72struct _Elm_Transit_Obj_State
73{
74 Evas_Coord x, y, w, h;
75 int r,g,b,a;
76 Evas_Map *map;
77 Eina_Bool map_enabled : 1;
78 Eina_Bool visible : 1;
79};
80
81struct _Elm_Transit_Obj_Data
82{
83 struct _Elm_Transit_Obj_State *state;
84 Eina_Bool freeze_events : 1;
85};
86
87typedef struct _Elm_Transit_Effect_Module Elm_Transit_Effect_Module;
88typedef struct _Elm_Transit_Obj_Data Elm_Transit_Obj_Data;
89typedef struct _Elm_Transit_Obj_State Elm_Transit_Obj_State;
90
91static void _transit_obj_data_update(Elm_Transit *transit, Evas_Object *obj);
92static void _transit_obj_data_recover(Elm_Transit *transit, Evas_Object *obj);
93static void _transit_obj_states_save(Evas_Object *obj, Elm_Transit_Obj_Data *obj_data);
94static void _transit_obj_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
95static void _transit_obj_remove(Elm_Transit *transit, Evas_Object *obj);
96static void _transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module);
97static void _transit_remove_dead_effects(Elm_Transit *transit);
98static void _transit_chain_go(Elm_Transit *transit);
99static void _transit_del(Elm_Transit *transit);
100static Eina_Bool _transit_animate_op(Elm_Transit *transit, double progress);
101static Eina_Bool _transit_animate_cb(void *data);
102
103static char *_transit_key= "_elm_transit_key";
104
105static void
106_transit_obj_data_update(Elm_Transit *transit, Evas_Object *obj)
107{
108 Elm_Transit_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
109
110 if (!obj_data)
111 obj_data = ELM_NEW(Elm_Transit_Obj_Data);
112
113 obj_data->freeze_events = evas_object_freeze_events_get(obj);
114
115 if ((!transit->state_keep) && (obj_data->state))
116 {
117 free(obj_data->state);
118 obj_data->state = NULL;
119 }
120 else
121 {
122 _transit_obj_states_save(obj, obj_data);
123 }
124
125 evas_object_data_set(obj, _transit_key, obj_data);
126}
127
128static void
129_transit_obj_states_save(Evas_Object *obj, Elm_Transit_Obj_Data *obj_data)
130{
131 Elm_Transit_Obj_State *state = obj_data->state;
132
133 if (!state)
134 state = calloc(1, sizeof(Elm_Transit_Obj_State));
135 if (!state) return;
136
137 evas_object_geometry_get(obj, &state->x, &state->y, &state->w, &state->h);
138 evas_object_color_get(obj, &state->r, &state->g, &state->b, &state->a);
139 state->visible = evas_object_visible_get(obj);
140 state->map_enabled = evas_object_map_enable_get(obj);
141 if (evas_object_map_get(obj))
142 state->map = evas_map_dup(evas_object_map_get(obj));
143 obj_data->state = state;
144}
145
146static void
147_remove_obj_from_list(Elm_Transit *transit, Evas_Object *obj)
148{
149 //Remove duplicated objects
150 //TODO: Need to consider about optimizing here
151 while (1)
152 {
153 if (!eina_list_data_find_list(transit->objs, obj))
154 break;
155 transit->objs = eina_list_remove(transit->objs, obj);
156 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
157 _transit_obj_remove_cb,
158 transit);
159 }
160}
161
162static void
163_transit_obj_remove_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
164{
165 Elm_Transit *transit = data;
166 Elm_Transit_Obj_Data *obj_data = evas_object_data_get(obj, _transit_key);
167 if (obj_data)
168 {
169 if (obj_data->state)
170 free(obj_data->state);
171 free(obj_data);
172 }
173 _remove_obj_from_list(transit, obj);
174 if (!transit->objs) elm_transit_del(transit);
175}
176
177static void
178_transit_obj_data_recover(Elm_Transit *transit, Evas_Object *obj)
179{
180 Elm_Transit_Obj_Data *obj_data;
181 Elm_Transit_Obj_State *state;
182
183 obj_data = evas_object_data_get(obj, _transit_key);
184 if (!obj_data) return;
185 evas_object_data_del(obj, _transit_key);
186 evas_object_freeze_events_set(obj, obj_data->freeze_events);
187 state = obj_data->state;
188 if (state)
189 {
190 //recover the states of the object.
191 if (!transit->state_keep)
192 {
193 evas_object_move(obj, state->x, state->y);
194 evas_object_resize(obj, state->w, state->h);
195 evas_object_color_set(obj, state->r, state->g, state->b, state->a);
196 if (state->visible) evas_object_show(obj);
197 else evas_object_hide(obj);
198 evas_object_map_enable_set(obj, state->map_enabled);
199 evas_object_map_set(obj, state->map);
200 }
201 free(state);
202 }
203 free(obj_data);
204}
205
206static void
207_transit_obj_remove(Elm_Transit *transit, Evas_Object *obj)
208{
209 _remove_obj_from_list(transit, obj);
210 _transit_obj_data_recover(transit, obj);
211}
212
213static void
214_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Module *effect_module)
215{
216 if (effect_module->end_cb)
217 effect_module->end_cb(effect_module->effect, transit);
218 free(effect_module);
219}
220
221static void
222_transit_remove_dead_effects(Elm_Transit *transit)
223{
224 Elm_Transit_Effect_Module *effect_module;
225
226 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
227 {
228 if (effect_module->deleted)
229 {
230 _transit_effect_del(transit, effect_module);
231 transit->effects_pending_del--;
232 if (!transit->effects_pending_del) return;
233 }
234 }
235}
236
237static void
238_transit_chain_go(Elm_Transit *transit)
239{
240 ELM_TRANSIT_CHECK_OR_RETURN(transit);
241 elm_transit_go(transit);
242 _transit_animate_cb(transit);
243}
244
245static void
246_transit_del(Elm_Transit *transit)
247{
248 Elm_Transit_Effect_Module *effect_module;
249 Elm_Transit *chain_transit;
250 Eina_List *elist, *elist_next;
251
252 if (transit->animator)
253 ecore_animator_del(transit->animator);
254
255 //remove effects
256 while (transit->effect_list)
257 {
258 effect_module = EINA_INLIST_CONTAINER_GET(transit->effect_list, Elm_Transit_Effect_Module);
259 transit->effect_list = eina_inlist_remove(transit->effect_list, transit->effect_list);
260 _transit_effect_del(transit, effect_module);
261 }
262
263 //remove objects.
264 while (transit->objs)
265 _transit_obj_remove(transit, eina_list_data_get(transit->objs));
266
267 transit->deleted = EINA_TRUE;
268
269 if (transit->del_data.func)
270 transit->del_data.func(transit->del_data.arg, transit);
271
272 //cut off the chain transit relationship
273 EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
274 chain_transit->prev_chain_transit = NULL;
275
276 if (transit->prev_chain_transit)
277 transit->prev_chain_transit->next_chain_transits =
278 eina_list_remove(transit->prev_chain_transit->next_chain_transits, transit);
279
280 // run chain transits
281 if (transit->finished && transit->next_chain_transits)
282 {
283 EINA_LIST_FOREACH_SAFE(transit->next_chain_transits, elist, elist_next, chain_transit)
284 _transit_chain_go(chain_transit);
285
286 }
287
288 eina_list_free(transit->next_chain_transits);
289
290 EINA_MAGIC_SET(transit, EINA_MAGIC_NONE);
291 free(transit);
292}
293
294//If the transit is deleted then EINA_FALSE is retruned.
295static Eina_Bool
296_transit_animate_op(Elm_Transit *transit, double progress)
297{
298 Elm_Transit_Effect_Module *effect_module;
299
300 transit->walking++;
301 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
302 {
303 if (transit->deleted) break;
304 if (!effect_module->deleted)
305 effect_module->transition_cb(effect_module->effect, transit, progress);
306 }
307 transit->walking--;
308
309 if (transit->walking) return EINA_TRUE;
310
311 if (transit->deleted)
312 {
313 _transit_del(transit);
314 return EINA_FALSE;
315 }
316
317 else if (transit->effects_pending_del) _transit_remove_dead_effects(transit);
318
319 return EINA_TRUE;
320}
321
322static Eina_Bool
323_transit_animate_cb(void *data)
324{
325 Elm_Transit *transit = data;
326 double elapsed_time, duration;
327
328 transit->time.current = ecore_loop_time_get();
329 elapsed_time = transit->time.current - transit->time.begin;
330 duration = transit->time.duration + transit->time.delayed;
331
332 if (elapsed_time > duration)
333 elapsed_time = duration;
334
335 transit->progress = elapsed_time / duration;
336 switch (transit->tween_mode)
337 {
338 case ELM_TRANSIT_TWEEN_MODE_LINEAR:
339 transit->progress = ecore_animator_pos_map(transit->progress,
340 ECORE_POS_MAP_LINEAR,
341 0, 0);
342 case ELM_TRANSIT_TWEEN_MODE_ACCELERATE:
343 transit->progress = ecore_animator_pos_map(transit->progress,
344 ECORE_POS_MAP_ACCELERATE,
345 0, 0);
346 break;
347 case ELM_TRANSIT_TWEEN_MODE_DECELERATE:
348 transit->progress = ecore_animator_pos_map(transit->progress,
349 ECORE_POS_MAP_DECELERATE,
350 0, 0);
351 break;
352 case ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL:
353 transit->progress = ecore_animator_pos_map(transit->progress,
354 ECORE_POS_MAP_SINUSOIDAL,
355 0, 0);
356 break;
357 default:
358 break;
359 }
360
361 /* Reverse? */
362 if (transit->repeat.reverse) transit->progress = 1 - transit->progress;
363
364 if (transit->time.duration > 0)
365 {
366 if (!_transit_animate_op(transit, transit->progress))
367 return ECORE_CALLBACK_CANCEL;
368 }
369
370 /* Not end. Keep going. */
371 if (elapsed_time < duration) return ECORE_CALLBACK_RENEW;
372
373 /* Repeat and reverse and time done! */
374 if ((transit->repeat.count >= 0) &&
375 (transit->repeat.current == transit->repeat.count) &&
376 ((!transit->auto_reverse) || transit->repeat.reverse))
377 {
378 transit->finished = EINA_TRUE;
379 elm_transit_del(transit);
380 return ECORE_CALLBACK_CANCEL;
381 }
382
383 /* Repeat Case */
384 if (!transit->auto_reverse || transit->repeat.reverse)
385 {
386 transit->repeat.current++;
387 transit->repeat.reverse = EINA_FALSE;
388 }
389 else transit->repeat.reverse = EINA_TRUE;
390
391 transit->time.begin = ecore_loop_time_get();
392
393 return ECORE_CALLBACK_RENEW;
394}
395
396static void
397_recover_image_uv_by_y(Evas_Map *map, int iw, int ih)
398{
399 evas_map_point_image_uv_set(map, 0, iw, 0);
400 evas_map_point_image_uv_set(map, 1, 0, 0);
401 evas_map_point_image_uv_set(map, 2, 0, ih);
402 evas_map_point_image_uv_set(map, 3, iw, ih);
403}
404
405static void
406_recover_image_uv_by_x(Evas_Map *map, int iw, int ih)
407{
408 evas_map_point_image_uv_set(map, 0, 0, ih);
409 evas_map_point_image_uv_set(map, 1, iw, ih);
410 evas_map_point_image_uv_set(map, 2, iw, 0);
411 evas_map_point_image_uv_set(map, 3, 0, 0);
412}
413
414static Eina_Bool
415_recover_image_uv(Evas_Object *obj, Evas_Map *map, Eina_Bool revert, Eina_Bool by_x)
416{
417 //Since the map is not proper for all types of objects,
418 //Need to handle uvs only for image objects
419 int iw, ih;
420 const char *type = evas_object_type_get(obj);
421 if ((!type) || (strcmp(type, "image"))) return EINA_FALSE;
422
423 evas_object_image_size_get(obj, &iw, &ih);
424
425 if (revert)
426 {
427 if (by_x)
428 _recover_image_uv_by_x(map, iw, ih);
429 else
430 _recover_image_uv_by_y(map, iw, ih);
431 }
432 else
433 {
434 evas_map_point_image_uv_set(map, 0, 0, 0);
435 evas_map_point_image_uv_set(map, 1, iw, 0);
436 evas_map_point_image_uv_set(map, 2, iw, ih);
437 evas_map_point_image_uv_set(map, 3, 0, ih);
438 }
439 return EINA_TRUE;
440}
441
442EAPI Elm_Transit *
443elm_transit_add(void)
444{
445 Elm_Transit *transit = ELM_NEW(Elm_Transit);
446 if (!transit)
447 {
448 ERR("Failed to allocate a elm_transit object!");
449 return NULL;
450 }
451
452 EINA_MAGIC_SET(transit, ELM_TRANSIT_MAGIC);
453
454 elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
455
456 return transit;
457}
458
459EAPI void
460elm_transit_del(Elm_Transit *transit)
461{
462 ELM_TRANSIT_CHECK_OR_RETURN(transit);
463
464 if (transit->walking) transit->deleted = EINA_TRUE;
465 else _transit_del(transit);
466}
467
468EAPI void
469elm_transit_effect_add(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect, Elm_Transit_Effect_End_Cb end_cb)
470{
471 ELM_TRANSIT_CHECK_OR_RETURN(transit);
472 EINA_SAFETY_ON_NULL_RETURN(transition_cb);
473 Elm_Transit_Effect_Module *effect_module;
474
475 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
476 if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
477 {
478 WRN("elm_transit does not allow to add the duplicated effect! : transit=%p", transit);
479 return;
480 }
481
482 effect_module = ELM_NEW(Elm_Transit_Effect_Module);
483 if (!effect_module)
484 {
485 ERR("Failed to allocate a new effect!: transit=%p", transit);
486 return;
487 }
488
489 effect_module->end_cb = end_cb;
490 effect_module->transition_cb = transition_cb;
491 effect_module->effect = effect;
492
493 transit->effect_list = eina_inlist_append(transit->effect_list, (Eina_Inlist*) effect_module);
494}
495
496EAPI void
497elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect)
498{
499 ELM_TRANSIT_CHECK_OR_RETURN(transit);
500 EINA_SAFETY_ON_NULL_RETURN(transition_cb);
501 Elm_Transit_Effect_Module *effect_module;
502
503 EINA_INLIST_FOREACH(transit->effect_list, effect_module)
504 {
505 if ((effect_module->transition_cb == transition_cb) && (effect_module->effect == effect))
506 {
507 if (transit->walking)
508 {
509 effect_module->deleted = EINA_TRUE;
510 transit->effects_pending_del++;
511 }
512 else
513 {
514 _transit_effect_del(transit, effect_module);
515 if (!transit->effect_list) elm_transit_del(transit);
516 }
517 return;
518 }
519 }
520}
521
522EAPI void
523elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj)
524{
525 ELM_TRANSIT_CHECK_OR_RETURN(transit);
526 EINA_SAFETY_ON_NULL_RETURN(obj);
527
528 if (transit->animator)
529 {
530 if (!evas_object_data_get(obj, _transit_key))
531 {
532 _transit_obj_data_update(transit, obj);
533 evas_object_freeze_events_set(obj, EINA_TRUE);
534 }
535 }
536
537 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
538 _transit_obj_remove_cb,
539 transit);
540
541 transit->objs = eina_list_append(transit->objs, obj);
542}
543
544EAPI void
545elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj)
546{
547 ELM_TRANSIT_CHECK_OR_RETURN(transit);
548 EINA_SAFETY_ON_NULL_RETURN(obj);
549
550 _transit_obj_remove(transit, obj);
551 if (!transit->objs) elm_transit_del(transit);
552}
553
554EAPI const Eina_List *
555elm_transit_objects_get(const Elm_Transit *transit)
556{
557 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
558 return transit->objs;
559}
560
561EAPI void
562elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled)
563{
564 ELM_TRANSIT_CHECK_OR_RETURN(transit);
565
566 Eina_List *list;
567 Evas_Object *obj;
568
569 if (transit->event_enabled == enabled) return;
570 transit->event_enabled = !!enabled;
571 if (!transit->animator) return;
572
573 EINA_LIST_FOREACH(transit->objs, list, obj)
574 evas_object_freeze_events_set(obj, enabled);
575}
576
577EAPI Eina_Bool
578elm_transit_event_enabled_get(const Elm_Transit *transit)
579{
580 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
581 return transit->event_enabled;
582}
583
584EAPI void
585elm_transit_del_cb_set(Elm_Transit *transit, void (*cb) (void *data, Elm_Transit *transit), void *data)
586{
587 ELM_TRANSIT_CHECK_OR_RETURN(transit);
588 transit->del_data.func = cb;
589 transit->del_data.arg = data;
590}
591
592EAPI void
593elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse)
594{
595 ELM_TRANSIT_CHECK_OR_RETURN(transit);
596 transit->auto_reverse = reverse;
597}
598
599EAPI Eina_Bool
600elm_transit_auto_reverse_get(const Elm_Transit *transit)
601{
602 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
603 return transit->auto_reverse;
604}
605
606EAPI void
607elm_transit_repeat_times_set(Elm_Transit *transit, int repeat)
608{
609 ELM_TRANSIT_CHECK_OR_RETURN(transit);
610 transit->repeat.count = repeat;
611 transit->repeat.current = 0;
612}
613
614EAPI int
615elm_transit_repeat_times_get(const Elm_Transit *transit)
616{
617 ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
618 return transit->repeat.count;
619}
620
621EAPI void
622elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode)
623{
624 ELM_TRANSIT_CHECK_OR_RETURN(transit);
625 transit->tween_mode = tween_mode;
626}
627
628EAPI Elm_Transit_Tween_Mode
629elm_transit_tween_mode_get(const Elm_Transit *transit)
630{
631 ELM_TRANSIT_CHECK_OR_RETURN(transit, ELM_TRANSIT_TWEEN_MODE_LINEAR);
632 return transit->tween_mode;
633}
634
635EAPI void
636elm_transit_duration_set(Elm_Transit *transit, double duration)
637{
638 ELM_TRANSIT_CHECK_OR_RETURN(transit);
639 if (transit->animator)
640 {
641 WRN("elm_transit does not allow to set the duration time in operating! : transit=%p", transit);
642 return;
643 }
644 transit->time.duration = duration;
645}
646
647EAPI double
648elm_transit_duration_get(const Elm_Transit *transit)
649{
650 ELM_TRANSIT_CHECK_OR_RETURN(transit, 0.0);
651 return transit->time.duration;
652}
653
654EAPI void
655elm_transit_go(Elm_Transit *transit)
656{
657 ELM_TRANSIT_CHECK_OR_RETURN(transit);
658
659 Eina_List *elist;
660 Evas_Object *obj;
661
662 if (transit->animator)
663 ecore_animator_del(transit->animator);
664
665 EINA_LIST_FOREACH(transit->objs, elist, obj)
666 _transit_obj_data_update(transit, obj);
667
668 if (!transit->event_enabled)
669 {
670 EINA_LIST_FOREACH(transit->objs, elist, obj)
671 evas_object_freeze_events_set(obj, EINA_TRUE);
672 }
673
674 transit->time.paused = 0;
675 transit->time.delayed = 0;
676 transit->time.begin = ecore_loop_time_get();
677 transit->animator = ecore_animator_add(_transit_animate_cb, transit);
678}
679
680EAPI void
681elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused)
682{
683 ELM_TRANSIT_CHECK_OR_RETURN(transit);
684
685 if (!transit->animator) return;
686
687 if (paused)
688 {
689 if (transit->time.paused > 0)
690 return;
691 ecore_animator_freeze(transit->animator);
692 transit->time.paused = ecore_loop_time_get();
693 }
694 else
695 {
696 if (transit->time.paused == 0)
697 return;
698 ecore_animator_thaw(transit->animator);
699 transit->time.delayed += (ecore_loop_time_get() - transit->time.paused);
700 transit->time.paused = 0;
701 }
702}
703
704EAPI Eina_Bool
705elm_transit_paused_get(const Elm_Transit *transit)
706{
707 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
708
709 if (transit->time.paused == 0)
710 return EINA_FALSE;
711
712 return EINA_TRUE;
713}
714
715EAPI double
716elm_transit_progress_value_get(const Elm_Transit *transit)
717{
718 ELM_TRANSIT_CHECK_OR_RETURN(transit, 0);
719
720 return transit->progress;
721}
722
723EAPI void
724elm_transit_objects_final_state_keep_set(Elm_Transit *transit, Eina_Bool state_keep)
725{
726 ELM_TRANSIT_CHECK_OR_RETURN(transit);
727
728 if (transit->state_keep == state_keep) return;
729 if (transit->animator)
730 {
731 WRN("elm_transit does not allow to change final state keep mode in operating! : transit=%p", transit);
732 return;
733 }
734 transit->state_keep = !!state_keep;
735}
736
737EAPI Eina_Bool
738elm_transit_objects_final_state_keep_get(const Elm_Transit *transit)
739{
740 ELM_TRANSIT_CHECK_OR_RETURN(transit, EINA_FALSE);
741 return transit->state_keep;
742}
743
744EAPI void
745elm_transit_chain_transit_add(Elm_Transit *transit, Elm_Transit *chain_transit)
746{
747 ELM_TRANSIT_CHECK_OR_RETURN(transit);
748 ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
749
750 if (transit == chain_transit)
751 {
752 WRN("You add a same transit as a chain transit! : transit=%p, chain_transit=%p", transit, chain_transit);
753 return;
754 }
755 if (transit == chain_transit->prev_chain_transit)
756 return;
757
758 if (chain_transit->prev_chain_transit)
759 chain_transit->prev_chain_transit->next_chain_transits = eina_list_remove(chain_transit->prev_chain_transit->next_chain_transits, chain_transit);
760
761 chain_transit->prev_chain_transit = transit;
762 transit->next_chain_transits = eina_list_append(transit->next_chain_transits, chain_transit);
763}
764
765EAPI void
766elm_transit_chain_transit_del(Elm_Transit *transit, Elm_Transit *chain_transit)
767{
768 ELM_TRANSIT_CHECK_OR_RETURN(transit);
769 ELM_TRANSIT_CHECK_OR_RETURN(chain_transit);
770
771 if (chain_transit->prev_chain_transit != transit)
772 {
773 WRN("A pair of transits does not have the chain relationship! : transit=%p, chain_transit=%p", transit, chain_transit);
774 return;
775 }
776
777 chain_transit->prev_chain_transit = NULL;
778 transit->next_chain_transits = eina_list_remove(transit->next_chain_transits, chain_transit);
779}
780
781EAPI Eina_List *
782elm_transit_chain_transits_get(const Elm_Transit * transit)
783{
784 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
785 return transit->next_chain_transits;
786}
787
788///////////////////////////////////////////////////////////////////////////
789//Resizing Effect
790///////////////////////////////////////////////////////////////////////////
791typedef struct _Elm_Transit_Effect_Resizing Elm_Transit_Effect_Resizing;
792
793struct _Elm_Transit_Effect_Resizing
794{
795 struct _size {
796 Evas_Coord w, h;
797 } from, to;
798};
799
800static void
801_transit_effect_resizing_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
802{
803 Elm_Transit_Effect_Resizing *resizing = effect;
804 free(resizing);
805}
806
807static void
808_transit_effect_resizing_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
809{
810 EINA_SAFETY_ON_NULL_RETURN(effect);
811 EINA_SAFETY_ON_NULL_RETURN(transit);
812 Evas_Coord w, h;
813 Evas_Object *obj;
814 Eina_List *elist;
815 Elm_Transit_Effect_Resizing *resizing = effect;
816
817 w = resizing->from.w + (resizing->to.w * progress);
818 h = resizing->from.h + (resizing->to.h * progress);
819
820 EINA_LIST_FOREACH(transit->objs, elist, obj)
821 evas_object_resize(obj, w, h);
822}
823
824static Elm_Transit_Effect *
825_transit_effect_resizing_context_new(Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
826{
827 Elm_Transit_Effect_Resizing *resizing;
828
829 resizing = ELM_NEW(Elm_Transit_Effect_Resizing);
830 if (!resizing) return NULL;
831
832 resizing->from.w = from_w;
833 resizing->from.h = from_h;
834 resizing->to.w = to_w - from_w;
835 resizing->to.h = to_h - from_h;
836
837 return resizing;
838}
839
840EAPI Elm_Transit_Effect *
841elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h)
842{
843 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
844 Elm_Transit_Effect *effect = _transit_effect_resizing_context_new(from_w, from_h, to_w, to_h);
845
846 if (!effect)
847 {
848 ERR("Failed to allocate resizing effect! : transit=%p", transit);
849 return NULL;
850 }
851 elm_transit_effect_add(transit,
852 _transit_effect_resizing_op, effect,
853 _transit_effect_resizing_context_free);
854 return effect;
855}
856
857///////////////////////////////////////////////////////////////////////////
858//Translation Effect
859///////////////////////////////////////////////////////////////////////////
860typedef struct _Elm_Transit_Effect_Translation Elm_Transit_Effect_Translation;
861typedef struct _Elm_Transit_Effect_Translation_Node Elm_Transit_Effect_Translation_Node;
862
863struct _Elm_Transit_Effect_Translation_Node
864{
865 Evas_Object *obj;
866 Evas_Coord x, y;
867};
868
869struct _Elm_Transit_Effect_Translation
870{
871 struct _position_variation {
872 Evas_Coord dx, dy;
873 } from, to;
874 Eina_List *nodes;
875};
876
877static void
878_translation_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
879{
880 Elm_Transit_Effect_Translation *translation = data;
881 Eina_List *elist;
882 Elm_Transit_Effect_Translation_Node *translation_node;
883
884 EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
885 {
886 if (translation_node->obj != obj) continue;
887 translation->nodes = eina_list_remove_list(translation->nodes, elist);
888 free(translation_node);
889 break;
890 }
891}
892
893static Eina_List *
894_translation_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Translation *translation)
895{
896 Elm_Transit_Effect_Translation_Node *translation_node;
897 const Eina_List *elist;
898 Evas_Object *obj;
899 Eina_List *data_list = NULL;
900 const Eina_List *objs = elm_transit_objects_get(transit);
901
902 EINA_LIST_FOREACH(objs, elist, obj)
903 {
904 translation_node = ELM_NEW(Elm_Transit_Effect_Translation_Node);
905 if (!translation_node)
906 {
907 eina_list_free(data_list);
908 return NULL;
909 }
910 translation_node->obj = obj;
911 evas_object_geometry_get(obj, &(translation_node->x),
912 &(translation_node->y), NULL, NULL);
913 data_list = eina_list_append(data_list, translation_node);
914 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
915 _translation_object_del_cb, translation);
916 }
917 return data_list;
918}
919
920void
921_transit_effect_translation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
922{
923 EINA_SAFETY_ON_NULL_RETURN(effect);
924 Elm_Transit_Effect_Translation *translation = effect;
925 Eina_List *elist, *elist_next;
926 Elm_Transit_Effect_Translation_Node *translation_node;
927
928 EINA_LIST_FOREACH_SAFE(translation->nodes,
929 elist, elist_next, translation_node)
930 {
931 evas_object_event_callback_del(translation_node->obj,
932 EVAS_CALLBACK_DEL, _translation_object_del_cb);
933 translation->nodes = eina_list_remove_list(translation->nodes, elist);
934 free(translation_node);
935 }
936 free(translation);
937}
938
939void
940_transit_effect_translation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress __UNUSED__)
941{
942 EINA_SAFETY_ON_NULL_RETURN(effect);
943 EINA_SAFETY_ON_NULL_RETURN(transit);
944 Evas_Coord x, y;
945 Elm_Transit_Effect_Translation *translation = effect;
946 Elm_Transit_Effect_Translation_Node *translation_node;
947 Eina_List *elist;
948
949 if (!translation->nodes)
950 translation->nodes = _translation_nodes_build(transit, translation);
951
952 EINA_LIST_FOREACH(translation->nodes, elist, translation_node)
953 {
954 x = translation_node->x + translation->from.dx
955 + (translation->to.dx * progress);
956 y = translation_node->y + translation->from.dy
957 + (translation->to.dy * progress);
958 evas_object_move(translation_node->obj, x, y);
959 }
960}
961
962static Elm_Transit_Effect *
963_transit_effect_translation_context_new(Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
964{
965 Elm_Transit_Effect_Translation *translation;
966
967 translation = ELM_NEW(Elm_Transit_Effect_Translation);
968 if (!translation) return NULL;
969
970 translation->from.dx = from_dx;
971 translation->from.dy = from_dy;
972 translation->to.dx = to_dx - from_dx;
973 translation->to.dy = to_dy - from_dy;
974
975 return translation;
976}
977
978EAPI Elm_Transit_Effect *
979elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy)
980{
981 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
982 Elm_Transit_Effect *effect = _transit_effect_translation_context_new(from_dx, from_dy, to_dx, to_dy);
983
984 if (!effect)
985 {
986 ERR("Failed to allocate translation effect! : transit=%p", transit);
987 return NULL;
988 }
989 elm_transit_effect_add(transit,
990 _transit_effect_translation_op, effect,
991 _transit_effect_translation_context_free);
992 return effect;
993}
994
995///////////////////////////////////////////////////////////////////////////
996//Zoom Effect
997///////////////////////////////////////////////////////////////////////////
998typedef struct _Elm_Transit_Effect_Zoom Elm_Transit_Effect_Zoom;
999
1000struct _Elm_Transit_Effect_Zoom
1001{
1002 float from, to;
1003};
1004
1005void
1006_transit_effect_zoom_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1007{
1008 Elm_Transit_Effect_Zoom *zoom = effect;
1009 free(zoom);
1010}
1011
1012static void
1013_transit_effect_zoom_op(Elm_Transit_Effect *effect, Elm_Transit *transit , double progress)
1014{
1015 EINA_SAFETY_ON_NULL_RETURN(effect);
1016 EINA_SAFETY_ON_NULL_RETURN(transit);
1017 Evas_Object *obj;
1018 Eina_List *elist;
1019 Elm_Transit_Effect_Zoom *zoom = effect;
1020 Evas_Map *map;
1021 Evas_Coord x, y, w, h;
1022
1023 map = evas_map_new(4);
1024 if (!map) return;
1025
1026 EINA_LIST_FOREACH(transit->objs, elist, obj)
1027 {
1028 evas_object_geometry_get(obj, &x, &y, &w, &h);
1029 evas_map_util_points_populate_from_object_full(map, obj, zoom->from +
1030 (progress * zoom->to));
1031 _recover_image_uv(obj, map, EINA_FALSE, EINA_FALSE);
1032 evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0,
1033 _TRANSIT_FOCAL);
1034 evas_object_map_set(obj, map);
1035 evas_object_map_enable_set(obj, EINA_TRUE);
1036 }
1037 evas_map_free(map);
1038}
1039
1040static Elm_Transit_Effect *
1041_transit_effect_zoom_context_new(float from_rate, float to_rate)
1042{
1043 Elm_Transit_Effect_Zoom *zoom;
1044
1045 zoom = ELM_NEW(Elm_Transit_Effect_Zoom);
1046 if (!zoom) return NULL;
1047
1048 zoom->from = (_TRANSIT_FOCAL - (from_rate * _TRANSIT_FOCAL)) * (1 / from_rate);
1049 zoom->to = ((_TRANSIT_FOCAL - (to_rate * _TRANSIT_FOCAL)) * (1 / to_rate)) - zoom->from;
1050
1051 return zoom;
1052}
1053
1054EAPI Elm_Transit_Effect *
1055elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate)
1056{
1057 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1058 Elm_Transit_Effect *effect = _transit_effect_zoom_context_new(from_rate, to_rate);
1059
1060 if (!effect)
1061 {
1062 ERR("Failed to allocate zoom effect! : transit=%p", transit);
1063 return NULL;
1064 }
1065 elm_transit_effect_add(transit,
1066 _transit_effect_zoom_op, effect,
1067 _transit_effect_zoom_context_free);
1068 return effect;
1069}
1070
1071///////////////////////////////////////////////////////////////////////////
1072//Flip Effect
1073///////////////////////////////////////////////////////////////////////////
1074typedef struct _Elm_Transit_Effect_Flip Elm_Transit_Effect_Flip;
1075
1076struct _Elm_Transit_Effect_Flip
1077{
1078 Elm_Transit_Effect_Flip_Axis axis;
1079 Eina_Bool cw : 1;
1080};
1081
1082static void
1083_transit_effect_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1084{
1085 EINA_SAFETY_ON_NULL_RETURN(effect);
1086 EINA_SAFETY_ON_NULL_RETURN(transit);
1087 Elm_Transit_Effect_Flip *flip = effect;
1088 Evas_Object *front, *back;
1089 int i;
1090 int count = eina_list_count(transit->objs);
1091
1092 for (i = 0; i < (count - 1); i += 2)
1093 {
1094 front = eina_list_nth(transit->objs, i);
1095 back = eina_list_nth(transit->objs, i+1);
1096 evas_object_map_enable_set(front, EINA_FALSE);
1097 evas_object_map_enable_set(back, EINA_FALSE);
1098 }
1099 free(flip);
1100}
1101
1102static void
1103_transit_effect_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1104{
1105 EINA_SAFETY_ON_NULL_RETURN(effect);
1106 EINA_SAFETY_ON_NULL_RETURN(transit);
1107 Evas_Object *obj, *front, *back;
1108 int count, i;
1109 Elm_Transit_Effect_Flip *flip = effect;
1110 Evas_Map *map;
1111 float degree;
1112 Evas_Coord x, y, w, h;
1113
1114 map = evas_map_new(4);
1115 if (!map) return;
1116
1117 if (flip->cw) degree = (float)(progress * 180);
1118 else degree = (float)(progress * -180);
1119
1120 count = eina_list_count(transit->objs);
1121
1122 for (i = 0; i < (count - 1); i += 2)
1123 {
1124 Evas_Coord half_w, half_h;
1125
1126 front = eina_list_nth(transit->objs, i);
1127 back = eina_list_nth(transit->objs, i+1);
1128
1129 if ((degree < 90) && (degree > -90))
1130 {
1131 obj = front;
1132 if (front != back)
1133 {
1134 evas_object_hide(back);
1135 evas_object_show(front);
1136 }
1137 }
1138 else
1139 {
1140 obj = back;
1141 if (front != back)
1142 {
1143 evas_object_hide(front);
1144 evas_object_show(back);
1145 }
1146 }
1147
1148 evas_map_util_points_populate_from_object_full(map, obj, 0);
1149 evas_object_geometry_get(obj, &x, &y, &w, &h);
1150 half_w = (w / 2);
1151 half_h = (h / 2);
1152
1153 if (flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1154 {
1155 if ((degree >= 90) || (degree <= -90))
1156 {
1157 if (!_recover_image_uv(obj, map, EINA_TRUE, EINA_FALSE))
1158 {
1159 evas_map_point_image_uv_set(map, 0, w, 0);
1160 evas_map_point_image_uv_set(map, 1, 0, 0);
1161 evas_map_point_image_uv_set(map, 2, 0, h);
1162 evas_map_point_image_uv_set(map, 3, w, h);
1163 }
1164 }
1165 else
1166 _recover_image_uv(obj, map, EINA_FALSE, EINA_FALSE);
1167 evas_map_util_3d_rotate(map, 0, degree,
1168 0, x + half_w, y + half_h, 0);
1169 }
1170 else
1171 {
1172 if ((degree >= 90) || (degree <= -90))
1173 {
1174 if (!_recover_image_uv(obj, map, EINA_TRUE, EINA_TRUE))
1175 {
1176 evas_map_point_image_uv_set(map, 0, 0, h);
1177 evas_map_point_image_uv_set(map, 1, w, h);
1178 evas_map_point_image_uv_set(map, 2, w, 0);
1179 evas_map_point_image_uv_set(map, 3, 0, 0);
1180 }
1181 }
1182 else
1183 _recover_image_uv(obj, map, EINA_FALSE, EINA_FALSE);
1184 evas_map_util_3d_rotate(map, degree,
1185 0, 0, x + half_w, y + half_h, 0);
1186 }
1187 evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
1188 evas_object_map_enable_set(front, EINA_TRUE);
1189 evas_object_map_enable_set(back, EINA_TRUE);
1190 evas_object_map_set(obj, map);
1191 }
1192 evas_map_free(map);
1193}
1194
1195static Elm_Transit_Effect *
1196_transit_effect_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1197{
1198 Elm_Transit_Effect_Flip *flip;
1199
1200 flip = ELM_NEW(Elm_Transit_Effect_Flip);
1201 if (!flip) return NULL;
1202
1203 flip->cw = cw;
1204 flip->axis = axis;
1205
1206 return flip;
1207}
1208
1209EAPI Elm_Transit_Effect *
1210elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1211{
1212 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1213 Elm_Transit_Effect *effect = _transit_effect_flip_context_new(axis, cw);
1214
1215 if (!effect)
1216 {
1217 ERR("Failed to allocate flip effect! : transit=%p", transit);
1218 return NULL;
1219 }
1220 elm_transit_effect_add(transit,
1221 _transit_effect_flip_op, effect,
1222 _transit_effect_flip_context_free);
1223 return effect;
1224}
1225
1226///////////////////////////////////////////////////////////////////////////
1227//ResizableFlip Effect
1228///////////////////////////////////////////////////////////////////////////
1229typedef struct _Elm_Transit_Effect_Resizable_Flip Elm_Transit_Effect_ResizableFlip;
1230typedef struct _Elm_Transit_Effect_Resizable_Flip_Node Elm_Transit_Effect_ResizableFlip_Node;
1231
1232struct _Elm_Transit_Effect_Resizable_Flip_Node
1233{
1234 Evas_Object *front;
1235 Evas_Object *back;
1236 struct _vector2d {
1237 float x, y;
1238 } from_pos, from_size, to_pos, to_size;
1239};
1240
1241struct _Elm_Transit_Effect_Resizable_Flip
1242{
1243 Eina_List *nodes;
1244 Eina_Bool cw : 1;
1245 Elm_Transit_Effect_Flip_Axis axis;
1246};
1247
1248static void
1249_resizable_flip_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1250{
1251 Elm_Transit_Effect_ResizableFlip *resizable_flip = data;
1252 Eina_List *elist;
1253 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1254
1255 EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1256 {
1257 if (resizable_flip_node->front == obj)
1258 evas_object_event_callback_del(resizable_flip_node->back,
1259 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1260 else if (resizable_flip_node->back == obj)
1261 evas_object_event_callback_del(resizable_flip_node->front,
1262 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1263 else continue;
1264
1265 resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1266 elist);
1267 free(resizable_flip_node);
1268 break;
1269 }
1270}
1271
1272static Eina_List *
1273_resizable_flip_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_ResizableFlip *resizable_flip)
1274{
1275 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1276 Eina_List *data_list = NULL;
1277 Evas_Coord front_x, front_y, front_w, front_h;
1278 Evas_Coord back_x, back_y, back_w, back_h;
1279 int i, count;
1280
1281 count = eina_list_count(transit->objs);
1282 for (i = 0; i < (count - 1); i += 2)
1283 {
1284 resizable_flip_node = ELM_NEW(Elm_Transit_Effect_ResizableFlip_Node);
1285 if (!resizable_flip_node)
1286 {
1287 eina_list_free(data_list);
1288 return NULL;
1289 }
1290
1291 resizable_flip_node->front = eina_list_nth(transit->objs, i);
1292 resizable_flip_node->back = eina_list_nth(transit->objs, i+1);
1293
1294 evas_object_geometry_get(resizable_flip_node->front,
1295 &front_x, &front_y, &front_w, &front_h);
1296 evas_object_geometry_get(resizable_flip_node->back,
1297 &back_x, &back_y, &back_w, &back_h);
1298
1299 resizable_flip_node->from_pos.x = front_x;
1300 resizable_flip_node->from_pos.y = front_y;
1301 resizable_flip_node->to_pos.x = back_x - front_x;
1302 resizable_flip_node->to_pos.y = back_y - front_y;
1303
1304 resizable_flip_node->from_size.x = front_w;
1305 resizable_flip_node->from_size.y = front_h;
1306 resizable_flip_node->to_size.x = back_w - front_w;
1307 resizable_flip_node->to_size.y = back_h - front_h;
1308
1309 data_list = eina_list_append(data_list, resizable_flip_node);
1310
1311 evas_object_event_callback_add(resizable_flip_node->back,
1312 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1313 evas_object_event_callback_add(resizable_flip_node->front,
1314 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb, resizable_flip);
1315 }
1316
1317 return data_list;
1318}
1319
1320static void
1321_set_image_uv_by_axis_y(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, Eina_Bool revert)
1322{
1323 if (revert)
1324 {
1325 evas_map_point_image_uv_set(map, 0,
1326 (flip->from_size.x * 2) + flip->to_size.x,
1327 0);
1328 evas_map_point_image_uv_set(map, 1, 0, 0);
1329 evas_map_point_image_uv_set(map, 2, 0,
1330 (flip->from_size.y * 2) + flip->to_size.y);
1331 evas_map_point_image_uv_set(map, 3,
1332 (flip->from_size.x * 2) + flip->to_size.x,
1333 (flip->from_size.y * 2) + flip->to_size.y);
1334 }
1335 else
1336 {
1337 evas_map_point_image_uv_set(map, 0, 0, 0);
1338 evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1339 evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1340 flip->from_size.y);
1341 evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1342 }
1343}
1344
1345static void
1346_set_image_uv_by_axis_x(Evas_Map *map, Elm_Transit_Effect_ResizableFlip_Node *flip, Eina_Bool revert)
1347{
1348 if (revert)
1349 {
1350 evas_map_point_image_uv_set(map, 0, 0,
1351 (flip->from_size.y * 2) + flip->to_size.y);
1352 evas_map_point_image_uv_set(map, 1,
1353 (flip->from_size.x * 2) + flip->to_size.x,
1354 (flip->from_size.y * 2) + flip->to_size.y);
1355 evas_map_point_image_uv_set(map, 2,
1356 (flip->from_size.x * 2) + flip->to_size.x,
1357 0);
1358 evas_map_point_image_uv_set(map, 3, 0, 0);
1359 }
1360 else
1361 {
1362 evas_map_point_image_uv_set(map, 0, 0, 0);
1363 evas_map_point_image_uv_set(map, 1, flip->from_size.x, 0);
1364 evas_map_point_image_uv_set(map, 2, flip->from_size.x,
1365 flip->from_size.y);
1366 evas_map_point_image_uv_set(map, 3, 0, flip->from_size.y);
1367 }
1368}
1369
1370void
1371_transit_effect_resizable_flip_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1372{
1373 EINA_SAFETY_ON_NULL_RETURN(effect);
1374
1375 Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1376 Eina_List *elist, *elist_next;
1377 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1378
1379 EINA_LIST_FOREACH_SAFE(resizable_flip->nodes,
1380 elist, elist_next, resizable_flip_node)
1381 {
1382 evas_object_map_enable_set(resizable_flip_node->front, EINA_FALSE);
1383 evas_object_map_enable_set(resizable_flip_node->back, EINA_FALSE);
1384
1385 resizable_flip->nodes = eina_list_remove_list(resizable_flip->nodes,
1386 elist);
1387
1388 evas_object_event_callback_del(resizable_flip_node->back,
1389 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1390 evas_object_event_callback_del(resizable_flip_node->front,
1391 EVAS_CALLBACK_DEL, _resizable_flip_object_del_cb);
1392 free(resizable_flip_node);
1393 }
1394 free(resizable_flip);
1395}
1396
1397void
1398_transit_effect_resizable_flip_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1399{
1400 EINA_SAFETY_ON_NULL_RETURN(effect);
1401 Evas_Map *map;
1402 Evas_Object *obj;
1403 float x, y, w, h;
1404 float degree;
1405 Evas_Coord half_w, half_h;
1406 Elm_Transit_Effect_ResizableFlip *resizable_flip = effect;
1407 Elm_Transit_Effect_ResizableFlip_Node *resizable_flip_node;
1408 Eina_List *elist;
1409
1410 map = evas_map_new(4);
1411 if (!map) return;
1412
1413 if (resizable_flip->cw) degree = (float)(progress * 180);
1414 else degree = (float)(progress * -180);
1415
1416 if (!resizable_flip->nodes)
1417 resizable_flip->nodes = _resizable_flip_nodes_build(transit,
1418 resizable_flip);
1419
1420 EINA_LIST_FOREACH(resizable_flip->nodes, elist, resizable_flip_node)
1421 {
1422 if ((degree < 90) && (degree > -90))
1423 {
1424 obj = resizable_flip_node->front;
1425 if (resizable_flip_node->front != resizable_flip_node->back)
1426 {
1427 evas_object_hide(resizable_flip_node->back);
1428 evas_object_show(resizable_flip_node->front);
1429 }
1430 }
1431 else
1432 {
1433 obj = resizable_flip_node->back;
1434 if (resizable_flip_node->front != resizable_flip_node->back)
1435 {
1436 evas_object_hide(resizable_flip_node->front);
1437 evas_object_show(resizable_flip_node->back);
1438 }
1439 }
1440
1441 x = resizable_flip_node->from_pos.x +
1442 (resizable_flip_node->to_pos.x * progress);
1443 y = resizable_flip_node->from_pos.y +
1444 (resizable_flip_node->to_pos.y * progress);
1445 w = resizable_flip_node->from_size.x +
1446 (resizable_flip_node->to_size.x * progress);
1447 h = resizable_flip_node->from_size.y +
1448 (resizable_flip_node->to_size.y * progress);
1449 evas_map_point_coord_set(map, 0, x, y, 0);
1450 evas_map_point_coord_set(map, 1, x + w, y, 0);
1451 evas_map_point_coord_set(map, 2, x + w, y + h, 0);
1452 evas_map_point_coord_set(map, 3, x, y + h, 0);
1453
1454 half_w = (Evas_Coord)(w / 2);
1455 half_h = (Evas_Coord)(h / 2);
1456
1457 if (resizable_flip->axis == ELM_TRANSIT_EFFECT_FLIP_AXIS_Y)
1458 {
1459 if ((degree >= 90) || (degree <= -90))
1460 {
1461 if (!_recover_image_uv(obj, map, EINA_TRUE, EINA_FALSE))
1462 _set_image_uv_by_axis_y(map, resizable_flip_node,
1463 EINA_TRUE);
1464 }
1465 else
1466 {
1467 if (!_recover_image_uv(obj, map, EINA_FALSE, EINA_FALSE))
1468 _set_image_uv_by_axis_y(map, resizable_flip_node,
1469 EINA_FALSE);
1470 }
1471 evas_map_util_3d_rotate(map, 0, degree,
1472 0, x + half_w, y + half_h, 0);
1473 }
1474 else
1475 {
1476 if ((degree >= 90) || (degree <= -90))
1477 {
1478 if (!_recover_image_uv(obj, map, EINA_TRUE, EINA_TRUE))
1479 _set_image_uv_by_axis_x(map, resizable_flip_node,
1480 EINA_TRUE);
1481 }
1482 else
1483 {
1484 if (!_recover_image_uv(obj, map, EINA_FALSE, EINA_TRUE))
1485 _set_image_uv_by_axis_x(map, resizable_flip_node,
1486 EINA_FALSE);
1487 }
1488 evas_map_util_3d_rotate(map, degree, 0,
1489 0, x + half_w, y + half_h, 0);
1490 }
1491
1492 evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0,
1493 _TRANSIT_FOCAL);
1494 evas_object_map_enable_set(resizable_flip_node->front, EINA_TRUE);
1495 evas_object_map_enable_set(resizable_flip_node->back, EINA_TRUE);
1496 evas_object_map_set(obj, map);
1497 }
1498 evas_map_free(map);
1499}
1500
1501static Elm_Transit_Effect *
1502_transit_effect_resizable_flip_context_new(Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1503{
1504 Elm_Transit_Effect_ResizableFlip *resizable_flip;
1505
1506 resizable_flip = ELM_NEW(Elm_Transit_Effect_ResizableFlip);
1507 if (!resizable_flip) return NULL;
1508
1509 resizable_flip->cw = cw;
1510 resizable_flip->axis = axis;
1511
1512 return resizable_flip;
1513}
1514
1515EAPI Elm_Transit_Effect *
1516elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw)
1517{
1518 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1519 Elm_Transit_Effect *effect = _transit_effect_resizable_flip_context_new(axis, cw);
1520
1521 if (!effect)
1522 {
1523 ERR("Failed to allocate resizable_flip effect! : transit=%p", transit);
1524 return NULL;
1525 }
1526 elm_transit_effect_add(transit,
1527 _transit_effect_resizable_flip_op, effect,
1528 _transit_effect_resizable_flip_context_free);
1529 return effect;
1530}
1531
1532///////////////////////////////////////////////////////////////////////////
1533//Wipe Effect
1534///////////////////////////////////////////////////////////////////////////
1535typedef struct _Elm_Transit_Effect_Wipe Elm_Transit_Effect_Wipe;
1536
1537struct _Elm_Transit_Effect_Wipe
1538{
1539 Elm_Transit_Effect_Wipe_Type type;
1540 Elm_Transit_Effect_Wipe_Dir dir;
1541};
1542
1543static void
1544_elm_fx_wipe_hide(Evas_Map * map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1545{
1546 float w2, h2;
1547
1548 switch (dir)
1549 {
1550 case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1551 w2 = w - (w * progress);
1552 h2 = (y + h);
1553 evas_map_point_image_uv_set(map, 0, 0, 0);
1554 evas_map_point_image_uv_set(map, 1, w2, 0);
1555 evas_map_point_image_uv_set(map, 2, w2, h);
1556 evas_map_point_image_uv_set(map, 3, 0, h);
1557 evas_map_point_coord_set(map, 0, x, y, 0);
1558 evas_map_point_coord_set(map, 1, x + w2, y, 0);
1559 evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1560 evas_map_point_coord_set(map, 3, x, h2, 0);
1561 break;
1562 case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1563 w2 = (w * progress);
1564 h2 = (y + h);
1565 evas_map_point_image_uv_set(map, 0, w2, 0);
1566 evas_map_point_image_uv_set(map, 1, w, 0);
1567 evas_map_point_image_uv_set(map, 2, w, h);
1568 evas_map_point_image_uv_set(map, 3, w2, h);
1569 evas_map_point_coord_set(map, 0, x + w2, y, 0);
1570 evas_map_point_coord_set(map, 1, x + w, y, 0);
1571 evas_map_point_coord_set(map, 2, x + w, h2, 0);
1572 evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1573 break;
1574 case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1575 w2 = (x + w);
1576 h2 = h - (h * progress);
1577 evas_map_point_image_uv_set(map, 0, 0, 0);
1578 evas_map_point_image_uv_set(map, 1, w, 0);
1579 evas_map_point_image_uv_set(map, 2, w, h2);
1580 evas_map_point_image_uv_set(map, 3, 0, h2);
1581 evas_map_point_coord_set(map, 0, x, y, 0);
1582 evas_map_point_coord_set(map, 1, w2, y, 0);
1583 evas_map_point_coord_set(map, 2, w2, y+h2, 0);
1584 evas_map_point_coord_set(map, 3, x, y+h2, 0);
1585 break;
1586 case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1587 w2 = (x + w);
1588 h2 = (h * progress);
1589 evas_map_point_image_uv_set(map, 0, 0, h2);
1590 evas_map_point_image_uv_set(map, 1, w, h2);
1591 evas_map_point_image_uv_set(map, 2, w, h);
1592 evas_map_point_image_uv_set(map, 3, 0, h);
1593 evas_map_point_coord_set(map, 0, x, y + h2, 0);
1594 evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1595 evas_map_point_coord_set(map, 2, w2, y + h, 0);
1596 evas_map_point_coord_set(map, 3, x, y + h, 0);
1597 break;
1598 default:
1599 break;
1600 }
1601 evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1602}
1603
1604static void
1605_elm_fx_wipe_show(Evas_Map *map, Elm_Transit_Effect_Wipe_Dir dir, float x, float y, float w, float h, float progress)
1606{
1607 float w2, h2;
1608
1609 switch (dir)
1610 {
1611 case ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT:
1612 w2 = (w - (w * progress));
1613 h2 = (y + h);
1614 evas_map_point_image_uv_set(map, 0, w2, 0);
1615 evas_map_point_image_uv_set(map, 1, w, 0);
1616 evas_map_point_image_uv_set(map, 2, w, h);
1617 evas_map_point_image_uv_set(map, 3, w2, h);
1618 evas_map_point_coord_set(map, 0, x + w2, y, 0);
1619 evas_map_point_coord_set(map, 1, w, y, 0);
1620 evas_map_point_coord_set(map, 2, w, h2, 0);
1621 evas_map_point_coord_set(map, 3, x + w2, h2, 0);
1622 break;
1623 case ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT:
1624 w2 = (w * progress);
1625 h2 = (y + h);
1626 evas_map_point_image_uv_set(map, 0, 0, 0);
1627 evas_map_point_image_uv_set(map, 1, w2, 0);
1628 evas_map_point_image_uv_set(map, 2, w2, h);
1629 evas_map_point_image_uv_set(map, 3, 0, h);
1630 evas_map_point_coord_set(map, 0, x, y, 0);
1631 evas_map_point_coord_set(map, 1, x + w2, y, 0);
1632 evas_map_point_coord_set(map, 2, x + w2, h2, 0);
1633 evas_map_point_coord_set(map, 3, x, h2, 0);
1634 break;
1635 case ELM_TRANSIT_EFFECT_WIPE_DIR_UP:
1636 w2 = (x + w);
1637 h2 = (h - (h * progress));
1638 evas_map_point_image_uv_set(map, 0, 0, h2);
1639 evas_map_point_image_uv_set(map, 1, w, h2);
1640 evas_map_point_image_uv_set(map, 2, w, h);
1641 evas_map_point_image_uv_set(map, 3, 0, h);
1642 evas_map_point_coord_set(map, 0, x, y + h2, 0);
1643 evas_map_point_coord_set(map, 1, w2, y + h2, 0);
1644 evas_map_point_coord_set(map, 2, w2, y + h, 0);
1645 evas_map_point_coord_set(map, 3, x, y + h, 0);
1646 break;
1647 case ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN:
1648 w2 = (x + w);
1649 h2 = (h * progress);
1650 evas_map_point_image_uv_set(map, 0, 0, 0);
1651 evas_map_point_image_uv_set(map, 1, w, 0);
1652 evas_map_point_image_uv_set(map, 2, w, h2);
1653 evas_map_point_image_uv_set(map, 3, 0, h2);
1654 evas_map_point_coord_set(map, 0, x, y, 0);
1655 evas_map_point_coord_set(map, 1, w2, y, 0);
1656 evas_map_point_coord_set(map, 2, w2, y + h2, 0);
1657 evas_map_point_coord_set(map, 3, x, y + h2, 0);
1658 break;
1659 default:
1660 break;
1661 }
1662 evas_map_util_3d_perspective(map, x + (w / 2), y + (h / 2), 0, _TRANSIT_FOCAL);
1663}
1664
1665static void
1666_transit_effect_wipe_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit)
1667{
1668 EINA_SAFETY_ON_NULL_RETURN(effect);
1669 EINA_SAFETY_ON_NULL_RETURN(transit);
1670 Eina_List *elist;
1671 Evas_Object *obj;
1672 Elm_Transit_Effect_Wipe *wipe = effect;
1673 Eina_Bool reverse = elm_transit_auto_reverse_get(transit);
1674
1675 EINA_LIST_FOREACH(transit->objs, elist, obj)
1676 {
1677 if ((wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW && !reverse)
1678 || (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE && reverse))
1679 evas_object_show(obj);
1680 else evas_object_hide(obj);
1681 evas_object_map_enable_set(obj, EINA_FALSE);
1682 }
1683
1684 free(wipe);
1685}
1686
1687static void
1688_transit_effect_wipe_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1689{
1690 EINA_SAFETY_ON_NULL_RETURN(effect);
1691 EINA_SAFETY_ON_NULL_RETURN(transit);
1692 Elm_Transit_Effect_Wipe *wipe = effect;
1693 Evas_Map *map;
1694 Evas_Coord _x, _y, _w, _h;
1695 Eina_List *elist;
1696 Evas_Object *obj;
1697 const char *type;
1698
1699 map = evas_map_new(4);
1700 if (!map) return;
1701
1702 EINA_LIST_FOREACH(transit->objs, elist, obj)
1703 {
1704 type = evas_object_type_get(obj);
1705 if ((!type) || (strcmp(type, "image")))
1706 evas_object_geometry_get(obj, &_x, &_y, &_w, &_h);
1707 else
1708 {
1709 evas_object_image_size_get(obj, &_w, &_h);
1710 _x = 0;
1711 _y = 0;
1712 }
1713 if (wipe->type == ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW)
1714 _elm_fx_wipe_show(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1715 else
1716 _elm_fx_wipe_hide(map, wipe->dir, _x, _y, _w, _h, (float)progress);
1717
1718 evas_object_map_enable_set(obj, EINA_TRUE);
1719 evas_object_map_set(obj, map);
1720 }
1721 evas_map_free(map);
1722}
1723
1724static Elm_Transit_Effect *
1725_transit_effect_wipe_context_new(Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1726{
1727 Elm_Transit_Effect_Wipe *wipe;
1728
1729 wipe = ELM_NEW(Elm_Transit_Effect_Wipe);
1730 if (!wipe) return NULL;
1731
1732 wipe->type = type;
1733 wipe->dir = dir;
1734
1735 return wipe;
1736}
1737
1738EAPI void *
1739elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir)
1740{
1741 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1742 void *effect = _transit_effect_wipe_context_new(type, dir);
1743
1744 if (!effect)
1745 {
1746 ERR("Failed to allocate wipe effect! : transit=%p", transit);
1747 return NULL;
1748 }
1749 elm_transit_effect_add(transit,
1750 _transit_effect_wipe_op, effect,
1751 _transit_effect_wipe_context_free);
1752 return effect;
1753}
1754
1755///////////////////////////////////////////////////////////////////////////
1756//Color Effect
1757///////////////////////////////////////////////////////////////////////////
1758typedef struct _Elm_Transit_Effect_Color Elm_Transit_Effect_Color;
1759
1760struct _Elm_Transit_Effect_Color
1761{
1762 struct _unsigned_color {
1763 unsigned int r, g, b, a;
1764 } from;
1765 struct _signed_color {
1766 int r, g, b, a;
1767 } to;
1768};
1769
1770static void
1771_transit_effect_color_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1772{
1773 Elm_Transit_Effect_Color *color = effect;
1774 free(color);
1775}
1776
1777static void
1778_transit_effect_color_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
1779{
1780 EINA_SAFETY_ON_NULL_RETURN(effect);
1781 EINA_SAFETY_ON_NULL_RETURN(transit);
1782 Elm_Transit_Effect_Color *color = effect;
1783 Evas_Object *obj;
1784 Eina_List *elist;
1785 unsigned int r, g, b, a;
1786
1787 r = (color->from.r + (int)((float)color->to.r * progress));
1788 g = (color->from.g + (int)((float)color->to.g * progress));
1789 b = (color->from.b + (int)((float)color->to.b * progress));
1790 a = (color->from.a + (int)((float)color->to.a * progress));
1791
1792 EINA_LIST_FOREACH(transit->objs, elist, obj)
1793 evas_object_color_set(obj, r, g, b, a);
1794}
1795
1796static Elm_Transit_Effect *
1797_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)
1798{
1799 Elm_Transit_Effect_Color *color;
1800
1801 color = ELM_NEW(Elm_Transit_Effect_Color);
1802 if (!color) return NULL;
1803
1804 color->from.r = from_r;
1805 color->from.g = from_g;
1806 color->from.b = from_b;
1807 color->from.a = from_a;
1808 color->to.r = to_r - from_r;
1809 color->to.g = to_g - from_g;
1810 color->to.b = to_b - from_b;
1811 color->to.a = to_a - from_a;
1812
1813 return color;
1814}
1815
1816EAPI Elm_Transit_Effect *
1817elm_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)
1818{
1819 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
1820 Elm_Transit_Effect *effect = _transit_effect_color_context_new(from_r, from_g, from_b, from_a, to_r, to_g, to_b, to_a);
1821
1822 if (!effect)
1823 {
1824 ERR("Failed to allocate color effect! : transit=%p", transit);
1825 return NULL;
1826 }
1827 elm_transit_effect_add(transit,
1828 _transit_effect_color_op, effect,
1829 _transit_effect_color_context_free);
1830 return effect;
1831}
1832
1833///////////////////////////////////////////////////////////////////////////
1834//Fade Effect
1835///////////////////////////////////////////////////////////////////////////
1836typedef struct _Elm_Transit_Effect_Fade Elm_Transit_Effect_Fade;
1837typedef struct _Elm_Transit_Effect_Fade_Node Elm_Transit_Effect_Fade_Node;
1838
1839struct _Elm_Transit_Effect_Fade_Node
1840{
1841 Evas_Object *before;
1842 Evas_Object *after;
1843 struct _signed_color before_color, after_color;
1844 int before_alpha;
1845 int after_alpha;
1846 Eina_Bool inversed : 1;
1847};
1848
1849struct _Elm_Transit_Effect_Fade
1850{
1851 Eina_List *nodes;
1852};
1853
1854static void
1855_fade_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1856{
1857 Elm_Transit_Effect_Fade *fade = data;
1858 Eina_List *elist;
1859 Elm_Transit_Effect_Fade_Node *fade_node;
1860
1861 EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
1862 {
1863 if (fade_node->before == obj)
1864 evas_object_event_callback_del(fade_node->after,
1865 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1866 else if (fade_node->after == obj)
1867 evas_object_event_callback_del(fade_node->before,
1868 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1869 else continue;
1870
1871 fade->nodes = eina_list_remove_list(fade->nodes, elist);
1872 free(fade_node);
1873 break;
1874 }
1875}
1876
1877static Eina_List *
1878_fade_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Fade *fade_data)
1879{
1880 Elm_Transit_Effect_Fade_Node *fade;
1881 Eina_List *data_list = NULL;
1882 int i, count;
1883
1884 count = eina_list_count(transit->objs);
1885 for (i = 0; i < count; i += 2)
1886 {
1887 fade = ELM_NEW(Elm_Transit_Effect_Fade_Node);
1888 if (!fade)
1889 {
1890 eina_list_free(data_list);
1891 return NULL;
1892 }
1893
1894 fade->before = eina_list_nth(transit->objs, i);
1895 fade->after = eina_list_nth(transit->objs, i+1);
1896
1897 evas_object_color_get(fade->before,
1898 &fade->before_color.r, &fade->before_color.g,
1899 &fade->before_color.b, &fade->before_color.a);
1900 evas_object_color_get(fade->after,
1901 &fade->after_color.r, &fade->after_color.g,
1902 &fade->after_color.b, &fade->after_color.a);
1903
1904 fade->before_alpha = (255 - fade->before_color.a);
1905 fade->after_alpha = (255 - fade->after_color.a);
1906
1907 data_list = eina_list_append(data_list, fade);
1908
1909 evas_object_event_callback_add(fade->before,
1910 EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
1911 evas_object_event_callback_add(fade->after,
1912 EVAS_CALLBACK_DEL, _fade_object_del_cb, fade_data);
1913 }
1914 return data_list;
1915}
1916
1917static void
1918_transit_effect_fade_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
1919{
1920 EINA_SAFETY_ON_NULL_RETURN(effect);
1921 Elm_Transit_Effect_Fade *fade = effect;
1922 Elm_Transit_Effect_Fade_Node *fade_node;
1923 Eina_List *elist, *elist_next;
1924
1925 EINA_LIST_FOREACH_SAFE(fade->nodes, elist, elist_next, fade_node)
1926 {
1927 evas_object_color_set(fade_node->before, fade_node->before_color.r,
1928 fade_node->before_color.g,
1929 fade_node->before_color.b,
1930 fade_node->before_color.a);
1931 evas_object_color_set(fade_node->after, fade_node->after_color.r,
1932 fade_node->after_color.g,
1933 fade_node->after_color.b,
1934 fade_node->after_color.a);
1935
1936 fade->nodes = eina_list_remove_list(fade->nodes, elist);
1937 evas_object_event_callback_del(fade_node->before,
1938 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1939 evas_object_event_callback_del(fade_node->after,
1940 EVAS_CALLBACK_DEL, _fade_object_del_cb);
1941 free(fade_node);
1942 }
1943
1944 free(fade);
1945}
1946
1947static void
1948_transit_effect_fade_op(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__, double progress)
1949{
1950 EINA_SAFETY_ON_NULL_RETURN(effect);
1951 Elm_Transit_Effect_Fade *fade = effect;
1952 Eina_List *elist;
1953 Elm_Transit_Effect_Fade_Node *fade_node;
1954 float _progress;
1955
1956 if (!fade->nodes)
1957 fade->nodes = _fade_nodes_build(transit, fade);
1958
1959 EINA_LIST_FOREACH(fade->nodes, elist, fade_node)
1960 {
1961 if (progress < 0.5)
1962 {
1963 if (!fade_node->inversed)
1964 {
1965 evas_object_hide(fade_node->after);
1966 evas_object_show(fade_node->before);
1967 fade_node->inversed = EINA_TRUE;
1968 }
1969
1970 _progress = (1 - (progress * 2));
1971
1972 evas_object_color_set(fade_node->before,
1973 fade_node->before_color.r * _progress,
1974 fade_node->before_color.g * _progress,
1975 fade_node->before_color.b * _progress,
1976 fade_node->before_color.a +
1977 fade_node->before_alpha * (1 - _progress));
1978 }
1979 else
1980 {
1981 if (fade_node->inversed)
1982 {
1983 evas_object_hide(fade_node->before);
1984 evas_object_show(fade_node->after);
1985 fade_node->inversed = EINA_FALSE;
1986 }
1987
1988 _progress = ((progress - 0.5) * 2);
1989
1990 evas_object_color_set(fade_node->after,
1991 fade_node->after_color.r * _progress,
1992 fade_node->after_color.g * _progress,
1993 fade_node->after_color.b * _progress,
1994 fade_node->after_color.a +
1995 fade_node->after_alpha * (1 - _progress));
1996 }
1997 }
1998}
1999
2000static Elm_Transit_Effect *
2001_transit_effect_fade_context_new(void)
2002{
2003 Elm_Transit_Effect_Fade *fade;
2004 fade = ELM_NEW(Elm_Transit_Effect_Fade);
2005 if (!fade) return NULL;
2006 return fade;
2007}
2008
2009EAPI Elm_Transit_Effect *
2010elm_transit_effect_fade_add(Elm_Transit *transit)
2011{
2012 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2013
2014 Elm_Transit_Effect *effect = _transit_effect_fade_context_new();
2015
2016 if (!effect)
2017 {
2018 ERR("Failed to allocate fade effect! : transit=%p", transit);
2019 return NULL;
2020 }
2021 elm_transit_effect_add(transit,
2022 _transit_effect_fade_op, effect,
2023 _transit_effect_fade_context_free);
2024 return effect;
2025}
2026
2027///////////////////////////////////////////////////////////////////////////
2028//Blend Effect
2029///////////////////////////////////////////////////////////////////////////
2030typedef struct _Elm_Transit_Effect_Blend Elm_Transit_Effect_Blend;
2031typedef struct _Elm_Transit_Effect_Blend_Node Elm_Transit_Effect_Blend_Node;
2032
2033struct _Elm_Transit_Effect_Blend_Node
2034{
2035 Evas_Object *before;
2036 Evas_Object *after;
2037 struct _signed_color from, to;
2038};
2039
2040struct _Elm_Transit_Effect_Blend
2041{
2042 Eina_List *nodes;
2043};
2044
2045static void
2046_blend_object_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
2047{
2048 Elm_Transit_Effect_Blend *blend = data;
2049 Eina_List *elist;
2050 Elm_Transit_Effect_Blend_Node *blend_node;
2051
2052 EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2053 {
2054 if (blend_node->after == obj)
2055 evas_object_event_callback_del(blend_node->before,
2056 EVAS_CALLBACK_DEL, _blend_object_del_cb);
2057 else if (blend_node->before == obj)
2058 evas_object_event_callback_del(blend_node->after,
2059 EVAS_CALLBACK_DEL, _blend_object_del_cb);
2060 else continue;
2061
2062 blend->nodes = eina_list_remove_list(blend->nodes, elist);
2063 free(blend_node);
2064 break;
2065 }
2066}
2067
2068static Eina_List *
2069_blend_nodes_build(Elm_Transit *transit, Elm_Transit_Effect_Blend *blend)
2070{
2071 Elm_Transit_Effect_Blend_Node *blend_node;
2072 Eina_List *data_list = NULL;
2073 int i, count;
2074
2075 count = eina_list_count(transit->objs);
2076 for (i = 0; i < (count - 1); i += 2)
2077 {
2078 blend_node = ELM_NEW(Elm_Transit_Effect_Blend_Node);
2079 if (!blend_node)
2080 {
2081 eina_list_free(data_list);
2082 return NULL;
2083 }
2084
2085 blend_node->before = eina_list_nth(transit->objs, i);
2086 blend_node->after = eina_list_nth(transit->objs, i + 1);
2087 evas_object_show(blend_node->before);
2088 evas_object_show(blend_node->after);
2089
2090 evas_object_color_get(blend_node->before, &blend_node->from.r,
2091 &blend_node->from.g, &blend_node->from.b,
2092 &blend_node->from.a);
2093 evas_object_color_get(blend_node->after, &blend_node->to.r,
2094 &blend_node->to.g, &blend_node->to.b,
2095 &blend_node->to.a);
2096
2097 data_list = eina_list_append(data_list, blend_node);
2098
2099 evas_object_event_callback_add(blend_node->before,
2100 EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2101 evas_object_event_callback_add(blend_node->after,
2102 EVAS_CALLBACK_DEL, _blend_object_del_cb, blend);
2103 }
2104 return data_list;
2105}
2106
2107void
2108_transit_effect_blend_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2109{
2110 EINA_SAFETY_ON_NULL_RETURN(effect);
2111 Elm_Transit_Effect_Blend *blend = effect;
2112 Elm_Transit_Effect_Blend_Node *blend_node;
2113 Eina_List *elist, *elist_next;
2114
2115 EINA_LIST_FOREACH_SAFE(blend->nodes, elist, elist_next, blend_node)
2116 {
2117 evas_object_color_set(blend_node->before,
2118 blend_node->from.r, blend_node->from.g,
2119 blend_node->from.b, blend_node->from.a);
2120 evas_object_color_set(blend_node->after, blend_node->to.r,
2121 blend_node->to.g, blend_node->to.b,
2122 blend_node->to.a);
2123
2124 if (elm_transit_auto_reverse_get(transit))
2125 evas_object_hide(blend_node->after);
2126 else
2127 evas_object_hide(blend_node->before);
2128
2129 blend->nodes = eina_list_remove_list(blend->nodes, elist);
2130
2131 evas_object_event_callback_del(blend_node->before,
2132 EVAS_CALLBACK_DEL, _blend_object_del_cb);
2133 evas_object_event_callback_del(blend_node->after,
2134 EVAS_CALLBACK_DEL, _blend_object_del_cb);
2135 free(blend_node);
2136 }
2137 free(blend);
2138}
2139
2140void
2141_transit_effect_blend_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2142{
2143 EINA_SAFETY_ON_NULL_RETURN(effect);
2144 EINA_SAFETY_ON_NULL_RETURN(transit);
2145 Elm_Transit_Effect_Blend *blend = effect;
2146 Elm_Transit_Effect_Blend_Node *blend_node;
2147 Eina_List *elist;
2148
2149 if (!blend->nodes) blend->nodes = _blend_nodes_build(transit, blend);
2150
2151 EINA_LIST_FOREACH(blend->nodes, elist, blend_node)
2152 {
2153 evas_object_color_set(blend_node->before,
2154 (int)(blend_node->from.r * (1 - progress)),
2155 (int)(blend_node->from.g * (1 - progress)),
2156 (int)(blend_node->from.b * (1 - progress)),
2157 (int)(blend_node->from.a * (1 - progress)));
2158 evas_object_color_set(blend_node->after,
2159 (int)(blend_node->to.r * progress),
2160 (int)(blend_node->to.g * progress),
2161 (int)(blend_node->to.b * progress),
2162 (int)(blend_node->to.a * progress));
2163 }
2164}
2165
2166static Elm_Transit_Effect *
2167_transit_effect_blend_context_new(void)
2168{
2169 Elm_Transit_Effect_Blend *blend;
2170
2171 blend = ELM_NEW(Elm_Transit_Effect_Blend);
2172 if (!blend) return NULL;
2173 return blend;
2174}
2175
2176EAPI Elm_Transit_Effect *
2177elm_transit_effect_blend_add(Elm_Transit *transit)
2178{
2179 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2180 Elm_Transit_Effect *effect = _transit_effect_blend_context_new();
2181
2182 if (!effect)
2183 {
2184 ERR("Failed to allocate blend effect! : transit=%p", transit);
2185 return NULL;
2186 }
2187 elm_transit_effect_add(transit,
2188 _transit_effect_blend_op, effect,
2189 _transit_effect_blend_context_free);
2190 return effect;
2191}
2192
2193///////////////////////////////////////////////////////////////////////////
2194//Rotation Effect
2195///////////////////////////////////////////////////////////////////////////
2196typedef struct _Elm_Transit_Effect_Rotation Elm_Transit_Effect_Rotation;
2197
2198struct _Elm_Transit_Effect_Rotation
2199{
2200 float from, to;
2201};
2202
2203static void
2204_transit_effect_rotation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2205{
2206 Elm_Transit_Effect_Rotation *rotation = effect;
2207 free(rotation);
2208}
2209
2210static void
2211_transit_effect_rotation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2212{
2213 EINA_SAFETY_ON_NULL_RETURN(effect);
2214 EINA_SAFETY_ON_NULL_RETURN(transit);
2215 Elm_Transit_Effect_Rotation *rotation = effect;
2216 Evas_Map *map;
2217 Evas_Coord x, y, w, h;
2218 float degree;
2219 float half_w, half_h;
2220 Eina_List *elist;
2221 Evas_Object *obj;
2222
2223 map = evas_map_new(4);
2224 if (!map) return;
2225
2226 EINA_LIST_FOREACH(transit->objs, elist, obj)
2227 {
2228 evas_map_util_points_populate_from_object_full(map, obj, 0);
2229 degree = rotation->from + (float)(progress * rotation->to);
2230
2231 evas_object_geometry_get(obj, &x, &y, &w, &h);
2232
2233 half_w = (float)w * 0.5;
2234 half_h = (float)h * 0.5;
2235
2236 evas_map_util_rotate(map, degree, x + half_w, y + half_h);
2237 evas_map_util_3d_perspective(map, x + half_w, y + half_h, 0, _TRANSIT_FOCAL);
2238 evas_object_map_enable_set(obj, EINA_TRUE);
2239 evas_object_map_set(obj, map);
2240 }
2241 evas_map_free(map);
2242}
2243
2244static Elm_Transit_Effect *
2245_transit_effect_rotation_context_new(float from_degree, float to_degree)
2246{
2247 Elm_Transit_Effect_Rotation *rotation;
2248
2249 rotation = ELM_NEW(Elm_Transit_Effect_Rotation);
2250 if (!rotation) return NULL;
2251
2252 rotation->from = from_degree;
2253 rotation->to = to_degree - from_degree;
2254
2255 return rotation;
2256}
2257
2258EAPI Elm_Transit_Effect *
2259elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree)
2260{
2261 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2262 Elm_Transit_Effect *effect = _transit_effect_rotation_context_new(from_degree, to_degree);
2263
2264 if (!effect)
2265 {
2266 ERR("Failed to allocate rotation effect! : transit=%p", transit);
2267 return NULL;
2268 }
2269 elm_transit_effect_add(transit,
2270 _transit_effect_rotation_op, effect,
2271 _transit_effect_rotation_context_free);
2272 return effect;
2273}
2274
2275///////////////////////////////////////////////////////////////////////////
2276//ImageAnimation Effect
2277///////////////////////////////////////////////////////////////////////////
2278typedef struct _Elm_Transit_Effect_Image_Animation Elm_Transit_Effect_Image_Animation;
2279
2280struct _Elm_Transit_Effect_Image_Animation
2281{
2282 Eina_List *images;
2283};
2284
2285static void
2286_transit_effect_image_animation_context_free(Elm_Transit_Effect *effect, Elm_Transit *transit __UNUSED__)
2287{
2288 EINA_SAFETY_ON_NULL_RETURN(effect);
2289 Elm_Transit_Effect_Image_Animation *image_animation = effect;
2290 const char *image;
2291 Eina_List *elist, *elist_next;
2292
2293 EINA_LIST_FOREACH_SAFE(image_animation->images, elist, elist_next, image)
2294 {
2295 image_animation->images =
2296 eina_list_remove_list(image_animation->images, elist);
2297 eina_stringshare_del(image);
2298 }
2299
2300 free(image_animation);
2301}
2302
2303static void
2304_transit_effect_image_animation_op(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress)
2305{
2306 EINA_SAFETY_ON_NULL_RETURN(effect);
2307 EINA_SAFETY_ON_NULL_RETURN(transit);
2308 Eina_List *elist;
2309 Evas_Object *obj;
2310 const char *type;
2311 Elm_Transit_Effect_Image_Animation *image_animation = effect;
2312 unsigned int count = 0;
2313 int len;
2314
2315 type = eina_stringshare_add("icon");
2316 len = eina_list_count(image_animation->images);
2317
2318 if (!len) count = floor(progress * len);
2319 else count = floor(progress * (len - 1));
2320
2321 EINA_LIST_FOREACH(transit->objs, elist, obj)
2322 {
2323 if (elm_widget_type_check(obj, type, __func__))
2324 elm_icon_file_set(obj,
2325 eina_list_nth(image_animation->images, count), NULL);
2326 }
2327
2328 eina_stringshare_del(type);
2329}
2330
2331static Elm_Transit_Effect *
2332_transit_effect_image_animation_context_new(Eina_List *images)
2333{
2334 Elm_Transit_Effect_Image_Animation *image_animation;
2335 image_animation = ELM_NEW(Elm_Transit_Effect_Image_Animation);
2336
2337 if (!image_animation) return NULL;
2338 image_animation->images = images;
2339 return image_animation;
2340}
2341
2342EAPI Elm_Transit_Effect *
2343elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images)
2344{
2345 ELM_TRANSIT_CHECK_OR_RETURN(transit, NULL);
2346 Elm_Transit_Effect *effect = _transit_effect_image_animation_context_new(images);
2347
2348 if (!effect)
2349 {
2350 ERR("Failed to allocate image_animation effect! : transit=%p", transit);
2351 return NULL;
2352 }
2353 elm_transit_effect_add(transit,
2354 _transit_effect_image_animation_op, effect,
2355 _transit_effect_image_animation_context_free);
2356 return effect;
2357}
diff --git a/libraries/elementary/src/lib/elm_transit.h b/libraries/elementary/src/lib/elm_transit.h
new file mode 100644
index 0000000..a167e9d
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_transit.h
@@ -0,0 +1,824 @@
1/**
2 * @defgroup Transit Transit
3 * @ingroup Elementary
4 *
5 * Transit is designed to apply various animated transition effects to @c
6 * Evas_Object, such like translation, rotation, etc. For using these
7 * effects, create an @ref Elm_Transit and add the desired transition effects.
8 *
9 * Once the effects are added into transit, they will be automatically
10 * managed (their callback will be called for the set duration and
11 * they will be deleted upon completion).
12 *
13 * Example:
14 * @code
15 * Elm_Transit *trans = elm_transit_add();
16 * elm_transit_object_add(trans, obj);
17 * elm_transit_effect_translation_add(trans, 0, 0, 280, 280
18 * elm_transit_duration_set(transit, 1);
19 * elm_transit_auto_reverse_set(transit, EINA_TRUE);
20 * elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_DECELERATE);
21 * elm_transit_repeat_times_set(transit, 3);
22 * @endcode
23 *
24 * Some transition effects are used to change the properties of objects. They
25 * are:
26 * @li @ref elm_transit_effect_translation_add
27 * @li @ref elm_transit_effect_color_add
28 * @li @ref elm_transit_effect_rotation_add
29 * @li @ref elm_transit_effect_wipe_add
30 * @li @ref elm_transit_effect_zoom_add
31 * @li @ref elm_transit_effect_resizing_add
32 *
33 * Other transition effects are used to make one object disappear and another
34 * object appear on its place. These effects are:
35 *
36 * @li @ref elm_transit_effect_flip_add
37 * @li @ref elm_transit_effect_resizable_flip_add
38 * @li @ref elm_transit_effect_fade_add
39 * @li @ref elm_transit_effect_blend_add
40 *
41 * It's also possible to make a transition chain with @ref
42 * elm_transit_chain_transit_add.
43 *
44 * @warning We strongly recommend to use elm_transit just when edje can not do
45 * the trick. Edje is better at handling transitions than Elm_Transit.
46 * Edje has more flexibility and animations can be manipulated inside the theme.
47 *
48 * List of examples:
49 * @li @ref transit_example_01_explained
50 * @li @ref transit_example_02_explained
51 * @li @ref transit_example_03_c
52 * @li @ref transit_example_04_c
53 *
54 * @{
55 */
56
57/**
58 * @enum Elm_Transit_Tween_Mode
59 *
60 * The type of acceleration used in the transition.
61 */
62typedef enum
63{
64 ELM_TRANSIT_TWEEN_MODE_LINEAR, /**< Constant speed */
65 ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL, /**< Starts slow, increase speed
66 over time, then decrease again
67 and stop slowly */
68 ELM_TRANSIT_TWEEN_MODE_DECELERATE, /**< Starts fast and decrease
69 speed over time */
70 ELM_TRANSIT_TWEEN_MODE_ACCELERATE /**< Starts slow and increase speed
71 over time */
72} Elm_Transit_Tween_Mode;
73
74/**
75 * @enum Elm_Transit_Effect_Flip_Axis
76 *
77 * The axis along which flip effect should be applied.
78 */
79typedef enum
80{
81 ELM_TRANSIT_EFFECT_FLIP_AXIS_X, /**< Flip on X axis */
82 ELM_TRANSIT_EFFECT_FLIP_AXIS_Y /**< Flip on Y axis */
83} Elm_Transit_Effect_Flip_Axis;
84
85/**
86 * @enum Elm_Transit_Effect_Wipe_Dir
87 *
88 * The direction in which the wipe effect should occur.
89 */
90typedef enum
91{
92 ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT, /**< Wipe to the left */
93 ELM_TRANSIT_EFFECT_WIPE_DIR_RIGHT, /**< Wipe to the right */
94 ELM_TRANSIT_EFFECT_WIPE_DIR_UP, /**< Wipe up */
95 ELM_TRANSIT_EFFECT_WIPE_DIR_DOWN /**< Wipe down */
96} Elm_Transit_Effect_Wipe_Dir;
97
98/** @enum Elm_Transit_Effect_Wipe_Type
99 *
100 * Whether the wipe effect should show or hide the object.
101 */
102typedef enum
103{
104 ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, /**< Hide the object during the
105 animation */
106 ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW /**< Show the object during the
107 animation */
108} Elm_Transit_Effect_Wipe_Type;
109
110/**
111 * @typedef Elm_Transit
112 *
113 * The Transit created with elm_transit_add(). This type has the information
114 * about the objects which the transition will be applied, and the
115 * transition effects that will be used. It also contains info about
116 * duration, number of repetitions, auto-reverse, etc.
117 */
118typedef struct _Elm_Transit Elm_Transit;
119typedef void Elm_Transit_Effect;
120
121/**
122 * @typedef Elm_Transit_Effect_Transition_Cb
123 *
124 * Transition callback called for this effect on each transition iteration.
125 */
126typedef void (*Elm_Transit_Effect_Transition_Cb)(Elm_Transit_Effect *effect, Elm_Transit *transit, double progress);
127
128/**
129 * Elm_Transit_Effect_End_Cb
130 *
131 * Transition callback called for this effect when the transition is over.
132 */
133typedef void (*Elm_Transit_Effect_End_Cb)(Elm_Transit_Effect *effect, Elm_Transit *transit);
134
135/**
136 * Elm_Transit_Del_Cb
137 *
138 * A callback called when the transit is deleted.
139 */
140typedef void (*Elm_Transit_Del_Cb)(void *data, Elm_Transit *transit);
141
142/**
143 * Create new transit.
144 *
145 * @note It is not necessary to delete the transit object, it will be deleted at
146 * the end of its operation.
147 * @note The transit will start playing when the program enters the main loop.
148 *
149 * @return The transit object.
150 *
151 * @ingroup Transit
152 */
153EAPI Elm_Transit *elm_transit_add(void);
154
155/**
156 * Stops the animation and delete the @p transit object.
157 *
158 * Call this function if you want to stop the animation before the
159 * transit time. Make sure the @p transit object is still alive with
160 * elm_transit_del_cb_set() function.
161 * All added effects will be deleted, calling its respective data_free_cb
162 * functions. The function set by elm_transit_del_cb_set() will be called.
163 *
164 * @see elm_transit_del_cb_set()
165 *
166 * @param transit The transit object to be deleted.
167 *
168 * @ingroup Transit
169 */
170EAPI void elm_transit_del(Elm_Transit *transit);
171
172/**
173 * Add a new effect to the transit.
174 *
175 * @note The cb function and the data are the key to the effect.
176 * If you try to add an existing effect, nothing is done.
177 * @note After the first addition of an effect to @p transit, if its
178 * effect list become empty again, the @p transit will be killed by
179 * elm_transit_del(transit) function.
180 *
181 * Example:
182 * @code
183 * Elm_Transit *transit = elm_transit_add();
184 * elm_transit_effect_add(transit,
185 * elm_transit_effect_blend_op,
186 * elm_transit_effect_blend_context_new(),
187 * elm_transit_effect_blend_context_free);
188 * @endcode
189 *
190 * @param transit The transit object.
191 * @param transition_cb The operation function. It is called when the
192 * animation begins, it is the function that actually performs the animation.
193 * It is called with the @p data, @p transit and the time progression of the
194 * animation (a double value between 0.0 and 1.0).
195 * @param effect The context data of the effect.
196 * @param end_cb The function to free the context data, it will be called
197 * at the end of the effect, it must finalize the animation and free the
198 * @p data.
199 *
200 * @ingroup Transit
201 * @warning The transit will free the context data at the and of the
202 * transition with the data_free_cb function.
203 * Do not share the context data in between different transit objects.
204 */
205EAPI void elm_transit_effect_add(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect, Elm_Transit_Effect_End_Cb end_cb);
206
207/**
208 * Delete an added effect.
209 *
210 * This function will remove the effect from the @p transit, calling the
211 * data_free_cb to free the @p data.
212 *
213 * @see elm_transit_effect_add()
214 *
215 * @note If the effect is not found, nothing is done.
216 * @note If the effect list become empty, this function will call
217 * elm_transit_del(transit), i.e., it will kill the @p transit.
218 *
219 * @param transit The transit object.
220 * @param transition_cb The operation function.
221 * @param effect The context data of the effect.
222 *
223 * @ingroup Transit
224 */
225EAPI void elm_transit_effect_del(Elm_Transit *transit, Elm_Transit_Effect_Transition_Cb transition_cb, Elm_Transit_Effect *effect);
226
227/**
228 * Add new object to apply the effects.
229 *
230 * @note After the first addition of an object to @p transit, if its
231 * object list become empty again, the @p transit will be killed by
232 * elm_transit_del(transit) function.
233 * @note If the @p obj belongs to another transit, the @p obj will be
234 * removed from it and it will only belong to the other @p transit.
235 * If the old transit stays without objects, it will die.
236 * @note When you add an object into the @p transit, its state from
237 * evas_object_pass_events_get(obj) is saved, and it is applied when the
238 * transit ends, if you change this state with evas_object_pass_events_set()
239 * after add the object, this state will change again when @p transit stops.
240 *
241 * @param transit The transit object.
242 * @param obj Object to be animated.
243 *
244 * @ingroup Transit
245 * @warning It is not allowed to add a new object after transit begins.
246 */
247EAPI void elm_transit_object_add(Elm_Transit *transit, Evas_Object *obj);
248
249/**
250 * Removes an added object from the transit.
251 *
252 * @note If the @p obj is not in the @p transit, nothing is done.
253 * @note If the list become empty, this function will call
254 * elm_transit_del(transit), i.e., it will kill the @p transit.
255 *
256 * @param transit The transit object.
257 * @param obj Object to be removed from @p transit.
258 *
259 * @ingroup Transit
260 * @warning It is not allowed to remove objects after transit begins.
261 */
262EAPI void elm_transit_object_remove(Elm_Transit *transit, Evas_Object *obj);
263
264/**
265 * Get the objects of the transit.
266 *
267 * @param transit The transit object.
268 * @return a Eina_List with the objects from the transit.
269 *
270 * @ingroup Transit
271 */
272EAPI const Eina_List *elm_transit_objects_get(const Elm_Transit *transit);
273
274/**
275 * Enable/disable keeping up the objects states.
276 * If it is not kept, the objects states will be reset when transition ends.
277 *
278 * @note @p transit can not be NULL.
279 * @note One state includes geometry, color, map data.
280 *
281 * @param transit The transit object.
282 * @param state_keep retain the state or not.
283 *
284 * @ingroup Transit
285 */
286EAPI void elm_transit_objects_final_state_keep_set(Elm_Transit *transit, Eina_Bool state_keep);
287
288/**
289 * Get a value whether the objects states will be reset or not.
290 *
291 * @note @p transit can not be NULL
292 *
293 * @see elm_transit_objects_final_state_keep_set()
294 *
295 * @param transit The transit object.
296 * @return EINA_TRUE means the states of the objects will be reset.
297 * If @p transit is NULL, EINA_FALSE is returned
298 *
299 * @ingroup Transit
300 */
301EAPI Eina_Bool elm_transit_objects_final_state_keep_get(const Elm_Transit *transit);
302
303/**
304 * Set the event enabled when transit is operating.
305 *
306 * If @p enabled is EINA_TRUE, the objects of the transit will receive
307 * events from mouse and keyboard during the animation.
308 * @note When you add an object with elm_transit_object_add(), its state from
309 * evas_object_freeze_events_get(obj) is saved, and it is applied when the
310 * transit ends. If you change this state with evas_object_freeze_events_set()
311 * after adding the object, this state will change again when @p transit stops
312 * to run.
313 *
314 * @param transit The transit object.
315 * @param enabled Events are received when enabled is @c EINA_TRUE, and
316 * ignored otherwise.
317 *
318 * @ingroup Transit
319 */
320EAPI void elm_transit_event_enabled_set(Elm_Transit *transit, Eina_Bool enabled);
321
322/**
323 * Get the value of event enabled status.
324 *
325 * @see elm_transit_event_enabled_set()
326 *
327 * @param transit The Transit object
328 * @return EINA_TRUE, when event is enabled. If @p transit is NULL
329 * EINA_FALSE is returned
330 *
331 * @ingroup Transit
332 */
333EAPI Eina_Bool elm_transit_event_enabled_get(const Elm_Transit *transit);
334
335/**
336 * Set the user-callback function when the transit is deleted.
337 *
338 * @note Using this function twice will overwrite the first function set.
339 * @note the @p transit object will be deleted after call @p cb function.
340 *
341 * @param transit The transit object.
342 * @param cb Callback function pointer. This function will be called before
343 * the deletion of the transit.
344 * @param data Callback function user data. It is the @p op parameter.
345 *
346 * @ingroup Transit
347 */
348EAPI void elm_transit_del_cb_set(Elm_Transit *transit, Elm_Transit_Del_Cb cb, void *data);
349
350/**
351 * Set reverse effect automatically.
352 *
353 * If auto reverse is set, after running the effects with the progress
354 * parameter from 0 to 1, it will call the effects again with the progress
355 * from 1 to 0. The transit will last for a time equal to (2 * duration * repeat),
356 * where the duration was set with the function elm_transit_add and
357 * the repeat with the function elm_transit_repeat_times_set().
358 *
359 * @param transit The transit object.
360 * @param reverse EINA_TRUE means the auto_reverse is on.
361 *
362 * @ingroup Transit
363 */
364EAPI void elm_transit_auto_reverse_set(Elm_Transit *transit, Eina_Bool reverse);
365
366/**
367 * Get if the auto reverse is on.
368 *
369 * @see elm_transit_auto_reverse_set()
370 *
371 * @param transit The transit object.
372 * @return EINA_TRUE means auto reverse is on. If @p transit is NULL
373 * EINA_FALSE is returned
374 *
375 * @ingroup Transit
376 */
377EAPI Eina_Bool elm_transit_auto_reverse_get(const Elm_Transit *transit);
378
379/**
380 * Set the transit repeat count. Effect will be repeated by repeat count.
381 *
382 * This function sets the number of repetition the transit will run after
383 * the first one, i.e., if @p repeat is 1, the transit will run 2 times.
384 * If the @p repeat is a negative number, it will repeat infinite times.
385 *
386 * @note If this function is called during the transit execution, the transit
387 * will run @p repeat times, ignoring the times it already performed.
388 *
389 * @param transit The transit object
390 * @param repeat Repeat count
391 *
392 * @ingroup Transit
393 */
394EAPI void elm_transit_repeat_times_set(Elm_Transit *transit, int repeat);
395
396/**
397 * Get the transit repeat count.
398 *
399 * @see elm_transit_repeat_times_set()
400 *
401 * @param transit The Transit object.
402 * @return The repeat count. If @p transit is NULL
403 * 0 is returned
404 *
405 * @ingroup Transit
406 */
407EAPI int elm_transit_repeat_times_get(const Elm_Transit *transit);
408
409/**
410 * Set the transit animation acceleration type.
411 *
412 * This function sets the tween mode of the transit that can be:
413 * ELM_TRANSIT_TWEEN_MODE_LINEAR - The default mode.
414 * ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL - Starts in accelerate mode and ends decelerating.
415 * ELM_TRANSIT_TWEEN_MODE_DECELERATE - The animation will be slowed over time.
416 * ELM_TRANSIT_TWEEN_MODE_ACCELERATE - The animation will accelerate over time.
417 *
418 * @param transit The transit object.
419 * @param tween_mode The tween type.
420 *
421 * @ingroup Transit
422 */
423EAPI void elm_transit_tween_mode_set(Elm_Transit *transit, Elm_Transit_Tween_Mode tween_mode);
424
425/**
426 * Get the transit animation acceleration type.
427 *
428 * @note @p transit can not be NULL
429 *
430 * @param transit The transit object.
431 * @return The tween type. If @p transit is NULL
432 * ELM_TRANSIT_TWEEN_MODE_LINEAR is returned.
433 *
434 * @ingroup Transit
435 */
436EAPI Elm_Transit_Tween_Mode elm_transit_tween_mode_get(const Elm_Transit *transit);
437
438/**
439 * Set the transit animation time
440 *
441 * @note @p transit can not be NULL
442 *
443 * @param transit The transit object.
444 * @param duration The animation time.
445 *
446 * @ingroup Transit
447 */
448EAPI void elm_transit_duration_set(Elm_Transit *transit, double duration);
449
450/**
451 * Get the transit animation time
452 *
453 * @note @p transit can not be NULL
454 *
455 * @param transit The transit object.
456 *
457 * @return The transit animation time.
458 *
459 * @ingroup Transit
460 */
461EAPI double elm_transit_duration_get(const Elm_Transit *transit);
462
463/**
464 * Starts the transition.
465 * Once this API is called, the transit begins to measure the time.
466 *
467 * @note @p transit can not be NULL
468 *
469 * @param transit The transit object.
470 *
471 * @ingroup Transit
472 */
473EAPI void elm_transit_go(Elm_Transit *transit);
474
475/**
476 * Pause/Resume the transition.
477 *
478 * If you call elm_transit_go again, the transit will be started from the
479 * beginning, and will be played.
480 *
481 * @note @p transit can not be NULL
482 *
483 * @param transit The transit object.
484 * @param paused Whether the transition should be paused or not.
485 *
486 * @ingroup Transit
487 */
488EAPI void elm_transit_paused_set(Elm_Transit *transit, Eina_Bool paused);
489
490/**
491 * Get the value of paused status.
492 *
493 * @see elm_transit_paused_set()
494 *
495 * @note @p transit can not be NULL
496 *
497 * @param transit The transit object.
498 * @return EINA_TRUE means transition is paused. If @p transit is NULL
499 * EINA_FALSE is returned
500 *
501 * @ingroup Transit
502 */
503EAPI Eina_Bool elm_transit_paused_get(const Elm_Transit *transit);
504
505/**
506 * Get the time progression of the animation (a double value between 0.0 and 1.0).
507 *
508 * The value returned is a fraction (current time / total time). It
509 * represents the progression position relative to the total.
510 *
511 * @note @p transit can not be NULL
512 *
513 * @param transit The transit object.
514 *
515 * @return The time progression value. If @p transit is NULL
516 * 0 is returned
517 *
518 * @ingroup Transit
519 */
520EAPI double elm_transit_progress_value_get(const Elm_Transit *transit);
521
522/**
523 * Makes the chain relationship between two transits.
524 *
525 * @note @p transit can not be NULL. Transit would have multiple chain transits.
526 * @note @p chain_transit can not be NULL. Chain transits could be chained to the only one transit.
527 *
528 * @param transit The transit object.
529 * @param chain_transit The chain transit object. This transit will be operated
530 * after transit is done.
531 *
532 * This function adds @p chain_transit transition to a chain after the @p
533 * transit, and will be started as soon as @p transit ends. See @ref
534 * transit_example_02_explained for a full example.
535 *
536 * @ingroup Transit
537 */
538EAPI void elm_transit_chain_transit_add(Elm_Transit *transit, Elm_Transit *chain_transit);
539
540/**
541 * Cut off the chain relationship between two transits.
542 *
543 * @note @p transit can not be NULL. Transit would have the chain relationship with @p chain transit.
544 * @note @p chain_transit can not be NULL. Chain transits should be chained to the @p transit.
545 *
546 * @param transit The transit object.
547 * @param chain_transit The chain transit object.
548 *
549 * This function remove the @p chain_transit transition from the @p transit.
550 *
551 * @ingroup Transit
552 */
553EAPI void elm_transit_chain_transit_del(Elm_Transit *transit, Elm_Transit *chain_transit);
554
555/**
556 * Get the current chain transit list.
557 *
558 * @note @p transit can not be NULL.
559 *
560 * @param transit The transit object.
561 * @return chain transit list.
562 *
563 * @ingroup Transit
564 */
565EAPI Eina_List *elm_transit_chain_transits_get(const Elm_Transit *transit);
566
567/**
568 * Add the Resizing Effect to Elm_Transit.
569 *
570 * @note This API is one of the facades. It creates resizing effect context
571 * and add it's required APIs to elm_transit_effect_add.
572 *
573 * @see elm_transit_effect_add()
574 *
575 * @param transit Transit object.
576 * @param from_w Object width size when effect begins.
577 * @param from_h Object height size when effect begins.
578 * @param to_w Object width size when effect ends.
579 * @param to_h Object height size when effect ends.
580 * @return Resizing effect context data.
581 *
582 * @ingroup Transit
583 */
584EAPI Elm_Transit_Effect *elm_transit_effect_resizing_add(Elm_Transit *transit, Evas_Coord from_w, Evas_Coord from_h, Evas_Coord to_w, Evas_Coord to_h);
585
586/**
587 * Add the Translation Effect to Elm_Transit.
588 *
589 * @note This API is one of the facades. It creates translation effect context
590 * and add it's required APIs to elm_transit_effect_add.
591 *
592 * @see elm_transit_effect_add()
593 *
594 * @param transit Transit object.
595 * @param from_dx X Position variation when effect begins.
596 * @param from_dy Y Position variation when effect begins.
597 * @param to_dx X Position variation when effect ends.
598 * @param to_dy Y Position variation when effect ends.
599 * @return Translation effect context data.
600 *
601 * @ingroup Transit
602 * @warning It is highly recommended just create a transit with this effect when
603 * the window that the objects of the transit belongs has already been created.
604 * This is because this effect needs the geometry information about the objects,
605 * and if the window was not created yet, it can get a wrong information.
606 */
607EAPI Elm_Transit_Effect *elm_transit_effect_translation_add(Elm_Transit *transit, Evas_Coord from_dx, Evas_Coord from_dy, Evas_Coord to_dx, Evas_Coord to_dy);
608
609/**
610 * Add the Zoom Effect to Elm_Transit.
611 *
612 * @note This API is one of the facades. It creates zoom effect context
613 * and add it's required APIs to elm_transit_effect_add.
614 *
615 * @see elm_transit_effect_add()
616 *
617 * @param transit Transit object.
618 * @param from_rate Scale rate when effect begins (1 is current rate).
619 * @param to_rate Scale rate when effect ends.
620 * @return Zoom effect context data.
621 *
622 * @ingroup Transit
623 * @warning It is highly recommended just create a transit with this effect when
624 * the window that the objects of the transit belongs has already been created.
625 * This is because this effect needs the geometry information about the objects,
626 * and if the window was not created yet, it can get a wrong information.
627 */
628EAPI Elm_Transit_Effect *elm_transit_effect_zoom_add(Elm_Transit *transit, float from_rate, float to_rate);
629
630/**
631 * Add the Flip Effect to Elm_Transit.
632 *
633 * @note This API is one of the facades. It creates flip effect context
634 * and add it's required APIs to elm_transit_effect_add.
635 * @note This effect is applied to each pair of objects in the order they are listed
636 * in the transit list of objects. The first object in the pair will be the
637 * "front" object and the second will be the "back" object.
638 *
639 * @see elm_transit_effect_add()
640 *
641 * @param transit Transit object.
642 * @param axis Flipping Axis(X or Y).
643 * @param cw Flipping Direction. EINA_TRUE is clock-wise.
644 * @return Flip effect context data.
645 *
646 * @ingroup Transit
647 * @warning It is highly recommended just create a transit with this effect when
648 * the window that the objects of the transit belongs has already been created.
649 * This is because this effect needs the geometry information about the objects,
650 * and if the window was not created yet, it can get a wrong information.
651 */
652EAPI Elm_Transit_Effect *elm_transit_effect_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw);
653
654/**
655 * Add the Resizeable Flip Effect to Elm_Transit.
656 *
657 * @note This API is one of the facades. It creates resizable flip effect context
658 * and add it's required APIs to elm_transit_effect_add.
659 * @note This effect is applied to each pair of objects in the order they are listed
660 * in the transit list of objects. The first object in the pair will be the
661 * "front" object and the second will be the "back" object.
662 *
663 * @see elm_transit_effect_add()
664 *
665 * @param transit Transit object.
666 * @param axis Flipping Axis(X or Y).
667 * @param cw Flipping Direction. EINA_TRUE is clock-wise.
668 * @return Resizeable flip effect context data.
669 *
670 * @ingroup Transit
671 * @warning It is highly recommended just create a transit with this effect when
672 * the window that the objects of the transit belongs has already been created.
673 * This is because this effect needs the geometry information about the objects,
674 * and if the window was not created yet, it can get a wrong information.
675 */
676EAPI Elm_Transit_Effect *elm_transit_effect_resizable_flip_add(Elm_Transit *transit, Elm_Transit_Effect_Flip_Axis axis, Eina_Bool cw);
677
678/**
679 * Add the Wipe Effect to Elm_Transit.
680 *
681 * @note This API is one of the facades. It creates wipe effect context
682 * and add it's required APIs to elm_transit_effect_add.
683 *
684 * @see elm_transit_effect_add()
685 *
686 * @param transit Transit object.
687 * @param type Wipe type. Hide or show.
688 * @param dir Wipe Direction.
689 * @return Wipe effect context data.
690 *
691 * @ingroup Transit
692 * @warning It is highly recommended just create a transit with this effect when
693 * the window that the objects of the transit belongs has already been created.
694 * This is because this effect needs the geometry information about the objects,
695 * and if the window was not created yet, it can get a wrong information.
696 */
697EAPI Elm_Transit_Effect *elm_transit_effect_wipe_add(Elm_Transit *transit, Elm_Transit_Effect_Wipe_Type type, Elm_Transit_Effect_Wipe_Dir dir);
698
699/**
700 * Add the Color Effect to Elm_Transit.
701 *
702 * @note This API is one of the facades. It creates color effect context
703 * and add it's required APIs to elm_transit_effect_add.
704 *
705 * @see elm_transit_effect_add()
706 *
707 * @param transit Transit object.
708 * @param from_r RGB R when effect begins.
709 * @param from_g RGB G when effect begins.
710 * @param from_b RGB B when effect begins.
711 * @param from_a RGB A when effect begins.
712 * @param to_r RGB R when effect ends.
713 * @param to_g RGB G when effect ends.
714 * @param to_b RGB B when effect ends.
715 * @param to_a RGB A when effect ends.
716 * @return Color effect context data.
717 *
718 * @ingroup Transit
719 */
720EAPI Elm_Transit_Effect *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);
721
722/**
723 * Add the Fade Effect to Elm_Transit.
724 *
725 * @note This API is one of the facades. It creates fade effect context
726 * and add it's required APIs to elm_transit_effect_add.
727 * @note This effect is applied to each pair of objects in the order they are listed
728 * in the transit list of objects. The first object in the pair will be the
729 * "before" object and the second will be the "after" object.
730 *
731 * @see elm_transit_effect_add()
732 *
733 * @param transit Transit object.
734 * @return Fade effect context data.
735 *
736 * @ingroup Transit
737 * @warning It is highly recommended just create a transit with this effect when
738 * the window that the objects of the transit belongs has already been created.
739 * This is because this effect needs the color information about the objects,
740 * and if the window was not created yet, it can get a wrong information.
741 */
742EAPI Elm_Transit_Effect *elm_transit_effect_fade_add(Elm_Transit *transit);
743
744/**
745 * Add the Blend Effect to Elm_Transit.
746 *
747 * @note This API is one of the facades. It creates blend effect context
748 * and add it's required APIs to elm_transit_effect_add.
749 * @note This effect is applied to each pair of objects in the order they are listed
750 * in the transit list of objects. The first object in the pair will be the
751 * "before" object and the second will be the "after" object.
752 *
753 * @see elm_transit_effect_add()
754 *
755 * @param transit Transit object.
756 * @return Blend effect context data.
757 *
758 * @ingroup Transit
759 * @warning It is highly recommended just create a transit with this effect when
760 * the window that the objects of the transit belongs has already been created.
761 * This is because this effect needs the color information about the objects,
762 * and if the window was not created yet, it can get a wrong information.
763 */
764EAPI Elm_Transit_Effect *elm_transit_effect_blend_add(Elm_Transit *transit);
765
766/**
767 * Add the Rotation Effect to Elm_Transit.
768 *
769 * @note This API is one of the facades. It creates rotation effect context
770 * and add it's required APIs to elm_transit_effect_add.
771 *
772 * @see elm_transit_effect_add()
773 *
774 * @param transit Transit object.
775 * @param from_degree Degree when effect begins.
776 * @param to_degree Degree when effect is ends.
777 * @return Rotation effect context data.
778 *
779 * @ingroup Transit
780 * @warning It is highly recommended just create a transit with this effect when
781 * the window that the objects of the transit belongs has already been created.
782 * This is because this effect needs the geometry information about the objects,
783 * and if the window was not created yet, it can get a wrong information.
784 */
785EAPI Elm_Transit_Effect *elm_transit_effect_rotation_add(Elm_Transit *transit, float from_degree, float to_degree);
786
787/**
788 * Add the ImageAnimation Effect to Elm_Transit.
789 *
790 * @note This API is one of the facades. It creates image animation effect context
791 * and add it's required APIs to elm_transit_effect_add.
792 * The @p images parameter is a list images paths. This list and
793 * its contents will be deleted at the end of the effect by
794 * elm_transit_effect_image_animation_context_free() function.
795 *
796 * Example:
797 * @code
798 * char buf[PATH_MAX];
799 * Eina_List *images = NULL;
800 * Elm_Transit *transi = elm_transit_add();
801 *
802 * snprintf(buf, sizeof(buf), "%s/images/icon_11.png", PACKAGE_DATA_DIR);
803 * images = eina_list_append(images, eina_stringshare_add(buf));
804 *
805 * snprintf(buf, sizeof(buf), "%s/images/logo_small.png", PACKAGE_DATA_DIR);
806 * images = eina_list_append(images, eina_stringshare_add(buf));
807 * elm_transit_effect_image_animation_add(transi, images);
808 *
809 * @endcode
810 *
811 * @see elm_transit_effect_add()
812 *
813 * @param transit Transit object.
814 * @param images Eina_List of images file paths. This list and
815 * its contents will be deleted at the end of the effect by
816 * elm_transit_effect_image_animation_context_free() function.
817 * @return Image Animation effect context data.
818 *
819 * @ingroup Transit
820 */
821EAPI Elm_Transit_Effect *elm_transit_effect_image_animation_add(Elm_Transit *transit, Eina_List *images);
822/**
823 * @}
824 */
diff --git a/libraries/elementary/src/lib/elm_util.c b/libraries/elementary/src/lib/elm_util.c
new file mode 100644
index 0000000..935acd3
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_util.c
@@ -0,0 +1,46 @@
1#ifdef HAVE_CONFIG_H
2# include "elementary_config.h"
3#endif
4#include <Elementary.h>
5#include "elm_priv.h"
6
7char *
8_str_ncpy(char *dest, const char *src, size_t count)
9{
10 if ((!dest) || (!src)) return NULL;
11 return strncpy(dest, src, count);
12}
13
14char *
15_str_append(char *str, const char *txt, int *len, int *alloc)
16{
17 int txt_len = strlen(txt);
18
19 if (txt_len <= 0) return str;
20 if ((*len + txt_len) >= *alloc)
21 {
22 char *str2;
23 int alloc2;
24
25 alloc2 = *alloc + txt_len + 128;
26 str2 = realloc(str, alloc2);
27 if (!str2) return str;
28 *alloc = alloc2;
29 str = str2;
30 }
31 strcpy(str + *len, txt);
32 *len += txt_len;
33 return str;
34}
35
36char *
37_elm_util_mkup_to_text(const char *mkup)
38{
39 return evas_textblock_text_markup_to_utf8(NULL, mkup);
40}
41
42char *
43_elm_util_text_to_mkup(const char *text)
44{
45 return evas_textblock_text_utf8_to_markup(NULL, text);
46}
diff --git a/libraries/elementary/src/lib/elm_video.c b/libraries/elementary/src/lib/elm_video.c
new file mode 100644
index 0000000..173f9ed
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_video.c
@@ -0,0 +1,581 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#ifdef HAVE_EMOTION
5# include <Emotion.h>
6#endif
7
8/* TODO: add buffering support to Emotion and display buffering progression in the theme when needed */
9
10typedef struct _Widget_Data Widget_Data;
11struct _Widget_Data
12{
13 Evas_Object *layout;
14 Evas_Object *emotion;
15
16 Ecore_Timer *timer;
17
18 Eina_Bool stop : 1;
19 Eina_Bool remember : 1;
20};
21
22#ifdef HAVE_EMOTION
23static const char *widtype = NULL;
24
25static const Evas_Smart_Cb_Description _signals[] = {
26 { NULL, NULL }
27};
28
29static void _del_hook(Evas_Object *obj);
30static void _mirrored_set(Evas_Object *obj, Eina_Bool rtl);
31static void _theme_hook(Evas_Object *obj);
32static void _sizing_eval(Evas_Object *obj);
33static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
34static void _on_focus_hook(void *data, Evas_Object *obj);
35static Eina_Bool _event_hook(Evas_Object *obj, Evas_Object *src,
36 Evas_Callback_Type type, void *event_info);
37
38static Eina_Bool
39_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
40{
41 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
42 Evas_Event_Key_Down *ev = event_info;
43 Widget_Data *wd = elm_widget_data_get(obj);
44 if (!wd) return EINA_FALSE;
45 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
46 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
47 if ((!strcmp(ev->keyname, "Left")) ||
48 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
49 {
50 double current, last;
51
52 current = elm_video_play_position_get(obj);
53 last = elm_video_play_length_get(obj);
54
55 if (current < last)
56 {
57 current += last / 100;
58 elm_video_play_position_set(obj, current);
59 }
60
61 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
62 return EINA_TRUE;
63 }
64 if ((!strcmp(ev->keyname, "Right")) ||
65 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
66 {
67 double current, last;
68
69 current = elm_video_play_position_get(obj);
70 last = elm_video_play_length_get(obj);
71
72 if (current > 0)
73 {
74 current -= last / 100;
75 if (current < 0) current = 0;
76 elm_video_play_position_set(obj, current);
77 }
78
79 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
80 return EINA_TRUE;
81 }
82 if (!strcmp(ev->keyname, "space"))
83 {
84 if (elm_video_is_playing_get(obj))
85 elm_video_pause(obj);
86 else
87 elm_video_play(obj);
88 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
89 return EINA_TRUE;
90 }
91 fprintf(stderr, "keyname: '%s' not handle\n", ev->keyname);
92 return EINA_FALSE;
93}
94
95static void
96_del_hook(Evas_Object *obj)
97{
98 Widget_Data *wd = elm_widget_data_get(obj);
99
100 if (!wd) return;
101 if (wd->timer) ecore_timer_del(wd->timer);
102 free(wd);
103}
104
105static void
106_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
107{
108 Widget_Data *wd = elm_widget_data_get(obj);
109 if (!wd) return;
110 if (elm_widget_focus_get(obj))
111 {
112 edje_object_signal_emit(wd->layout, "elm,action,focus", "elm");
113 evas_object_focus_set(wd->layout, EINA_TRUE);
114 }
115 else
116 {
117 edje_object_signal_emit(wd->layout, "elm,action,unfocus", "elm");
118 evas_object_focus_set(wd->layout, EINA_FALSE);
119 }
120}
121
122static void
123_mirrored_set(Evas_Object *obj, Eina_Bool rtl)
124{
125 Widget_Data *wd = elm_widget_data_get(obj);
126 if (!wd) return;
127 edje_object_mirrored_set(wd->layout, rtl);
128}
129
130static void
131_theme_hook(Evas_Object *obj)
132{
133 Widget_Data *wd = elm_widget_data_get(obj);
134 if (!wd) return;
135 _elm_widget_mirrored_reload(obj);
136 _mirrored_set(obj, elm_widget_mirrored_get(obj));
137 _elm_theme_object_set(obj, wd->layout, "video", "base", elm_widget_style_get(obj));
138 edje_object_scale_set(wd->layout, elm_widget_scale_get(obj) *
139 _elm_config->scale);
140 _sizing_eval(obj);
141}
142
143static void
144_sizing_eval(Evas_Object *obj)
145{
146 Widget_Data *wd = elm_widget_data_get(obj);
147 Evas_Coord minw = -1, minh = -1;
148 Evas_Coord w, h;
149
150 if (!wd) return;
151 evas_object_size_hint_request_get(wd->emotion, &minw, &minh);
152 evas_object_size_hint_aspect_set(wd->emotion, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
153 edje_object_size_min_calc(wd->layout, &w, &h);
154
155 if (w != 0 && h != 0)
156 {
157 minw = w;
158 minh = h;
159 }
160 evas_object_size_hint_aspect_set(obj, EVAS_ASPECT_CONTROL_BOTH, minw, minh);
161}
162
163static void
164_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
165{
166 _sizing_eval(data);
167}
168
169static void
170_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
171{
172 Widget_Data *wd = elm_widget_data_get(obj);
173
174 if (wd->remember) emotion_object_last_position_save(wd->emotion);
175}
176
177static void
178_open_done(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
179{
180 Widget_Data *wd = elm_widget_data_get(data);
181
182 edje_object_signal_emit(wd->layout, "elm,video,open", "elm");
183}
184
185static void
186_playback_started(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
187{
188 Widget_Data *wd = elm_widget_data_get(data);
189
190 edje_object_signal_emit(wd->layout, "elm,video,play", "elm");
191}
192
193static void
194_playback_finished(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
195{
196 Widget_Data *wd = elm_widget_data_get(data);
197
198 edje_object_signal_emit(wd->layout, "elm,video,end", "elm");
199}
200
201static void
202_update_aspect_ratio(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
203{
204 _sizing_eval(data);
205}
206
207static void
208_title_change(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
209{
210 Widget_Data *wd = elm_widget_data_get(data);
211 const char *title;
212
213 title = emotion_object_title_get(wd->emotion);
214 edje_object_part_text_escaped_set(wd->layout, "elm,title", title);
215 edje_object_signal_emit(wd->layout, "elm,video,title", "elm");
216}
217
218static void
219_audio_level_change(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
220{
221 (void) data;
222}
223
224static Eina_Bool
225_suspend_cb(void *data)
226{
227 Widget_Data *wd = elm_widget_data_get(data);
228 double interval;
229
230 interval = ecore_timer_interval_get(wd->timer);
231 if (interval <= 20)
232 emotion_object_suspend_set(wd->emotion, EMOTION_SLEEP);
233 else if (interval <= 30)
234 emotion_object_suspend_set(wd->emotion, EMOTION_DEEP_SLEEP);
235 else
236 {
237 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
238 wd->timer = NULL;
239 return ECORE_CALLBACK_CANCEL;
240 }
241
242 ecore_timer_interval_set(wd->timer, interval + 10);
243 return ECORE_CALLBACK_RENEW;
244}
245#endif
246
247Eina_Bool
248_elm_video_check(Evas_Object *video)
249{
250#ifdef HAVE_EMOTION
251 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
252 return EINA_TRUE;
253#else
254 (void) video;
255 return EINA_FALSE;
256#endif
257}
258
259EAPI Evas_Object *
260elm_video_add(Evas_Object *parent)
261{
262#ifdef HAVE_EMOTION
263 Evas_Object *obj;
264 Evas *e;
265 Widget_Data *wd;
266
267 ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
268 ELM_SET_WIDTYPE(widtype, "video");
269 elm_widget_type_set(obj, "video");
270 elm_widget_sub_object_add(parent, obj);
271 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
272 elm_widget_data_set(obj, wd);
273 elm_widget_del_hook_set(obj, _del_hook);
274 elm_widget_theme_hook_set(obj, _theme_hook);
275 elm_widget_can_focus_set(obj, EINA_TRUE);
276 elm_widget_event_hook_set(obj, _event_hook);
277
278 wd->stop = EINA_FALSE;
279 wd->remember = EINA_FALSE;
280
281 wd->layout = edje_object_add(e);
282 _elm_theme_object_set(obj, wd->layout, "video", "base", "default");
283 elm_widget_resize_object_set(obj, wd->layout);
284 evas_object_show(wd->layout);
285 evas_object_size_hint_weight_set(wd->layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
286
287 wd->emotion = emotion_object_add(e);
288 emotion_object_init(wd->emotion, NULL);
289 elm_widget_sub_object_add(obj, wd->emotion);
290 edje_object_part_swallow(wd->layout, "elm.swallow.video", wd->emotion);
291
292 evas_object_smart_callback_add(wd->emotion, "open_done", _open_done, obj);
293 evas_object_smart_callback_add(wd->emotion, "playback_started", _playback_started, obj);
294 evas_object_smart_callback_add(wd->emotion, "playback_finished", _playback_finished, obj);
295 evas_object_smart_callback_add(wd->emotion, "frame_resize", _update_aspect_ratio, obj);
296 evas_object_smart_callback_add(wd->emotion, "title_change", _title_change, obj);
297 evas_object_smart_callback_add(wd->emotion, "audio_level_change", _audio_level_change, obj);
298
299 evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
300 evas_object_event_callback_add(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, NULL);
301 evas_object_smart_callbacks_descriptions_set(obj, _signals);
302
303 _mirrored_set(obj, elm_widget_mirrored_get(obj));
304 _sizing_eval(obj);
305
306 wd->timer = ecore_timer_add(20.0, _suspend_cb, obj);
307
308 return obj;
309#else
310 (void) parent;
311 return NULL;
312#endif
313}
314
315EAPI Eina_Bool
316elm_video_file_set(Evas_Object *video, const char *filename)
317{
318#ifdef HAVE_EMOTION
319 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
320 Widget_Data *wd = elm_widget_data_get(video);
321
322 if (wd->remember) emotion_object_last_position_save(wd->emotion);
323 wd->stop = EINA_FALSE;
324 if (!emotion_object_file_set(wd->emotion, filename)) return EINA_FALSE;
325
326 if ((!strncmp(filename, "file://", 7)) || (!strstr(filename, "://")))
327 emotion_object_last_position_load(wd->emotion);
328
329 edje_object_signal_emit(wd->layout, "elm,video,load", "elm");
330
331 return EINA_TRUE;
332#else
333 (void) video;
334 (void) filename;
335
336 return EINA_FALSE;
337#endif
338}
339
340EAPI Evas_Object *
341elm_video_emotion_get(const Evas_Object *video)
342{
343#ifdef HAVE_EMOTION
344 ELM_CHECK_WIDTYPE(video, widtype) NULL;
345 Widget_Data *wd = elm_widget_data_get(video);
346
347 return wd->emotion;
348#else
349 (void) video;
350 return NULL;
351#endif
352}
353
354EAPI void
355elm_video_play(Evas_Object *video)
356{
357#ifdef HAVE_EMOTION
358 ELM_CHECK_WIDTYPE(video, widtype);
359 Widget_Data *wd = elm_widget_data_get(video);
360
361 if (emotion_object_play_get(wd->emotion)) return ;
362
363 if (wd->timer) ecore_timer_del(wd->timer);
364 wd->timer = NULL;
365 wd->stop = EINA_FALSE;
366 emotion_object_play_set(wd->emotion, EINA_TRUE);
367#else
368 (void) video;
369#endif
370}
371
372/* FIXME: pause will setup timer and go into sleep or
373 * hibernate after a while without activity.
374 */
375
376EAPI void
377elm_video_pause(Evas_Object *video)
378{
379#ifdef HAVE_EMOTION
380 ELM_CHECK_WIDTYPE(video, widtype);
381 Widget_Data *wd = elm_widget_data_get(video);
382
383 if (!emotion_object_play_get(wd->emotion)) return ;
384
385 if (!wd->timer) wd->timer = ecore_timer_add(20.0, _suspend_cb, video);
386 emotion_object_play_set(wd->emotion, EINA_FALSE);
387 edje_object_signal_emit(wd->layout, "elm,video,pause", "elm");
388#else
389 (void) video;
390#endif
391}
392
393/* FIXME: stop should go into hibernate state directly.
394 */
395EAPI void
396elm_video_stop(Evas_Object *video)
397{
398#ifdef HAVE_EMOTION
399 ELM_CHECK_WIDTYPE(video, widtype);
400 Widget_Data *wd = elm_widget_data_get(video);
401
402 if (!emotion_object_play_get(wd->emotion) && wd->stop) return ;
403
404 if (wd->timer) ecore_timer_del(wd->timer);
405 wd->timer = NULL;
406 wd->stop = EINA_TRUE;
407 emotion_object_play_set(wd->emotion, EINA_FALSE);
408 edje_object_signal_emit(wd->layout, "elm,video,stop", "elm");
409 emotion_object_suspend_set(wd->emotion, EMOTION_HIBERNATE);
410#else
411 (void) video;
412#endif
413}
414
415EAPI Eina_Bool
416elm_video_is_playing_get(const Evas_Object *video)
417{
418#ifdef HAVE_EMOTION
419 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
420 Widget_Data *wd = elm_widget_data_get(video);
421
422 return emotion_object_play_get(wd->emotion);
423#else
424 (void) video;
425 return EINA_FALSE;
426#endif
427}
428
429EAPI Eina_Bool
430elm_video_is_seekable_get(const Evas_Object *video)
431{
432#ifdef HAVE_EMOTION
433 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
434 Widget_Data *wd = elm_widget_data_get(video);
435
436 return emotion_object_seekable_get(wd->emotion);
437#else
438 (void) video;
439 return EINA_FALSE;
440#endif
441}
442
443EAPI Eina_Bool
444elm_video_audio_mute_get(const Evas_Object *video)
445{
446#ifdef HAVE_EMOTION
447 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
448 Widget_Data *wd = elm_widget_data_get(video);
449
450 return emotion_object_audio_mute_get(wd->emotion);
451#else
452 (void) video;
453 return EINA_FALSE;
454#endif
455}
456
457EAPI void
458elm_video_audio_mute_set(Evas_Object *video, Eina_Bool mute)
459{
460#ifdef HAVE_EMOTION
461 ELM_CHECK_WIDTYPE(video, widtype);
462 Widget_Data *wd = elm_widget_data_get(video);
463
464 emotion_object_audio_mute_set(wd->emotion, mute);
465#else
466 (void) video;
467 (void) mute;
468#endif
469}
470
471EAPI double
472elm_video_audio_level_get(const Evas_Object *video)
473{
474#ifdef HAVE_EMOTION
475 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
476 Widget_Data *wd = elm_widget_data_get(video);
477
478 return emotion_object_audio_volume_get(wd->emotion);
479#else
480 (void) video;
481 return 0.0;
482#endif
483}
484
485EAPI void
486elm_video_audio_level_set(Evas_Object *video, double volume)
487{
488#ifdef HAVE_EMOTION
489 ELM_CHECK_WIDTYPE(video, widtype);
490 Widget_Data *wd = elm_widget_data_get(video);
491
492 emotion_object_audio_volume_set(wd->emotion, volume);
493#else
494 (void) video;
495 (void) volume;
496#endif
497}
498
499EAPI double
500elm_video_play_position_get(const Evas_Object *video)
501{
502#ifdef HAVE_EMOTION
503 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
504 Widget_Data *wd = elm_widget_data_get(video);
505
506 return emotion_object_position_get(wd->emotion);
507#else
508 (void) video;
509 return 0.0;
510#endif
511}
512
513EAPI void
514elm_video_play_position_set(Evas_Object *video, double position)
515{
516#ifdef HAVE_EMOTION
517 ELM_CHECK_WIDTYPE(video, widtype);
518 Widget_Data *wd = elm_widget_data_get(video);
519
520 emotion_object_position_set(wd->emotion, position);
521#else
522 (void) video;
523 (void) position;
524#endif
525}
526
527EAPI double
528elm_video_play_length_get(const Evas_Object *video)
529{
530#ifdef HAVE_EMOTION
531 ELM_CHECK_WIDTYPE(video, widtype) 0.0;
532 Widget_Data *wd = elm_widget_data_get(video);
533
534 return emotion_object_play_length_get(wd->emotion);
535#else
536 (void) video;
537 return 0.0;
538#endif
539}
540
541EAPI const char *
542elm_video_title_get(const Evas_Object *video)
543{
544#ifdef HAVE_EMOTION
545 ELM_CHECK_WIDTYPE(video, widtype) NULL;
546 Widget_Data *wd = elm_widget_data_get(video);
547
548 return emotion_object_title_get(wd->emotion);
549#else
550 (void) video;
551 return NULL;
552#endif
553}
554
555EAPI void
556elm_video_remember_position_set(Evas_Object *video, Eina_Bool remember)
557{
558#ifdef HAVE_EMOTION
559 ELM_CHECK_WIDTYPE(video, widtype);
560 Widget_Data *wd = elm_widget_data_get(video);
561
562 wd->remember = remember;
563#else
564 (void) video;
565 (void) remember;
566#endif
567}
568
569EAPI Eina_Bool
570elm_video_remember_position_get(const Evas_Object *video)
571{
572#ifdef HAVE_EMOTION
573 ELM_CHECK_WIDTYPE(video, widtype) EINA_FALSE;
574 Widget_Data *wd = elm_widget_data_get(video);
575
576 return wd->remember;
577#else
578 (void) video;
579 return EINA_FALSE;
580#endif
581}
diff --git a/libraries/elementary/src/lib/elm_video.h b/libraries/elementary/src/lib/elm_video.h
new file mode 100644
index 0000000..018f632
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_video.h
@@ -0,0 +1,268 @@
1/**
2 * @defgroup Video Video
3 * @ingroup Elementary
4 *
5 * @addtogroup Video
6 * @{
7 *
8 * Elementary comes with two object that help design application that need
9 * to display video.
10 *
11 * The first one, Elm_Video, display a video by using Emotion.
12 * It embeds the video inside an Edje object, so you can do some
13 * animation depending on the video state change. It also implements a
14 * resource management policy to remove this burden from the application.
15 *
16 * The second one,
17 * Elm_Player is a video player that need to be linked with an Elm_Video.
18 * It take care of updating its content according to Emotion event and provide a
19 * way to theme itself. It also automatically raises the priority of the
20 * linked Elm_Video so it will use the video decoder, if available. It also
21 * activates the "remember" function on the linked Elm_Video object.
22 *
23 * Signals that you can add callback for are :
24 *
25 * "forward,clicked" - the user clicked the forward button.
26 * "info,clicked" - the user clicked the info button.
27 * "next,clicked" - the user clicked the next button.
28 * "pause,clicked" - the user clicked the pause button.
29 * "play,clicked" - the user clicked the play button.
30 * "prev,clicked" - the user clicked the prev button.
31 * "rewind,clicked" - the user clicked the rewind button.
32 * "stop,clicked" - the user clicked the stop button.
33 *
34 * Default content parts of the player widget that you can use for are:
35 * @li "video" - A video of the player
36 *
37 */
38
39/**
40 * @brief Add a new Elm_Player object to the given parent Elementary (container) object.
41 *
42 * @param parent The parent object
43 * @return a new player widget handle or @c NULL, on errors.
44 *
45 * This function inserts a new player widget on the canvas.
46 *
47 * @see elm_object_part_content_set()
48 *
49 * @ingroup Video
50 */
51EAPI Evas_Object *elm_player_add(Evas_Object *parent);
52
53/**
54 * @brief Add a new Elm_Video object to the given parent Elementary (container) object.
55 *
56 * @param parent The parent object
57 * @return a new video widget handle or @c NULL, on errors.
58 *
59 * This function inserts a new video widget on the canvas.
60 *
61 * @see elm_video_file_set()
62 *
63 * @ingroup Video
64 */
65EAPI Evas_Object *elm_video_add(Evas_Object *parent);
66
67/**
68 * @brief Define the file or URI that will be the video source.
69 *
70 * @param video The video object to define the file or URI for the video
71 * of the Elm_Video object.
72 *
73 * @param filename The file or URI to target.
74 * Local files can be specified using file:// or by using full file paths.
75 * URI could be remote source of video, like http:// or local source like
76 * WebCam (v4l2://). (You can use Emotion API to request and list
77 * the available Webcam on your system).
78 *
79 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise
80 *
81 * This function will explicitly define a file or URI as a source
82 * for the video of the Elm_Video object.
83 *
84 * @see elm_video_add()
85 * @see elm_player_add()
86 *
87 * @ingroup Video
88 */
89EAPI Eina_Bool elm_video_file_set(Evas_Object *video, const char *filename);
90
91/**
92 * @brief Get the underlying Emotion object.
93 *
94 * @param video The video object to proceed the request on.
95 * @return the underlying Emotion object.
96 *
97 * @ingroup Video
98 */
99EAPI Evas_Object *elm_video_emotion_get(const Evas_Object *video);
100
101/**
102 * @brief Start to play the video
103 *
104 * @param video The video object to proceed the request on.
105 *
106 * Start to play the video and cancel all suspend state.
107 *
108 * @ingroup Video
109 */
110EAPI void elm_video_play(Evas_Object *video);
111
112/**
113 * @brief Pause the video
114 *
115 * @param video The video object to proceed the request on.
116 *
117 * Pause the video and start a timer to trigger suspend mode.
118 *
119 * @ingroup Video
120 */
121EAPI void elm_video_pause(Evas_Object *video);
122
123/**
124 * @brief Stop the video
125 *
126 * @param video The video object to proceed the request on.
127 *
128 * Stop the video and put the emotion in deep sleep mode.
129 *
130 * @ingroup Video
131 */
132EAPI void elm_video_stop(Evas_Object *video);
133
134/**
135 * @brief Is the video actually playing.
136 *
137 * @param video The video object to proceed the request on.
138 * @return EINA_TRUE if the video is actually playing.
139 *
140 * You should consider watching event on the object instead of polling
141 * the object state.
142 *
143 * @ingroup Video
144 */
145EAPI Eina_Bool elm_video_is_playing_get(const Evas_Object *video);
146
147/**
148 * @brief Is it possible to seek inside the video.
149 *
150 * @param video The video object to proceed the request on.
151 * @return EINA_TRUE if is possible to seek inside the video.
152 *
153 * @ingroup Video
154 */
155EAPI Eina_Bool elm_video_is_seekable_get(const Evas_Object *video);
156
157/**
158 * @brief Is the audio muted.
159 *
160 * @param video The video object to proceed the request on.
161 * @return EINA_TRUE if the audio is muted.
162 *
163 * @ingroup Video
164 */
165EAPI Eina_Bool elm_video_audio_mute_get(const Evas_Object *video);
166
167/**
168 * @brief Change the mute state of the Elm_Video object.
169 *
170 * @param video The video object to proceed the request on.
171 * @param mute The new mute state.
172 *
173 * @ingroup Video
174 */
175EAPI void elm_video_audio_mute_set(Evas_Object *video, Eina_Bool mute);
176
177/**
178 * @brief Get the audio level of the current video.
179 *
180 * @param video The video object to proceed the request on.
181 * @return the current audio level.
182 *
183 * @ingroup Video
184 */
185EAPI double elm_video_audio_level_get(const Evas_Object *video);
186
187/**
188 * @brief Set the audio level of an Elm_Video object.
189 *
190 * @param video The video object to proceed the request on.
191 * @param volume The new audio volume.
192 *
193 * @ingroup Video
194 */
195EAPI void elm_video_audio_level_set(Evas_Object *video, double volume);
196
197/**
198 * @brief Get the current position (in seconds) being played in the
199 * Elm_Video object.
200 *
201 * @param video The video object.
202 * @return the time(in seconds) since the beginning of the media file.
203 *
204 * @ingroup Video
205 */
206EAPI double elm_video_play_position_get(const Evas_Object *video);
207
208/**
209 * @brief Set the current position (in seconds) to be played in the
210 * Elm_Video object.
211 *
212 * @param video The video object.
213 * @param position the time(in seconds) since the beginning of the media file.
214 *
215 * @ingroup Video
216 */
217EAPI void elm_video_play_position_set(Evas_Object *video, double position);
218/**
219 * @brief Get the total playing time (in seconds) of the Elm_Video object.
220 *
221 * @param video The video object.
222 * @return the total duration(in seconds) of the media file.
223 *
224 * @ingroup Video
225 */
226EAPI double elm_video_play_length_get(const Evas_Object *video);
227
228/**
229 * @brief Set whether the object can remember the last played position.
230 *
231 * @param video The video object.
232 * @param remember the last played position of the Elm_Video object.
233 *
234 * @note This API only serves as indication. System support is required.
235 *
236 * @ingroup Video
237 */
238EAPI void elm_video_remember_position_set(Evas_Object *video, Eina_Bool remember);
239
240/**
241 * @brief Set whether the object can remember the last played position.
242 *
243 * @param video The video object.
244 * @return whether the object remembers the last played position (EINA_TRUE)
245 * or not.
246 *
247 * @note This API only serves as indication. System support is required.
248 *
249 * @ingroup Video
250 */
251EAPI Eina_Bool elm_video_remember_position_get(const Evas_Object *video);
252
253/**
254 * @brief Get the title (for ex. DVD title) from this emotion object.
255 *
256 * @param video The Elm_Video object.
257 * @return A string containing the title.
258 *
259 * This function is only useful when playing a DVD.
260 *
261 * @note Don't change or free the string returned by this function.
262 *
263 * @ingroup Video
264 */
265EAPI const char *elm_video_title_get(const Evas_Object *video);
266/**
267 * @}
268 */
diff --git a/libraries/elementary/src/lib/elm_web.c b/libraries/elementary/src/lib/elm_web.c
new file mode 100644
index 0000000..72e970f
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_web.c
@@ -0,0 +1,1944 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4// TODO:
5// 1 - easy to use zoom like elm_photocam API
6// 2 - review scrolling to match elm_scroller. Maybe in future use elm_scroller
7
8#ifdef HAVE_ELEMENTARY_WEB
9#include <EWebKit.h>
10
11/* Similar to iPhone */
12// TODO: switch between iPhone, iPad or Chrome/Safari based on some elm setting?
13#define ELM_WEB_USER_AGENT "Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3 " PACKAGE_NAME "/" PACKAGE_VERSION
14
15static Ewk_View_Smart_Class _parent_sc = EWK_VIEW_SMART_CLASS_INIT_NULL;
16
17typedef struct _View_Smart_Data View_Smart_Data;
18struct _View_Smart_Data
19{
20 Ewk_View_Smart_Data base;
21 struct
22 {
23 Evas_Event_Mouse_Down event;
24 Evas_Coord x, y;
25 unsigned int move_count;
26 Ecore_Timer *longpress_timer;
27 Ecore_Animator *pan_anim;
28 } mouse;
29};
30#endif
31
32typedef struct _Widget_Data Widget_Data;
33struct _Widget_Data
34{
35 Evas_Object *self;
36#ifdef HAVE_ELEMENTARY_WEB
37 Evas_Object *ewk_view;
38 struct
39 {
40 Elm_Web_Window_Open window_create;
41 void *window_create_data;
42 Elm_Web_Dialog_Alert alert;
43 void *alert_data;
44 Elm_Web_Dialog_Confirm confirm;
45 void *confirm_data;
46 Elm_Web_Dialog_Prompt prompt;
47 void *prompt_data;
48 Elm_Web_Dialog_File_Selector file_selector;
49 void *file_selector_data;
50 Elm_Web_Console_Message console_message;
51 void *console_message_data;
52 } hook;
53 Elm_Win_Keyboard_Mode input_method;
54 struct
55 {
56 Elm_Web_Zoom_Mode mode;
57 float current;
58 float min, max;
59 Eina_Bool no_anim;
60 Ecore_Timer *timer;
61 } zoom;
62 struct
63 {
64 struct
65 {
66 int x, y;
67 } start, end;
68 Ecore_Animator *animator;
69 } bring_in;
70 Eina_Bool tab_propagate : 1;
71 Eina_Bool inwin_mode : 1;
72#else
73 Evas_Object *label;
74#endif
75};
76
77enum Dialog_Type
78{
79 DIALOG_ALERT,
80 DIALOG_CONFIRM,
81 DIALOG_PROMPT,
82 DIALOG_FILE_SELECTOR
83};
84
85typedef struct _Dialog_Data Dialog_Data;
86struct _Dialog_Data
87{
88 enum Dialog_Type type;
89 Evas_Object *dialog;
90 Evas_Object *box;
91 Evas_Object *bt_ok, *bt_cancel;
92 Evas_Object *entry;
93 Evas_Object *file_sel;
94
95 Eina_Bool *response;
96 char **entry_value;
97 Eina_List **selected_files;
98};
99
100struct _Elm_Web_Callback_Proxy_Context
101{
102 const char *name;
103 Evas_Object *obj;
104};
105typedef struct _Elm_Web_Callback_Proxy_Context Elm_Web_Callback_Proxy_Context;
106
107static const char *widtype = NULL;
108static const Evas_Smart_Cb_Description _elm_web_callback_names[] = {
109 { "download,request", "p" },
110 { "editorclient,contents,changed", "" },
111 { "editorclient,selection,changed", "" },
112 { "frame,created", "p" },
113 { "icon,received", "" },
114 { "inputmethod,changed", "b" },
115 { "js,windowobject,clear", "" },
116 { "link,hover,in", "p" },
117 { "link,hover,out", "" },
118 { "load,document,finished", "p" },
119 { "load,error", "p" },
120 { "load,finished", "p" },
121 { "load,newwindow,show", "" },
122 { "load,progress", "d" },
123 { "load,provisional", "" },
124 { "load,started", "" },
125 { "menubar,visible,get", "b" },
126 { "menubar,visible,set", "b" },
127 { "popup,created", "p" },
128 { "popup,willdelete", "p" },
129 { "ready", "" },
130 { "scrollbars,visible,get", "b" },
131 { "scrollbars,visible,set", "b" },
132 { "statusbar,text,set", "s" },
133 { "statusbar,visible,get", "b" },
134 { "statusbar,visible,set", "b" },
135 { "title,changed", "s" },
136 { "toolbars,visible,get", "b" },
137 { "toolbars,visible,set", "b" },
138 { "tooltip,text,set", "s" },
139 { "uri,changed", "s" },
140 { "view,resized", "" },
141 { "windows,close,request", ""},
142 { "zoom,animated,end", "" },
143 { NULL, NULL }
144};
145
146#ifdef HAVE_ELEMENTARY_WEB
147static char *
148_webkit_theme_find(const Eina_List *list)
149{
150 const Eina_List *l;
151 const char *th;
152
153 EINA_LIST_FOREACH(list, l, th)
154 {
155 char *path = elm_theme_list_item_path_get(th, NULL);
156 if (!path) continue;
157 if (edje_file_group_exists(path, "webkit/base"))
158 return path;
159 free(path);
160 }
161
162 return NULL;
163}
164#endif
165
166static void
167_theme_hook(Evas_Object *obj)
168{
169#ifdef HAVE_ELEMENTARY_WEB
170 Elm_Theme *theme = elm_object_theme_get(obj);
171 Widget_Data *wd = elm_widget_data_get(obj);
172 const Eina_List *themes;
173 char *view_theme = NULL;
174
175 themes = elm_theme_overlay_list_get(theme);
176 view_theme = _webkit_theme_find(themes);
177 if (view_theme) goto set;
178
179 themes = elm_theme_list_get(theme);
180 view_theme = _webkit_theme_find(themes);
181 if (view_theme) goto set;
182
183 themes = elm_theme_extension_list_get(theme);
184 view_theme = _webkit_theme_find(themes);
185
186set:
187 if (view_theme)
188 {
189 ewk_view_theme_set(wd->ewk_view, view_theme);
190 free(view_theme);
191 }
192 else
193 ewk_view_theme_set(wd->ewk_view, WEBKIT_DATADIR"/themes/default.edj");
194#else
195 (void)obj;
196#endif
197}
198
199static void
200_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
201{
202#ifdef HAVE_ELEMENTARY_WEB
203 Widget_Data *wd = elm_widget_data_get(obj);
204 Evas_Object *top = elm_widget_top_get(obj);
205
206 if (!wd) return;
207
208 if (elm_object_focus_get(obj))
209 {
210 evas_object_focus_set(wd->ewk_view, EINA_TRUE);
211 if (top) elm_win_keyboard_mode_set(top, wd->input_method);
212 }
213 else
214 {
215 evas_object_focus_set(wd->ewk_view, EINA_FALSE);
216 if (top) elm_win_keyboard_mode_set(top, ELM_WIN_KEYBOARD_OFF);
217 }
218#else
219 (void)obj;
220#endif
221}
222
223static Eina_Bool
224_event_hook(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
225{
226#ifdef HAVE_ELEMENTARY_WEB
227 Evas_Event_Key_Down *ev = event_info;
228 Widget_Data *wd = elm_widget_data_get(obj);
229
230 if (!wd) return EINA_FALSE;
231 if (type != EVAS_CALLBACK_KEY_DOWN) return EINA_FALSE;
232 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return EINA_FALSE;
233 if (elm_widget_disabled_get(obj)) return EINA_FALSE;
234
235 if ((!strcmp(ev->keyname, "Tab")) && (!wd->tab_propagate))
236 {
237 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
238 return EINA_TRUE;
239 }
240 else
241 return EINA_FALSE;
242#else
243 return EINA_FALSE;
244 (void)obj;
245 (void)type;
246 (void)event_info;
247#endif
248}
249
250#ifdef HAVE_ELEMENTARY_WEB
251static Eina_Bool
252_view_pan_animator(void *data)
253{
254 View_Smart_Data *sd = data;
255 Evas_Coord x, y, dx, dy;
256
257 evas_pointer_canvas_xy_get(sd->base.base.evas, &x, &y);
258
259 dx = sd->mouse.x - x;
260 dy = sd->mouse.y - y;
261
262 if ((dx == 0) && (dy == 0))
263 goto end;
264
265 ewk_frame_scroll_add(sd->base.main_frame, dx, dy);
266
267 sd->mouse.x = x;
268 sd->mouse.y = y;
269
270 end:
271 return EINA_TRUE;
272}
273
274static void
275_view_smart_add(Evas_Object *obj)
276{
277 View_Smart_Data *sd;
278
279 sd = calloc(1, sizeof(View_Smart_Data));
280 evas_object_smart_data_set(obj, sd);
281
282 _parent_sc.sc.add(obj);
283
284 ewk_view_history_enable_set(obj, EINA_TRUE);
285 ewk_history_limit_set(ewk_view_history_get(obj), 100);
286 // TODO: auto toggle between smooth/nearest during bring-in animations
287 //ewk_view_zoom_weak_smooth_scale_set(obj, EINA_TRUE);
288}
289
290static void
291_view_smart_del(Evas_Object *obj)
292{
293 View_Smart_Data *sd;
294
295 sd = evas_object_smart_data_get(obj);
296
297 if (sd->mouse.pan_anim)
298 ecore_animator_del(sd->mouse.pan_anim);
299
300 _parent_sc.sc.del(obj);
301}
302
303static Eina_Bool
304_view_longpress_timer(void *data)
305{
306 View_Smart_Data *sd = data;
307
308 sd->mouse.move_count = 0;
309 sd->mouse.longpress_timer = NULL;
310 return ECORE_CALLBACK_CANCEL;
311}
312
313static Eina_Bool
314_view_smart_mouse_down(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Down *event)
315{
316 // TODO: mimic elm_scroller and like
317 // TODO-minor: offer hook?
318 View_Smart_Data *sd = (View_Smart_Data *)esd;
319
320 if (event->button != 1)
321 return _parent_sc.mouse_down(esd, event);
322
323 sd->mouse.pan_anim = ecore_animator_add(_view_pan_animator, sd);
324 sd->mouse.longpress_timer = ecore_timer_add(_elm_config->longpress_timeout, _view_longpress_timer, sd);
325 sd->mouse.move_count = 1;
326 sd->mouse.x = event->canvas.x;
327 sd->mouse.y = event->canvas.y;
328 sd->mouse.event = *event;
329
330 return EINA_TRUE;
331}
332
333static Eina_Bool
334_view_smart_mouse_up(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Up *event)
335{
336 // TODO: mimic elm_scroller and like
337 // TODO-minor: offer hook?
338 View_Smart_Data *sd = (View_Smart_Data *)esd;
339
340 if (sd->mouse.pan_anim)
341 {
342 ecore_animator_del(sd->mouse.pan_anim);
343 sd->mouse.pan_anim = NULL;
344
345 if (sd->mouse.longpress_timer)
346 _parent_sc.mouse_down(esd, &sd->mouse.event);
347 else
348 return EINA_TRUE;
349 }
350
351 if (sd->mouse.longpress_timer)
352 {
353 ecore_timer_del(sd->mouse.longpress_timer);
354 sd->mouse.longpress_timer = NULL;
355 }
356
357 sd->mouse.move_count = 0;
358 return _parent_sc.mouse_up(esd, event);
359}
360
361static Eina_Bool
362_view_smart_mouse_move(Ewk_View_Smart_Data *esd, const Evas_Event_Mouse_Move *event)
363{
364 // TODO: mimic elm_scroller and like
365 // TODO-minor: offer hook?
366 View_Smart_Data *sd = (View_Smart_Data *)esd;
367 sd->mouse.move_count++;
368
369 if (sd->mouse.longpress_timer &&
370 (((sd->mouse.x ^ sd->mouse.event.canvas.x) |
371 (sd->mouse.y ^ sd->mouse.event.canvas.y)) & (~0x07)))
372 {
373 ecore_timer_del(sd->mouse.longpress_timer);
374 sd->mouse.longpress_timer = NULL;
375 }
376
377 if (sd->mouse.pan_anim)
378 {
379 return EINA_FALSE;
380 }
381
382 return _parent_sc.mouse_move(esd, event);
383}
384
385static Evas_Object *
386_view_smart_window_create(Ewk_View_Smart_Data *sd, Eina_Bool javascript, const Ewk_Window_Features *window_features)
387{
388 Evas_Object *new;
389 Evas_Object *obj = evas_object_smart_parent_get(sd->self);
390 Widget_Data *wd = elm_widget_data_get(obj);
391
392 if (!wd->hook.window_create) return NULL;
393 new = wd->hook.window_create(wd->hook.window_create_data, obj, javascript,
394 (const Elm_Web_Window_Features *)window_features);
395 if (new) return elm_web_webkit_view_get(new);
396
397 return NULL;
398}
399
400static void
401_view_smart_window_close(Ewk_View_Smart_Data *sd)
402{
403 Evas_Object *obj = evas_object_smart_parent_get(sd->self);
404 evas_object_smart_callback_call(obj, "windows,close,request", NULL);
405}
406
407static void
408_bt_close(void *data, Evas_Object *obj, void *event_info __UNUSED__)
409{
410 Dialog_Data *d = data;
411
412 *d->response = (obj == d->bt_ok);
413 if ((d->type == DIALOG_PROMPT) && (*d->response == EINA_TRUE))
414 *d->entry_value = strdup(elm_entry_entry_get(d->entry));
415 evas_object_del(d->dialog);
416}
417
418static void
419_file_sel_done(void *data, Evas_Object *obj __UNUSED__, void *event_info)
420{
421 Dialog_Data *d = data;
422 if (event_info)
423 {
424 *d->selected_files = eina_list_append(NULL, strdup(event_info));
425 *d->response = EINA_TRUE;
426 }
427 else
428 *d->response = EINA_FALSE;
429 evas_object_del(d->dialog);
430 free(d);
431}
432
433static Dialog_Data *
434_dialog_new(Evas_Object *parent)
435{
436 Dialog_Data *d;
437 Widget_Data *wd = elm_widget_data_get(parent);
438
439 d = calloc(1, sizeof(Dialog_Data));
440 if (!d) return NULL;
441
442 if (!parent || wd->inwin_mode)
443 {
444 Evas_Object *bg;
445
446 d->dialog = elm_win_add(NULL, "elm-web-popup", ELM_WIN_DIALOG_BASIC);
447 evas_object_smart_callback_add(d->dialog, "delete,request",
448 _bt_close, d);
449
450 bg = elm_bg_add(d->dialog);
451 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND,
452 EVAS_HINT_EXPAND);
453 elm_win_resize_object_add(d->dialog, bg);
454 evas_object_show(bg);
455
456 d->box = elm_box_add(d->dialog);
457 evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
458 EVAS_HINT_EXPAND);
459 elm_win_resize_object_add(d->dialog, d->box);
460 evas_object_show(d->box);
461 }
462 else
463 {
464 Evas_Object *win = elm_widget_top_get(parent);
465 d->dialog = elm_win_inwin_add(win);
466 elm_object_style_set(d->dialog, "minimal");
467 evas_object_size_hint_weight_set(d->dialog, EVAS_HINT_EXPAND,
468 EVAS_HINT_EXPAND);
469
470 d->box = elm_box_add(win);
471 evas_object_size_hint_weight_set(d->box, EVAS_HINT_EXPAND,
472 EVAS_HINT_EXPAND);
473 elm_win_inwin_content_set(d->dialog, d->box);
474 evas_object_show(d->box);
475 }
476
477 return d;
478}
479
480static Evas_Object *
481_run_dialog(Evas_Object *parent, enum Dialog_Type type, const char *message, const char *default_entry_value, char **entry_value, Eina_Bool allows_multiple_files __UNUSED__, Eina_List *accept_types __UNUSED__, Eina_List **selected_filenames, Eina_Bool *response)
482{
483 EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!default_entry_value), EINA_FALSE);
484 EINA_SAFETY_ON_TRUE_RETURN_VAL((type != DIALOG_PROMPT) && (!!entry_value), EINA_FALSE);
485
486 Dialog_Data *dialog_data = _dialog_new(evas_object_smart_parent_get(parent));
487 Evas_Object *lb;
488
489 if (type != DIALOG_FILE_SELECTOR)
490 {
491 lb = elm_label_add(dialog_data->box);
492 elm_object_text_set(lb, message);
493 elm_box_pack_end(dialog_data->box, lb);
494 evas_object_show(lb);
495 }
496
497 dialog_data->type = type;
498 dialog_data->response = response;
499 dialog_data->entry_value = entry_value;
500 dialog_data->selected_files = selected_filenames;
501
502 if (type == DIALOG_ALERT)
503 {
504 dialog_data->bt_ok = elm_button_add(dialog_data->box);
505 elm_object_text_set(dialog_data->bt_ok, "Close");
506 elm_box_pack_end(dialog_data->box, dialog_data->bt_ok);
507 evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
508 evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
509 evas_object_show(dialog_data->bt_ok);
510 }
511 else if (type == DIALOG_FILE_SELECTOR)
512 {
513 dialog_data->file_sel = elm_fileselector_add(dialog_data->dialog);
514 evas_object_size_hint_weight_set(dialog_data->file_sel,
515 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
516 evas_object_size_hint_align_set(dialog_data->file_sel, EVAS_HINT_FILL,
517 EVAS_HINT_FILL);
518 elm_box_pack_end(dialog_data->box, dialog_data->file_sel);
519 evas_object_show(dialog_data->file_sel);
520
521 elm_fileselector_path_set(dialog_data->file_sel, ".");
522 elm_fileselector_is_save_set(dialog_data->file_sel, EINA_FALSE);
523 elm_fileselector_folder_only_set(dialog_data->file_sel, EINA_FALSE);
524 elm_fileselector_buttons_ok_cancel_set(dialog_data->file_sel,
525 EINA_TRUE);
526 elm_fileselector_expandable_set(dialog_data->file_sel, EINA_FALSE);
527 evas_object_smart_callback_add(dialog_data->file_sel, "done",
528 _file_sel_done, dialog_data);
529 // fileselector can't set it's minimum size correctly
530 evas_object_size_hint_min_set(dialog_data->file_sel, 300, 400);
531 }
532 else
533 {
534 if (type == DIALOG_PROMPT)
535 {
536 dialog_data->entry = elm_entry_add(dialog_data->box);
537 elm_entry_single_line_set(dialog_data->entry, EINA_TRUE);
538 elm_entry_scrollable_set(dialog_data->entry, EINA_TRUE);
539 elm_entry_entry_set(dialog_data->entry, default_entry_value);
540 evas_object_size_hint_align_set(dialog_data->entry, EVAS_HINT_FILL, EVAS_HINT_FILL);
541 evas_object_size_hint_weight_set(dialog_data->entry, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
542 elm_box_pack_end(dialog_data->box, dialog_data->entry);
543 evas_object_show(dialog_data->entry);
544 }
545
546 if (type == DIALOG_PROMPT || type == DIALOG_CONFIRM)
547 {
548 Evas_Object *bx_h = elm_box_add(dialog_data->box);
549 elm_box_horizontal_set(bx_h, 1);
550 elm_box_pack_end(dialog_data->box, bx_h);
551 evas_object_size_hint_weight_set(bx_h, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
552 evas_object_size_hint_align_set(bx_h, EVAS_HINT_FILL, EVAS_HINT_FILL);
553 evas_object_show(bx_h);
554
555 dialog_data->bt_cancel = elm_button_add(bx_h);
556 elm_object_text_set(dialog_data->bt_cancel, "Cancel");
557 elm_box_pack_end(bx_h, dialog_data->bt_cancel);
558 evas_object_size_hint_weight_set(dialog_data->bt_cancel, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
559 evas_object_size_hint_align_set(dialog_data->bt_cancel, EVAS_HINT_FILL, EVAS_HINT_FILL);
560 evas_object_smart_callback_add(dialog_data->bt_cancel, "clicked", _bt_close, dialog_data);
561 evas_object_show(dialog_data->bt_cancel);
562
563 dialog_data->bt_ok = elm_button_add(bx_h);
564 elm_object_text_set(dialog_data->bt_ok, "Ok");
565 elm_box_pack_end(bx_h, dialog_data->bt_ok);
566 evas_object_size_hint_weight_set(dialog_data->bt_ok, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
567 evas_object_size_hint_align_set(dialog_data->bt_ok, EVAS_HINT_FILL, EVAS_HINT_FILL);
568 evas_object_smart_callback_add(dialog_data->bt_ok, "clicked", _bt_close, dialog_data);
569 evas_object_show(dialog_data->bt_ok);
570 }
571 else
572 return EINA_FALSE;
573 }
574
575 evas_object_show(dialog_data->dialog);
576
577 return dialog_data->dialog;
578}
579
580static void
581_dialog_del_cb(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
582{
583 ecore_main_loop_quit();
584}
585
586static void
587_exec_dialog(Evas_Object *dialog)
588{
589 evas_object_event_callback_add(dialog, EVAS_CALLBACK_DEL, _dialog_del_cb,
590 NULL);
591 ecore_main_loop_begin();
592}
593
594/* called by ewk_view when javascript called alert()
595 *
596 */
597static void
598_view_smart_run_javascript_alert(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
599{
600 View_Smart_Data *sd = (View_Smart_Data *)esd;
601 Evas_Object *view = sd->base.self;
602 Evas_Object *obj = evas_object_smart_parent_get(view);
603 Evas_Object *diag = NULL;
604 Widget_Data *wd = elm_widget_data_get(obj);
605 Eina_Bool response = EINA_FALSE;
606
607 if (wd->hook.alert)
608 diag = wd->hook.alert(wd->hook.alert_data, obj, message);
609 else
610 diag = _run_dialog(view, DIALOG_ALERT, message, NULL, NULL, EINA_FALSE,
611 NULL, NULL, &response);
612 if (diag) _exec_dialog(diag);
613}
614
615/* called by ewk_view when javascript called confirm()
616 *
617 */
618static Eina_Bool
619_view_smart_run_javascript_confirm(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message)
620{
621 View_Smart_Data *sd = (View_Smart_Data *)esd;
622 Evas_Object *view = sd->base.self;
623 Evas_Object *obj = evas_object_smart_parent_get(view);
624 Evas_Object *diag = NULL;
625 Widget_Data *wd = elm_widget_data_get(obj);
626 Eina_Bool response = EINA_FALSE;
627
628 if (wd->hook.confirm)
629 diag = wd->hook.confirm(wd->hook.confirm_data, obj, message, &response);
630 else
631 diag = _run_dialog(view, DIALOG_CONFIRM, message, NULL, NULL, EINA_FALSE,
632 NULL, NULL, &response);
633 if (diag) _exec_dialog(diag);
634 return response;
635}
636
637/* called by ewk_view when javascript called confirm()
638 *
639 */
640static Eina_Bool
641_view_smart_run_javascript_prompt(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, const char *message, const char *default_value, char **value)
642{
643 View_Smart_Data *sd = (View_Smart_Data *)esd;
644 Evas_Object *view = sd->base.self;
645 Evas_Object *obj = evas_object_smart_parent_get(view);
646 Evas_Object *diag = NULL;
647 Widget_Data *wd = elm_widget_data_get(obj);
648 Eina_Bool response = EINA_FALSE;
649
650 if (wd->hook.prompt)
651 diag = wd->hook.prompt(wd->hook.prompt_data, obj, message, default_value,
652 value, &response);
653 else
654 diag = _run_dialog(view, DIALOG_PROMPT, message, default_value, value,
655 EINA_FALSE, NULL, NULL, &response);
656 if (diag) _exec_dialog(diag);
657 if (!response)
658 *value = NULL;
659
660 return EINA_TRUE;
661}
662
663static Eina_Bool
664_view_smart_run_open_panel(Ewk_View_Smart_Data *esd, Evas_Object *frame __UNUSED__, Eina_Bool allows_multiple_files, Eina_List *accept_types, Eina_List **selected_filenames)
665{
666 View_Smart_Data *sd = (View_Smart_Data *)esd;
667 Evas_Object *view = sd->base.self;
668 Evas_Object *obj = evas_object_smart_parent_get(view);
669 Evas_Object *diag = NULL;
670 Widget_Data *wd = elm_widget_data_get(obj);
671 Eina_Bool response = EINA_FALSE;
672
673 if (wd->hook.file_selector)
674 diag = wd->hook.file_selector(wd->hook.file_selector_data, obj,
675 allows_multiple_files, accept_types,
676 selected_filenames, &response);
677 else
678 diag = _run_dialog(view, DIALOG_FILE_SELECTOR, NULL, NULL, NULL,
679 allows_multiple_files, accept_types, selected_filenames,
680 &response);
681 if (diag) _exec_dialog(diag);
682
683 return response;
684}
685
686static void
687_view_smart_add_console_message(Ewk_View_Smart_Data *esd, const char *message, unsigned int line_number, const char *source_id)
688{
689 Evas_Object *obj = evas_object_smart_parent_get(esd->self);
690 Widget_Data *wd = elm_widget_data_get(obj);
691
692 if (wd->hook.console_message)
693 wd->hook.console_message(wd->hook.console_message_data, obj, message,
694 line_number, source_id);
695}
696
697static Eina_Bool
698_view_smart_focus_can_cycle(Ewk_View_Smart_Data *sd, Ewk_Focus_Direction direction)
699{
700 Evas_Object *obj = evas_object_smart_parent_get(sd->self);
701 Elm_Focus_Direction dir;
702
703 switch (direction)
704 {
705 case EWK_FOCUS_DIRECTION_FORWARD:
706 dir = ELM_FOCUS_NEXT;
707 break;
708 case EWK_FOCUS_DIRECTION_BACKWARD:
709 dir = ELM_FOCUS_PREVIOUS;
710 break;
711 default:
712 return EINA_FALSE;
713 }
714
715 elm_widget_focus_cycle(elm_widget_parent_get(obj), dir);
716
717 return EINA_TRUE;
718}
719
720/**
721 * Creates a new view object given the parent.
722 *
723 * @param parent object to use as parent.
724 *
725 * @return newly added Evas_Object or @c NULL on errors.
726 */
727Evas_Object *
728_view_add(Evas_Object *parent)
729{
730 static Evas_Smart *smart = NULL;
731 Evas *canvas = evas_object_evas_get(parent);
732 Evas_Object *view;
733
734 if (!smart)
735 {
736 static Ewk_View_Smart_Class api = EWK_VIEW_SMART_CLASS_INIT_NAME_VERSION("EWK_View_Elementary");
737
738#ifndef TILED_BACKING_STORE
739 ewk_view_single_smart_set(&api);
740#else
741 ewk_view_tiled_smart_set(&api);
742#endif
743
744 _parent_sc = api;
745
746 // TODO: check every api method and provide overrides with hooks!
747 // TODO: hooks should provide extension points
748 // TODO: extension should have some kind of "default implementation",
749 // TODO: that can be replaced or controlled by hooks.
750 // TODO: ie: run_javascript_alert() should present an elm_win
751 // TODO: by default, but user could override it to show as inwin.
752 api.sc.add = _view_smart_add;
753 api.sc.del = _view_smart_del;
754 //api.sc.calculate = _view_smart_calculate;
755 api.mouse_down = _view_smart_mouse_down;
756 api.mouse_up = _view_smart_mouse_up;
757 api.mouse_move = _view_smart_mouse_move;
758 api.add_console_message = _view_smart_add_console_message;
759 api.window_create = _view_smart_window_create;
760 api.window_close = _view_smart_window_close;
761 api.run_javascript_alert = _view_smart_run_javascript_alert;
762 api.run_javascript_confirm = _view_smart_run_javascript_confirm;
763 api.run_javascript_prompt = _view_smart_run_javascript_prompt;
764 api.run_open_panel = _view_smart_run_open_panel;
765 api.focus_can_cycle = _view_smart_focus_can_cycle;
766
767 smart = evas_smart_class_new(&api.sc);
768 if (!smart)
769 {
770 CRITICAL("Could not create smart class");
771 return NULL;
772 }
773 }
774
775 view = evas_object_smart_add(canvas, smart);
776 if (!view)
777 {
778 ERR("Could not create smart object object for view");
779 return NULL;
780 }
781
782 return view;
783}
784
785static void
786_ewk_view_inputmethod_change_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
787{
788 Widget_Data *wd = data;
789 Evas_Object *top = elm_widget_top_get(wd->self);
790 if (!top) return;
791
792 if (event_info)
793 wd->input_method = ELM_WIN_KEYBOARD_ON;
794 else
795 wd->input_method = ELM_WIN_KEYBOARD_OFF;
796 elm_win_keyboard_mode_set(top, wd->input_method);
797}
798
799static void
800_ewk_view_load_started_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
801{
802 _ewk_view_inputmethod_change_cb(data, obj, (void *)(long)EINA_FALSE);
803}
804
805static void
806_ewk_view_load_finished_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
807{
808 Widget_Data *wd = data;
809
810 if (event_info)
811 return;
812
813 if (wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL)
814 {
815 float tz = wd->zoom.current;
816 wd->zoom.current = 0.0;
817 elm_web_zoom_set(wd->self, tz);
818 }
819}
820
821static void
822_ewk_view_viewport_changed_cb(void *data, Evas_Object *obj, void *event_info __UNUSED__)
823{
824 Widget_Data *wd = data;
825
826 if (wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL)
827 {
828 ewk_view_zoom_set(obj, 1.0, 0, 0);
829 wd->zoom.no_anim = EINA_TRUE;
830 }
831}
832
833static Eina_Bool
834_restore_zoom_mode_timer_cb(void *data)
835{
836 Widget_Data *wd = data;
837 float tz = wd->zoom.current;
838 wd->zoom.timer = NULL;
839 wd->zoom.current = 0.0;
840 wd->zoom.no_anim = EINA_TRUE;
841 elm_web_zoom_set(wd->self, tz);
842 return EINA_FALSE;
843}
844
845static Eina_Bool
846_reset_zoom_timer_cb(void *data)
847{
848 Widget_Data *wd = data;
849 wd->zoom.timer = ecore_timer_add(0.0, _restore_zoom_mode_timer_cb, wd);
850 ewk_view_zoom_set(wd->ewk_view, 1.0, 0, 0);
851 return EINA_FALSE;
852}
853
854static void
855_ewk_view_resized_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
856{
857 Widget_Data *wd = data;
858 if (!(wd->zoom.mode != ELM_WEB_ZOOM_MODE_MANUAL))
859 return;
860 if (wd->zoom.timer)
861 ecore_timer_del(wd->zoom.timer);
862 wd->zoom.timer = ecore_timer_add(0.5, _reset_zoom_timer_cb, wd);
863}
864
865static void
866_popup_del_job(void *data)
867{
868 evas_object_del(data);
869}
870
871static void
872_popup_will_delete(void *data, Evas_Object *obj, void *event_info __UNUSED__)
873{
874 ecore_job_add(_popup_del_job, data);
875 evas_object_smart_callback_del(obj, "popup,willdelete", _popup_will_delete);
876}
877
878static void
879_popup_item_selected(void *data, Evas_Object *obj, void *event_info __UNUSED__)
880{
881 Evas_Object *view = data;
882 Elm_Object_Item *list_it = elm_list_selected_item_get(obj);
883 const Eina_List *itr, *list = elm_list_items_get(obj);
884 void *d;
885 int i = 0;
886
887 EINA_LIST_FOREACH(list, itr, d)
888 {
889 if (d == list_it)
890 break;
891
892 i++;
893 }
894
895 ewk_view_popup_selected_set(view, i);
896 ewk_view_popup_destroy(view);
897}
898
899static void
900_popup_dismiss_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
901{
902 ewk_view_popup_destroy(data);
903}
904
905static void
906_ewk_view_popup_create_cb(void *data, Evas_Object *obj, void *event_info)
907{
908 Widget_Data *wd = data;
909 Ewk_Menu *m = event_info;
910 Elm_Web_Menu m2;
911 Ewk_Menu_Item *it;
912 Eina_List *itr;
913 Evas_Object *notify, *list;
914
915 m2.items = m->items;
916 m2.x = m->x;
917 m2.y = m->y;
918 m2.width = m->width;
919 m2.height = m->height;
920 m2.handled = EINA_FALSE;
921 evas_object_smart_callback_call(wd->self, "popup,create", &m2);
922 if (m2.handled)
923 return;
924
925 notify = elm_notify_add(obj);
926 elm_notify_allow_events_set(notify, EINA_FALSE);
927 elm_notify_orient_set(notify, ELM_NOTIFY_ORIENT_BOTTOM);
928
929 list = elm_list_add(obj);
930 elm_list_select_mode_set(data, ELM_OBJECT_SELECT_MODE_ALWAYS);
931 elm_list_bounce_set(list, EINA_FALSE, EINA_FALSE);
932 elm_list_mode_set(list, ELM_LIST_EXPAND);
933 evas_object_size_hint_weight_set(list, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
934 evas_object_size_hint_align_set(list, EVAS_HINT_FILL, EVAS_HINT_FILL);
935 elm_object_content_set(notify, list);
936 evas_object_show(list);
937
938 EINA_LIST_FOREACH(m->items, itr, it)
939 elm_list_item_append(list, it->text, NULL, NULL, _popup_item_selected,
940 obj);
941 elm_list_go(list);
942
943 evas_object_show(notify);
944
945 evas_object_smart_callback_add(obj, "popup,willdelete", _popup_will_delete,
946 notify);
947 evas_object_smart_callback_add(notify, "block,clicked", _popup_dismiss_cb,
948 obj);
949}
950
951static void
952_view_smart_callback_proxy_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
953{
954 free(data);
955}
956
957static void
958_view_smart_callback_proxy_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info)
959{
960 Elm_Web_Callback_Proxy_Context *ctxt = data;
961
962 evas_object_smart_callback_call(ctxt->obj, ctxt->name, event_info);
963}
964
965static void
966_view_smart_callback_proxy(Evas_Object *view, Evas_Object *parent)
967{
968 const Evas_Smart_Cb_Description **cls_descs, **inst_descs;
969 unsigned int cls_count, inst_count, total;
970 Elm_Web_Callback_Proxy_Context *ctxt;
971
972 evas_object_smart_callbacks_descriptions_get(view, &cls_descs, &cls_count,
973 &inst_descs, &inst_count);
974 total = cls_count + inst_count;
975 if (!total) return;
976 ctxt = malloc(sizeof(Elm_Web_Callback_Proxy_Context) * total);
977 if (!ctxt) return;
978 evas_object_event_callback_add(view, EVAS_CALLBACK_FREE,
979 _view_smart_callback_proxy_free_cb, ctxt);
980
981 for (; cls_count > 0; cls_count--, cls_descs++, ctxt++)
982 {
983 const Evas_Smart_Cb_Description *d = *cls_descs;
984 if (!strcmp(d->name, "popup,create"))
985 continue;
986 ctxt->name = d->name;
987 ctxt->obj = parent;
988 evas_object_smart_callback_add(view, d->name,
989 _view_smart_callback_proxy_cb, ctxt);
990 }
991
992 for (; inst_count > 0; inst_count--, inst_descs++, ctxt++)
993 {
994 const Evas_Smart_Cb_Description *d = *inst_descs;
995 ctxt->name = d->name;
996 ctxt->obj = parent;
997 evas_object_smart_callback_add(view, d->name,
998 _view_smart_callback_proxy_cb, ctxt);
999 }
1000}
1001
1002static Eina_Bool
1003_bring_in_anim_cb(void *data, double pos)
1004{
1005 Widget_Data *wd = data;
1006 Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
1007 int sx, sy, rx, ry;
1008
1009 sx = wd->bring_in.start.x;
1010 sy = wd->bring_in.start.y;
1011 rx = (wd->bring_in.end.x - sx) * pos;
1012 ry = (wd->bring_in.end.y - sy) * pos;
1013
1014 ewk_frame_scroll_set(frame, rx + sx, ry + sy);
1015
1016 if (pos == 1.0)
1017 {
1018 wd->bring_in.end.x = wd->bring_in.end.y = wd->bring_in.start.x =
1019 wd->bring_in.start.y = 0;
1020 wd->bring_in.animator = NULL;
1021 }
1022
1023 return EINA_TRUE;
1024}
1025#endif
1026
1027#ifdef HAVE_ELEMENTARY_WEB
1028static int _elm_need_web = 0;
1029#endif
1030
1031void
1032_elm_unneed_web(void)
1033{
1034#ifdef HAVE_ELEMENTARY_WEB
1035 if (--_elm_need_web) return;
1036
1037 _elm_need_web = 0;
1038 ewk_shutdown();
1039#endif
1040}
1041
1042EAPI Eina_Bool
1043elm_need_web(void)
1044{
1045#ifdef HAVE_ELEMENTARY_WEB
1046 if (_elm_need_web++) return EINA_TRUE;
1047 ewk_init();
1048 return EINA_TRUE;
1049#else
1050 return EINA_FALSE;
1051#endif
1052}
1053
1054EAPI Evas_Object *
1055elm_web_add(Evas_Object *parent)
1056{
1057 Evas_Object *obj;
1058 Widget_Data *wd;
1059 Evas *e;
1060
1061 EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
1062
1063 wd = calloc(1, sizeof(Widget_Data));
1064 e = evas_object_evas_get(parent);
1065 if (!e)
1066 return NULL;
1067 obj = elm_widget_add(e);
1068 wd->self = obj;
1069
1070 if (!widtype)
1071 {
1072 widtype = eina_stringshare_add("web");
1073 elm_widget_type_register(&widtype);
1074 }
1075
1076 elm_widget_type_set(obj, widtype);
1077 elm_widget_sub_object_add(parent, obj);
1078 elm_widget_theme_hook_set(obj, _theme_hook);
1079 elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
1080 elm_widget_event_hook_set(obj, _event_hook);
1081 elm_widget_data_set(obj, wd);
1082 elm_widget_can_focus_set(obj, EINA_TRUE);
1083
1084#ifdef HAVE_ELEMENTARY_WEB
1085 wd->ewk_view = _view_add(obj);
1086 ewk_view_setting_user_agent_set(wd->ewk_view, ELM_WEB_USER_AGENT);
1087
1088 wd->input_method = ELM_WIN_KEYBOARD_OFF;
1089 evas_object_smart_callback_add(wd->ewk_view, "inputmethod,changed",
1090 _ewk_view_inputmethod_change_cb, wd);
1091 evas_object_smart_callback_add(wd->ewk_view, "load,started",
1092 _ewk_view_load_started_cb, wd);
1093 evas_object_smart_callback_add(wd->ewk_view, "popup,create",
1094 _ewk_view_popup_create_cb, wd);
1095 evas_object_smart_callback_add(wd->ewk_view, "load,finished",
1096 _ewk_view_load_finished_cb, wd);
1097 evas_object_smart_callback_add(wd->ewk_view, "viewport,changed",
1098 _ewk_view_viewport_changed_cb, wd);
1099 evas_object_smart_callback_add(wd->ewk_view, "view,resized",
1100 _ewk_view_resized_cb, wd);
1101
1102 elm_widget_resize_object_set(obj, wd->ewk_view);
1103
1104 wd->tab_propagate = EINA_FALSE;
1105 wd->inwin_mode = _elm_config->inwin_dialogs_enable;
1106 wd->zoom.min = ewk_view_zoom_range_min_get(wd->ewk_view);
1107 wd->zoom.max = ewk_view_zoom_range_max_get(wd->ewk_view);
1108 wd->zoom.current = 1.0;
1109
1110 _view_smart_callback_proxy(wd->ewk_view, wd->self);
1111 evas_object_smart_callbacks_descriptions_set(obj, _elm_web_callback_names);
1112
1113 _theme_hook(obj);
1114
1115#else
1116 wd->label = elm_label_add(obj);
1117 elm_object_text_set(wd->label, "WebKit not supported!");
1118 evas_object_show(wd->label);
1119 elm_widget_resize_object_set(obj, wd->label);
1120#endif
1121
1122 return obj;
1123}
1124
1125EAPI Evas_Object *
1126elm_web_webkit_view_get(const Evas_Object *obj)
1127{
1128 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1129#ifdef HAVE_ELEMENTARY_WEB
1130 Widget_Data *wd = elm_widget_data_get(obj);
1131 if (!wd) return NULL;
1132 return wd->ewk_view;
1133#else
1134 ERR("Elementary not compiled with EWebKit support.");
1135 return NULL;
1136#endif
1137}
1138
1139EAPI void
1140elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data)
1141{
1142 ELM_CHECK_WIDTYPE(obj, widtype);
1143#ifdef HAVE_ELEMENTARY_WEB
1144 Widget_Data *wd = elm_widget_data_get(obj);
1145 if (!wd) return;
1146 wd->hook.window_create = func;
1147 wd->hook.window_create_data = data;
1148#else
1149 (void)func;
1150 (void)data;
1151#endif
1152}
1153
1154EAPI void
1155elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data)
1156{
1157 ELM_CHECK_WIDTYPE(obj, widtype);
1158#ifdef HAVE_ELEMENTARY_WEB
1159 Widget_Data *wd = elm_widget_data_get(obj);
1160 if (!wd) return;
1161 wd->hook.alert = func;
1162 wd->hook.alert_data = data;
1163#else
1164 (void)func;
1165 (void)data;
1166#endif
1167}
1168
1169EAPI void
1170elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data)
1171{
1172 ELM_CHECK_WIDTYPE(obj, widtype);
1173#ifdef HAVE_ELEMENTARY_WEB
1174 Widget_Data *wd = elm_widget_data_get(obj);
1175 if (!wd) return;
1176 wd->hook.confirm = func;
1177 wd->hook.confirm_data = data;
1178#else
1179 (void)func;
1180 (void)data;
1181#endif
1182}
1183
1184EAPI void
1185elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data)
1186{
1187 ELM_CHECK_WIDTYPE(obj, widtype);
1188#ifdef HAVE_ELEMENTARY_WEB
1189 Widget_Data *wd = elm_widget_data_get(obj);
1190 if (!wd) return;
1191 wd->hook.prompt = func;
1192 wd->hook.prompt_data = data;
1193#else
1194 (void)func;
1195 (void)data;
1196#endif
1197}
1198
1199EAPI void
1200elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data)
1201{
1202 ELM_CHECK_WIDTYPE(obj, widtype);
1203#ifdef HAVE_ELEMENTARY_WEB
1204 Widget_Data *wd = elm_widget_data_get(obj);
1205 if (!wd) return;
1206 wd->hook.file_selector = func;
1207 wd->hook.file_selector_data = data;
1208#else
1209 (void)func;
1210 (void)data;
1211#endif
1212}
1213
1214EAPI void
1215elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data)
1216{
1217 ELM_CHECK_WIDTYPE(obj, widtype);
1218#ifdef HAVE_ELEMENTARY_WEB
1219 Widget_Data *wd = elm_widget_data_get(obj);
1220 if (!wd) return;
1221 wd->hook.console_message = func;
1222 wd->hook.console_message_data = data;
1223#else
1224 (void)func;
1225 (void)data;
1226#endif
1227}
1228
1229EAPI void
1230elm_web_useragent_set(Evas_Object *obj, const char *user_agent)
1231{
1232 ELM_CHECK_WIDTYPE(obj, widtype);
1233#ifdef HAVE_ELEMENTARY_WEB
1234 Widget_Data *wd = elm_widget_data_get(obj);
1235 if (!wd) return;
1236 ewk_view_setting_user_agent_set(wd->ewk_view, user_agent);
1237#else
1238 (void)user_agent;
1239#endif
1240}
1241
1242EAPI const char*
1243elm_web_useragent_get(const Evas_Object *obj)
1244{
1245 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1246#ifdef HAVE_ELEMENTARY_WEB
1247 Widget_Data *wd = elm_widget_data_get(obj);
1248 if (!wd) return NULL;
1249 return ewk_view_setting_user_agent_get(wd->ewk_view);
1250#else
1251 return NULL;
1252#endif
1253}
1254
1255EAPI Eina_Bool
1256elm_web_tab_propagate_get(const Evas_Object *obj)
1257{
1258 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1259#ifdef HAVE_ELEMENTARY_WEB
1260 Widget_Data *wd = elm_widget_data_get(obj);
1261 if (!wd) return EINA_FALSE;
1262 return wd->tab_propagate;
1263#else
1264 return EINA_FALSE;
1265#endif
1266}
1267
1268EAPI void
1269elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate)
1270{
1271 ELM_CHECK_WIDTYPE(obj, widtype);
1272#ifdef HAVE_ELEMENTARY_WEB
1273 Widget_Data *wd = elm_widget_data_get(obj);
1274 if (!wd) return;
1275 wd->tab_propagate = propagate;
1276#else
1277 (void)propagate;
1278#endif
1279}
1280
1281EAPI Eina_Bool
1282elm_web_uri_set(Evas_Object *obj, const char *uri)
1283{
1284 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1285#ifdef HAVE_ELEMENTARY_WEB
1286 Widget_Data *wd = elm_widget_data_get(obj);
1287 if (!wd) return EINA_FALSE;
1288 return ewk_view_uri_set(wd->ewk_view, uri);
1289#else
1290 (void)uri;
1291 return EINA_FALSE;
1292#endif
1293}
1294
1295EAPI const char *
1296elm_web_uri_get(const Evas_Object *obj)
1297{
1298 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1299#ifdef HAVE_ELEMENTARY_WEB
1300 Widget_Data *wd = elm_widget_data_get(obj);
1301 if (!wd) return NULL;
1302 return ewk_view_uri_get(wd->ewk_view);
1303#else
1304 return NULL;
1305#endif
1306}
1307
1308EAPI const char *
1309elm_web_title_get(const Evas_Object *obj)
1310{
1311 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1312#ifdef HAVE_ELEMENTARY_WEB
1313 Widget_Data *wd = elm_widget_data_get(obj);
1314 if (!wd) return NULL;
1315 return ewk_view_title_get(wd->ewk_view);
1316#else
1317 return NULL;
1318#endif
1319}
1320
1321EAPI void
1322elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a)
1323{
1324 ELM_CHECK_WIDTYPE(obj, widtype);
1325#ifdef HAVE_ELEMENTARY_WEB
1326 Widget_Data *wd = elm_widget_data_get(obj);
1327 if (!wd) return;
1328 ewk_view_bg_color_set(wd->ewk_view, r, g, b, a);
1329#else
1330 (void)r;
1331 (void)g;
1332 (void)b;
1333 (void)a;
1334#endif
1335}
1336
1337EAPI void
1338elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1339{
1340 if (r) *r = 0;
1341 if (g) *g = 0;
1342 if (b) *b = 0;
1343 if (a) *a = 0;
1344 ELM_CHECK_WIDTYPE(obj, widtype);
1345#ifdef HAVE_ELEMENTARY_WEB
1346 Widget_Data *wd = elm_widget_data_get(obj);
1347 if (!wd) return;
1348 return ewk_view_bg_color_get(wd->ewk_view, r, g, b, a);
1349#endif
1350}
1351
1352EAPI char *
1353elm_web_selection_get(const Evas_Object *obj)
1354{
1355 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
1356#ifdef HAVE_ELEMENTARY_WEB
1357 Widget_Data *wd = elm_widget_data_get(obj);
1358 if (!wd) return NULL;
1359 return ewk_view_selection_get(wd->ewk_view);
1360#else
1361 return NULL;
1362#endif
1363}
1364
1365EAPI void
1366elm_web_popup_selected_set(Evas_Object *obj, int idx)
1367{
1368 ELM_CHECK_WIDTYPE(obj, widtype);
1369#ifdef HAVE_ELEMENTARY_WEB
1370 Widget_Data *wd = elm_widget_data_get(obj);
1371 ewk_view_popup_selected_set(wd->ewk_view, idx);
1372#else
1373 (void)idx;
1374#endif
1375}
1376
1377EAPI Eina_Bool
1378elm_web_popup_destroy(Evas_Object *obj)
1379{
1380 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1381#ifdef HAVE_ELEMENTARY_WEB
1382 Widget_Data *wd = elm_widget_data_get(obj);
1383 return ewk_view_popup_destroy(wd->ewk_view);
1384#else
1385 return EINA_FALSE;
1386#endif
1387}
1388
1389EAPI Eina_Bool
1390elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap)
1391{
1392 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1393#ifdef HAVE_ELEMENTARY_WEB
1394 Widget_Data *wd = elm_widget_data_get(obj);
1395 if (!wd) return EINA_FALSE;
1396 return ewk_view_text_search
1397 (wd->ewk_view, string, case_sensitive, forward, wrap);
1398#else
1399 (void)string;
1400 (void)case_sensitive;
1401 (void)forward;
1402 (void)wrap;
1403 return EINA_FALSE;
1404#endif
1405}
1406
1407EAPI unsigned int
1408elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit)
1409{
1410 ELM_CHECK_WIDTYPE(obj, widtype) 0;
1411#ifdef HAVE_ELEMENTARY_WEB
1412 Widget_Data *wd = elm_widget_data_get(obj);
1413 if (!wd) return 0;
1414 return ewk_view_text_matches_mark
1415 (wd->ewk_view, string, case_sensitive, highlight, limit);
1416#else
1417 (void)string;
1418 (void)case_sensitive;
1419 (void)highlight;
1420 (void)limit;
1421 return 0;
1422#endif
1423}
1424
1425EAPI Eina_Bool
1426elm_web_text_matches_unmark_all(Evas_Object *obj)
1427{
1428 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1429#ifdef HAVE_ELEMENTARY_WEB
1430 Widget_Data *wd = elm_widget_data_get(obj);
1431 if (!wd) return EINA_FALSE;
1432 return ewk_view_text_matches_unmark_all(wd->ewk_view);
1433#else
1434 return EINA_FALSE;
1435#endif
1436}
1437
1438EAPI Eina_Bool
1439elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight)
1440{
1441 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1442#ifdef HAVE_ELEMENTARY_WEB
1443 Widget_Data *wd = elm_widget_data_get(obj);
1444 if (!wd) return EINA_FALSE;
1445 return ewk_view_text_matches_highlight_set(wd->ewk_view, highlight);
1446#else
1447 (void)highlight;
1448 return EINA_FALSE;
1449#endif
1450}
1451
1452EAPI Eina_Bool
1453elm_web_text_matches_highlight_get(const Evas_Object *obj)
1454{
1455 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1456#ifdef HAVE_ELEMENTARY_WEB
1457 Widget_Data *wd = elm_widget_data_get(obj);
1458 if (!wd) return EINA_FALSE;
1459 return ewk_view_text_matches_highlight_get(wd->ewk_view);
1460#else
1461 return EINA_FALSE;
1462#endif
1463}
1464
1465EAPI double
1466elm_web_load_progress_get(const Evas_Object *obj)
1467{
1468 ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
1469#ifdef HAVE_ELEMENTARY_WEB
1470 Widget_Data *wd = elm_widget_data_get(obj);
1471 if (!wd) return -1.0;
1472 return ewk_view_load_progress_get(wd->ewk_view);
1473#else
1474 return EINA_FALSE;
1475#endif
1476}
1477
1478EAPI Eina_Bool
1479elm_web_stop(Evas_Object *obj)
1480{
1481 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1482#ifdef HAVE_ELEMENTARY_WEB
1483 Widget_Data *wd = elm_widget_data_get(obj);
1484 if (!wd) return EINA_FALSE;
1485 return ewk_view_stop(wd->ewk_view);
1486#else
1487 return EINA_FALSE;
1488#endif
1489}
1490
1491EAPI Eina_Bool
1492elm_web_reload(Evas_Object *obj)
1493{
1494 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1495#ifdef HAVE_ELEMENTARY_WEB
1496 Widget_Data *wd = elm_widget_data_get(obj);
1497 if (!wd) return EINA_FALSE;
1498 return ewk_view_reload(wd->ewk_view);
1499#else
1500 return EINA_FALSE;
1501#endif
1502}
1503
1504EAPI Eina_Bool
1505elm_web_reload_full(Evas_Object *obj)
1506{
1507 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1508#ifdef HAVE_ELEMENTARY_WEB
1509 Widget_Data *wd = elm_widget_data_get(obj);
1510 if (!wd) return EINA_FALSE;
1511 return ewk_view_reload_full(wd->ewk_view);
1512#else
1513 return EINA_FALSE;
1514#endif
1515}
1516
1517
1518EAPI Eina_Bool
1519elm_web_back(Evas_Object *obj)
1520{
1521 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1522#ifdef HAVE_ELEMENTARY_WEB
1523 Widget_Data *wd = elm_widget_data_get(obj);
1524 if (!wd) return EINA_FALSE;
1525 return ewk_view_back(wd->ewk_view);
1526#else
1527 return EINA_FALSE;
1528#endif
1529}
1530
1531EAPI Eina_Bool
1532elm_web_forward(Evas_Object *obj)
1533{
1534 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1535#ifdef HAVE_ELEMENTARY_WEB
1536 Widget_Data *wd = elm_widget_data_get(obj);
1537 if (!wd) return EINA_FALSE;
1538 return ewk_view_forward(wd->ewk_view);
1539#else
1540 return EINA_FALSE;
1541#endif
1542}
1543
1544EAPI Eina_Bool
1545elm_web_navigate(Evas_Object *obj, int steps)
1546{
1547 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1548#ifdef HAVE_ELEMENTARY_WEB
1549 Widget_Data *wd = elm_widget_data_get(obj);
1550 if (!wd) return EINA_FALSE;
1551 return ewk_view_navigate(wd->ewk_view, steps);
1552#else
1553 return EINA_FALSE;
1554 (void)steps;
1555#endif
1556}
1557
1558EINA_DEPRECATED EAPI Eina_Bool
1559elm_web_back_possible(Evas_Object *obj)
1560{
1561 return elm_web_back_possible_get(obj);
1562}
1563
1564EAPI Eina_Bool
1565elm_web_back_possible_get(Evas_Object *obj)
1566{
1567 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1568#ifdef HAVE_ELEMENTARY_WEB
1569 Widget_Data *wd = elm_widget_data_get(obj);
1570 if (!wd) return EINA_FALSE;
1571 return ewk_view_back_possible(wd->ewk_view);
1572#else
1573 return EINA_FALSE;
1574#endif
1575}
1576
1577EAPI Eina_Bool
1578elm_web_forward_possible_get(Evas_Object *obj)
1579{
1580 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1581#ifdef HAVE_ELEMENTARY_WEB
1582 Widget_Data *wd = elm_widget_data_get(obj);
1583 if (!wd) return EINA_FALSE;
1584 return ewk_view_forward_possible(wd->ewk_view);
1585#else
1586 return EINA_FALSE;
1587#endif
1588}
1589
1590EAPI Eina_Bool
1591elm_web_navigate_possible_get(Evas_Object *obj, int steps)
1592{
1593 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1594#ifdef HAVE_ELEMENTARY_WEB
1595 Widget_Data *wd = elm_widget_data_get(obj);
1596 if (!wd) return EINA_FALSE;
1597 return ewk_view_navigate_possible(wd->ewk_view, steps);
1598#else
1599 return EINA_FALSE;
1600 (void)steps;
1601#endif
1602}
1603
1604EAPI Eina_Bool
1605elm_web_history_enabled_get(const Evas_Object *obj)
1606{
1607 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1608#ifdef HAVE_ELEMENTARY_WEB
1609 Widget_Data *wd = elm_widget_data_get(obj);
1610 if (!wd) return EINA_FALSE;
1611 return ewk_view_history_enable_get(wd->ewk_view);
1612#else
1613 return EINA_FALSE;
1614#endif
1615}
1616
1617EAPI void
1618elm_web_history_enabled_set(Evas_Object *obj, Eina_Bool enable)
1619{
1620 ELM_CHECK_WIDTYPE(obj, widtype);
1621#ifdef HAVE_ELEMENTARY_WEB
1622 Widget_Data *wd = elm_widget_data_get(obj);
1623 if (!wd) return;
1624 ewk_view_history_enable_set(wd->ewk_view, enable);
1625#else
1626 (void)enable;
1627#endif
1628}
1629
1630//EAPI Ewk_History *ewk_view_history_get(const Evas_Object *obj); // TODO:
1631
1632EAPI void
1633elm_web_zoom_set(Evas_Object *obj, double zoom)
1634{
1635 ELM_CHECK_WIDTYPE(obj, widtype);
1636#ifdef HAVE_ELEMENTARY_WEB
1637 Widget_Data *wd = elm_widget_data_get(obj);
1638 int vw, vh, cx, cy;
1639 float z = 1.0;
1640 evas_object_geometry_get(wd->ewk_view, NULL, NULL, &vw, &vh);
1641 cx = vw / 2;
1642 cy = vh / 2;
1643 if (zoom > wd->zoom.max)
1644 zoom = wd->zoom.max;
1645 else if (zoom < wd->zoom.min)
1646 zoom = wd->zoom.min;
1647 if (zoom == wd->zoom.current) return;
1648 wd->zoom.current = zoom;
1649 if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_MANUAL)
1650 z = zoom;
1651 else if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_AUTO_FIT)
1652 {
1653 Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
1654 Evas_Coord fw, fh, pw, ph;
1655 if (!ewk_frame_contents_size_get(frame, &fw, &fh))
1656 return;
1657 z = ewk_frame_page_zoom_get(frame);
1658 fw /= z;
1659 fh /= z;
1660 if ((fw > 0) && (fh > 0))
1661 {
1662 ph = (fh * vw) / fw;
1663 if (ph > vh)
1664 {
1665 pw = (fw * vh) / fh;
1666 ph = vh;
1667 }
1668 else
1669 pw = vw;
1670 if (fw > fh)
1671 z = (float)pw / fw;
1672 else
1673 z = (float)ph / fh;
1674 }
1675 }
1676 else if (wd->zoom.mode == ELM_WEB_ZOOM_MODE_AUTO_FILL)
1677 {
1678 Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
1679 Evas_Coord fw, fh, pw, ph;
1680 if (!ewk_frame_contents_size_get(frame, &fw, &fh))
1681 return;
1682 z = ewk_frame_page_zoom_get(frame);
1683 fw /= z;
1684 fh /= z;
1685 if ((fw > 0) && (fh > 0))
1686 {
1687 ph = (fh * vw) / fw;
1688 if (ph < vh)
1689 {
1690 pw = (fw * vh) / fh;
1691 ph = vh;
1692 }
1693 else
1694 pw = vw;
1695 if (fw > fh)
1696 z = (float)pw / fw;
1697 else
1698 z = (float)ph / fh;
1699 }
1700 }
1701 if (wd->zoom.no_anim)
1702 ewk_view_zoom_set(wd->ewk_view, z, cx, cy);
1703 else
1704 ewk_view_zoom_animated_set(wd->ewk_view, z, _elm_config->zoom_friction,
1705 cx, cy);
1706 wd->zoom.no_anim = EINA_FALSE;
1707#else
1708 (void)zoom;
1709#endif
1710}
1711
1712EAPI double
1713elm_web_zoom_get(const Evas_Object *obj)
1714{
1715 ELM_CHECK_WIDTYPE(obj, widtype) -1.0;
1716#ifdef HAVE_ELEMENTARY_WEB
1717 Widget_Data *wd = elm_widget_data_get(obj);
1718 return wd->zoom.current;
1719#else
1720 return -1.0;
1721#endif
1722}
1723
1724EAPI void
1725elm_web_zoom_mode_set(Evas_Object *obj, Elm_Web_Zoom_Mode mode)
1726{
1727 ELM_CHECK_WIDTYPE(obj, widtype);
1728#ifdef HAVE_ELEMENTARY_WEB
1729 Widget_Data *wd = elm_widget_data_get(obj);
1730 float tz;
1731 if (mode >= ELM_WEB_ZOOM_MODE_LAST)
1732 return;
1733 if (mode == wd->zoom.mode)
1734 return;
1735 wd->zoom.mode = mode;
1736 tz = wd->zoom.current;
1737 wd->zoom.current = 0.0;
1738 elm_web_zoom_set(obj, tz);
1739#else
1740 (void)mode;
1741#endif
1742}
1743
1744EAPI Elm_Web_Zoom_Mode
1745elm_web_zoom_mode_get(const Evas_Object *obj)
1746{
1747 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WEB_ZOOM_MODE_LAST;
1748#ifdef HAVE_ELEMENTARY_WEB
1749 Widget_Data *wd = elm_widget_data_get(obj);
1750 return wd->zoom.mode;
1751#else
1752 return ELM_WEB_ZOOM_MODE_LAST;
1753#endif
1754}
1755
1756EAPI void
1757elm_web_region_show(Evas_Object *obj, int x, int y, int w __UNUSED__, int h __UNUSED__)
1758{
1759 ELM_CHECK_WIDTYPE(obj, widtype);
1760#ifdef HAVE_ELEMENTARY_WEB
1761 Widget_Data *wd = elm_widget_data_get(obj);
1762 Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
1763 int fw, fh, zw, zh, rx, ry;
1764 float zoom;
1765 ewk_frame_contents_size_get(frame, &fw, &fh);
1766 zoom = ewk_frame_page_zoom_get(frame);
1767 zw = fw / zoom;
1768 zh = fh / zoom;
1769 rx = (x * fw) / zw;
1770 ry = (y * fh) / zh;
1771 if (wd->bring_in.animator)
1772 {
1773 ecore_animator_del(wd->bring_in.animator);
1774 wd->bring_in.animator = NULL;
1775 }
1776 ewk_frame_scroll_set(frame, rx, ry);
1777#else
1778 (void)x;
1779 (void)y;
1780#endif
1781}
1782
1783EAPI void
1784elm_web_region_bring_in(Evas_Object *obj, int x, int y, int w __UNUSED__, int h __UNUSED__)
1785{
1786 ELM_CHECK_WIDTYPE(obj, widtype);
1787#ifdef HAVE_ELEMENTARY_WEB
1788 Widget_Data *wd = elm_widget_data_get(obj);
1789 Evas_Object *frame = ewk_view_frame_main_get(wd->ewk_view);
1790 int fw, fh, zw, zh, rx, ry, sx, sy;
1791 float zoom;
1792 ewk_frame_contents_size_get(frame, &fw, &fh);
1793 ewk_frame_scroll_pos_get(frame, &sx, &sy);
1794 zoom = ewk_frame_page_zoom_get(frame);
1795 zw = fw / zoom;
1796 zh = fh / zoom;
1797 rx = (x * fw) / zw;
1798 ry = (y * fh) / zh;
1799 if ((wd->bring_in.end.x == rx) && (wd->bring_in.end.y == ry))
1800 return;
1801 wd->bring_in.start.x = sx;
1802 wd->bring_in.start.y = sy;
1803 wd->bring_in.end.x = rx;
1804 wd->bring_in.end.y = ry;
1805 if (wd->bring_in.animator)
1806 ecore_animator_del(wd->bring_in.animator);
1807 wd->bring_in.animator = ecore_animator_timeline_add(
1808 _elm_config->bring_in_scroll_friction, _bring_in_anim_cb, wd);
1809#else
1810 (void)x;
1811 (void)y;
1812#endif
1813}
1814
1815EAPI void
1816elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value)
1817{
1818 ELM_CHECK_WIDTYPE(obj, widtype);
1819#ifdef HAVE_ELEMENTARY_WEB
1820 Widget_Data *wd = elm_widget_data_get(obj);
1821
1822 wd->inwin_mode = value;
1823#else
1824 (void)value;
1825#endif
1826}
1827
1828EAPI Eina_Bool
1829elm_web_inwin_mode_get(const Evas_Object *obj)
1830{
1831 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
1832#ifdef HAVE_ELEMENTARY_WEB
1833 Widget_Data *wd = elm_widget_data_get(obj);
1834
1835 return wd->inwin_mode;
1836#else
1837 return EINA_FALSE;
1838#endif
1839}
1840
1841EAPI void
1842elm_web_window_features_ref(Elm_Web_Window_Features *wf)
1843{
1844#ifdef HAVE_ELEMENTARY_WEB
1845 ewk_window_features_ref((Ewk_Window_Features *)wf);
1846#else
1847 (void)wf;
1848#endif
1849}
1850
1851EAPI void
1852elm_web_window_features_unref(Elm_Web_Window_Features *wf)
1853{
1854#ifdef HAVE_ELEMENTARY_WEB
1855 ewk_window_features_unref((Ewk_Window_Features *)wf);
1856#else
1857 (void)wf;
1858#endif
1859}
1860
1861EAPI Eina_Bool
1862elm_web_window_features_property_get(const Elm_Web_Window_Features *wf, Elm_Web_Window_Feature_Flag flag)
1863{
1864#ifdef HAVE_ELEMENTARY_WEB
1865 Eina_Bool toolbar_visible, statusbar_visible;
1866 Eina_Bool scrollbars_visible, menubar_visible;
1867 Eina_Bool locationbar_visible, fullscreen;
1868
1869 ewk_window_features_bool_property_get((const Ewk_Window_Features *)wf,
1870 &toolbar_visible, &statusbar_visible,
1871 &scrollbars_visible, &menubar_visible,
1872 &locationbar_visible, &fullscreen);
1873
1874 //TODO : Improve ewk API usage to get one value.
1875 //
1876 switch(flag)
1877 {
1878 case ELM_WEB_WINDOW_FEATURE_TOOLBAR:
1879 return toolbar_visible;
1880 break;
1881 case ELM_WEB_WINDOW_FEATURE_STATUSBAR:
1882 return statusbar_visible;
1883 break;
1884 case ELM_WEB_WINDOW_FEATURE_SCROLLBARS:
1885 return scrollbars_visible;
1886 break;
1887 case ELM_WEB_WINDOW_FEATURE_MENUBAR:
1888 return menubar_visible;
1889 break;
1890 case ELM_WEB_WINDOW_FEATURE_LOCATIONBAR:
1891 return locationbar_visible;
1892 break;
1893 case ELM_WEB_WINDOW_FEATURE_FULLSCREEN:
1894 return fullscreen;
1895 break;
1896 }
1897#else
1898
1899 if (!wf) return EINA_FALSE;
1900 if (flag==ELM_WEB_WINDOW_FEATURE_TOOLBAR)
1901 {
1902 //TODO Handle unused variable warnings when
1903 //ewk is not installed.
1904 }
1905
1906 /* What to do with these ?
1907
1908 (void)wf;
1909 (void)toolbar_visible;
1910 (void)statusbar_visible;
1911 (void)scrollbars_visible;
1912 (void)menubar_visible;
1913 (void)locationbar_visible;
1914 (void)fullscreen;
1915
1916 */
1917
1918#endif
1919 return EINA_FALSE;
1920}
1921
1922EAPI void
1923elm_web_window_features_region_get(const Elm_Web_Window_Features *wf, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
1924{
1925#ifdef HAVE_ELEMENTARY_WEB
1926 ewk_window_features_int_property_get((const Ewk_Window_Features *)wf,
1927 x, y, w, h);
1928#else
1929
1930 if (!wf || !x || !y || !w || !h) return;
1931 /* What to do with these ?
1932
1933 (void)wf;
1934 (void)x;
1935 (void)y;
1936 (void)w;
1937 (void)h;
1938
1939 */
1940
1941#endif
1942}
1943
1944// TODO: use all ewk_view_zoom stuff to implement bring-in and animated zoom like elm_photocam. Should be simple to use, must not expose every single bit to users!
diff --git a/libraries/elementary/src/lib/elm_web.h b/libraries/elementary/src/lib/elm_web.h
new file mode 100644
index 0000000..b465906
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_web.h
@@ -0,0 +1,1060 @@
1/**
2 * @defgroup Web Web
3 * @ingroup Elementary
4 *
5 * @image html img/widget/web/preview-00.png
6 * @image latex img/widget/web/preview-00.eps
7 *
8 * A web widget is used for displaying web pages (HTML/CSS/JS)
9 * using WebKit-EFL. You must have compiled Elementary with
10 * ewebkit support.
11 *
12 * Signals that you can add callbacks for are:
13 * @li "download,request": A file download has been requested. Event info is
14 * a pointer to a Elm_Web_Download
15 * @li "editorclient,contents,changed": Editor client's contents changed
16 * @li "editorclient,selection,changed": Editor client's selection changed
17 * @li "frame,created": A new frame was created. Event info is an
18 * Evas_Object which can be handled with WebKit's ewk_frame API
19 * @li "icon,received": An icon was received by the main frame
20 * @li "inputmethod,changed": Input method changed. Event info is an
21 * Eina_Bool indicating whether it's enabled or not
22 * @li "js,windowobject,clear": JS window object has been cleared
23 * @li "link,hover,in": Mouse cursor is hovering over a link. Event info
24 * is a char *link[2], where the first string contains the URL the link
25 * points to, and the second one the title of the link
26 * @li "link,hover,out": Mouse cursor left the link
27 * @li "load,document,finished": Loading of a document finished. Event info
28 * is the frame that finished loading
29 * @li "load,error": Load failed. Event info is a pointer to
30 * Elm_Web_Frame_Load_Error
31 * @li "load,finished": Load finished. Event info is NULL on success, on
32 * error it's a pointer to Elm_Web_Frame_Load_Error
33 * @li "load,newwindow,show": A new window was created and is ready to be
34 * shown
35 * @li "load,progress": Overall load progress. Event info is a pointer to
36 * a double containing a value between 0.0 and 1.0
37 * @li "load,provisional": Started provisional load
38 * @li "load,started": Loading of a document started
39 * @li "menubar,visible,get": Queries if the menubar is visible. Event info
40 * is a pointer to Eina_Bool where the callback should set EINA_TRUE if
41 * the menubar is visible, or EINA_FALSE in case it's not
42 * @li "menubar,visible,set": Informs menubar visibility. Event info is
43 * an Eina_Bool indicating the visibility
44 * @li "popup,created": A dropdown widget was activated, requesting its
45 * popup menu to be created. Event info is a pointer to Elm_Web_Menu
46 * @li "popup,willdelete": The web object is ready to destroy the popup
47 * object created. Event info is a pointer to Elm_Web_Menu
48 * @li "ready": Page is fully loaded
49 * @li "scrollbars,visible,get": Queries visibility of scrollbars. Event
50 * info is a pointer to Eina_Bool where the visibility state should be set
51 * @li "scrollbars,visible,set": Informs scrollbars visibility. Event info
52 * is an Eina_Bool with the visibility state set
53 * @li "statusbar,text,set": Text of the statusbar changed. Even info is
54 * a string with the new text
55 * @li "statusbar,visible,get": Queries visibility of the status bar.
56 * Event info is a pointer to Eina_Bool where the visibility state should be
57 * set.
58 * @li "statusbar,visible,set": Informs statusbar visibility. Event info is
59 * an Eina_Bool with the visibility value
60 * @li "title,changed": Title of the main frame changed. Event info is a
61 * string with the new title
62 * @li "toolbars,visible,get": Queries visibility of toolbars. Event info
63 * is a pointer to Eina_Bool where the visibility state should be set
64 * @li "toolbars,visible,set": Informs the visibility of toolbars. Event
65 * info is an Eina_Bool with the visibility state
66 * @li "tooltip,text,set": Show and set text of a tooltip. Event info is
67 * a string with the text to show
68 * @li "uri,changed": URI of the main frame changed. Event info is a string
69 * with the new URI
70 * @li "view,resized": The web object internal's view changed sized
71 * @li "windows,close,request": A JavaScript request to close the current
72 * window was requested
73 * @li "zoom,animated,end": Animated zoom finished
74 *
75 * available styles:
76 * - default
77 *
78 * An example of use of web:
79 *
80 * - @ref web_example_01 TBD
81 */
82
83/**
84 * @addtogroup Web
85 * @{
86 */
87
88/**
89 * Structure used to report load errors.
90 *
91 * Load errors are reported as signal by elm_web. All the strings are
92 * temporary references and should @b not be used after the signal
93 * callback returns. If it's required, make copies with strdup() or
94 * eina_stringshare_add() (they are not even guaranteed to be
95 * stringshared, so must use eina_stringshare_add() and not
96 * eina_stringshare_ref()).
97 */
98typedef struct _Elm_Web_Frame_Load_Error Elm_Web_Frame_Load_Error;
99
100/**
101 * Structure used to report load errors.
102 *
103 * Load errors are reported as signal by elm_web. All the strings are
104 * temporary references and should @b not be used after the signal
105 * callback returns. If it's required, make copies with strdup() or
106 * eina_stringshare_add() (they are not even guaranteed to be
107 * stringshared, so must use eina_stringshare_add() and not
108 * eina_stringshare_ref()).
109 */
110struct _Elm_Web_Frame_Load_Error
111{
112 int code; /**< Numeric error code */
113 Eina_Bool is_cancellation; /**< Error produced by canceling a request */
114 const char *domain; /**< Error domain name */
115 const char *description; /**< Error description (already localized) */
116 const char *failing_url; /**< The URL that failed to load */
117 Evas_Object *frame; /**< Frame object that produced the error */
118};
119
120/**
121 * The possibles types that the items in a menu can be
122 */
123typedef enum
124{
125 ELM_WEB_MENU_SEPARATOR,
126 ELM_WEB_MENU_GROUP,
127 ELM_WEB_MENU_OPTION
128} Elm_Web_Menu_Item_Type;
129
130/**
131 * Structure describing the items in a menu
132 */
133typedef struct _Elm_Web_Menu_Item Elm_Web_Menu_Item;
134
135/**
136 * Structure describing the items in a menu
137 */
138struct _Elm_Web_Menu_Item
139{
140 const char *text; /**< The text for the item */
141 Elm_Web_Menu_Item_Type type; /**< The type of the item */
142};
143
144/**
145 * Structure describing the menu of a popup
146 *
147 * This structure will be passed as the @c event_info for the "popup,create"
148 * signal, which is emitted when a dropdown menu is opened. Users wanting
149 * to handle these popups by themselves should listen to this signal and
150 * set the @c handled property of the struct to @c EINA_TRUE. Leaving this
151 * property as @c EINA_FALSE means that the user will not handle the popup
152 * and the default implementation will be used.
153 *
154 * When the popup is ready to be dismissed, a "popup,willdelete" signal
155 * will be emitted to notify the user that it can destroy any objects and
156 * free all data related to it.
157 *
158 * @see elm_web_popup_selected_set()
159 * @see elm_web_popup_destroy()
160 *
161 * @ingroup Web
162 */
163typedef struct _Elm_Web_Menu Elm_Web_Menu;
164
165/**
166 * Structure describing the menu of a popup
167 *
168 * This structure will be passed as the @c event_info for the "popup,create"
169 * signal, which is emitted when a dropdown menu is opened. Users wanting
170 * to handle these popups by themselves should listen to this signal and
171 * set the @c handled property of the struct to @c EINA_TRUE. Leaving this
172 * property as @c EINA_FALSE means that the user will not handle the popup
173 * and the default implementation will be used.
174 *
175 * When the popup is ready to be dismissed, a "popup,willdelete" signal
176 * will be emitted to notify the user that it can destroy any objects and
177 * free all data related to it.
178 *
179 * @see elm_web_popup_selected_set()
180 * @see elm_web_popup_destroy()
181 *
182 * @ingroup Web
183 */
184struct _Elm_Web_Menu
185{
186 Eina_List *items; /**< List of #Elm_Web_Menu_Item */
187 int x; /**< The X position of the popup, relative to the elm_web object */
188 int y; /**< The Y position of the popup, relative to the elm_web object */
189 int width; /**< Width of the popup menu */
190 int height; /**< Height of the popup menu */
191
192 Eina_Bool handled : 1; /**< Set to @c EINA_TRUE by the user to indicate that the popup has been handled and the default implementation should be ignored. Leave as @c EINA_FALSE otherwise. */
193};
194
195typedef struct _Elm_Web_Download Elm_Web_Download;
196struct _Elm_Web_Download
197{
198 const char *url;
199};
200
201/**
202 * Types of zoom available.
203 */
204typedef enum
205{
206 ELM_WEB_ZOOM_MODE_MANUAL = 0, /**< Zoom controlled normally by elm_web_zoom_set */
207 ELM_WEB_ZOOM_MODE_AUTO_FIT, /**< Zoom until content fits in web object */
208 ELM_WEB_ZOOM_MODE_AUTO_FILL, /**< Zoom until content fills web object */
209 ELM_WEB_ZOOM_MODE_LAST
210} Elm_Web_Zoom_Mode;
211
212/**
213 * Opaque handler containing the features (such as statusbar, menubar, etc)
214 * that are to be set on a newly requested window.
215 */
216typedef struct _Elm_Web_Window_Features Elm_Web_Window_Features;
217
218
219/**
220 * Definitions of web window features.
221 *
222 */
223typedef enum
224{
225 ELM_WEB_WINDOW_FEATURE_TOOLBAR,
226 ELM_WEB_WINDOW_FEATURE_STATUSBAR,
227 ELM_WEB_WINDOW_FEATURE_SCROLLBARS,
228 ELM_WEB_WINDOW_FEATURE_MENUBAR,
229 ELM_WEB_WINDOW_FEATURE_LOCATIONBAR,
230 ELM_WEB_WINDOW_FEATURE_FULLSCREEN
231} Elm_Web_Window_Feature_Flag;
232
233/**
234 * Callback type for the create_window hook.
235 *
236 * The function parameters are:
237 * @li @p data User data pointer set when setting the hook function
238 * @li @p obj The elm_web object requesting the new window
239 * @li @p js Set to @c EINA_TRUE if the request was originated from
240 * JavaScript. @c EINA_FALSE otherwise.
241 * @li @p window_features A pointer of #Elm_Web_Window_Features indicating
242 * the features requested for the new window.
243 *
244 * The returned value of the function should be the @c elm_web widget where
245 * the request will be loaded. That is, if a new window or tab is created,
246 * the elm_web widget in it should be returned, and @b NOT the window
247 * object.
248 * Returning @c NULL should cancel the request.
249 *
250 * @see elm_web_window_create_hook_set()
251 *
252 * @ingroup Web
253 */
254typedef Evas_Object *(*Elm_Web_Window_Open)(void *data, Evas_Object *obj, Eina_Bool js, const Elm_Web_Window_Features *window_features);
255
256/**
257 * Callback type for the JS alert hook.
258 *
259 * The function parameters are:
260 * @li @p data User data pointer set when setting the hook function
261 * @li @p obj The elm_web object requesting the new window
262 * @li @p message The message to show in the alert dialog
263 *
264 * The function should return the object representing the alert dialog.
265 * Elm_Web will run a second main loop to handle the dialog and normal
266 * flow of the application will be restored when the object is deleted, so
267 * the user should handle the popup properly in order to delete the object
268 * when the action is finished.
269 * If the function returns @c NULL the popup will be ignored.
270 *
271 * @see elm_web_dialog_alert_hook_set()
272 *
273 * @ingroup Web
274 */
275typedef Evas_Object *(*Elm_Web_Dialog_Alert)(void *data, Evas_Object *obj, const char *message);
276
277/**
278 * Callback type for the JS confirm hook.
279 *
280 * The function parameters are:
281 * @li @p data User data pointer set when setting the hook function
282 * @li @p obj The elm_web object requesting the new window
283 * @li @p message The message to show in the confirm dialog
284 * @li @p ret Pointer to store the user selection. @c EINA_TRUE if
285 * the user selected @c Ok, @c EINA_FALSE otherwise.
286 *
287 * The function should return the object representing the confirm dialog.
288 * Elm_Web will run a second main loop to handle the dialog and normal
289 * flow of the application will be restored when the object is deleted, so
290 * the user should handle the popup properly in order to delete the object
291 * when the action is finished.
292 * If the function returns @c NULL the popup will be ignored.
293 *
294 * @see elm_web_dialog_confirm_hook_set()
295 *
296 * @ingroup Web
297 */
298typedef Evas_Object *(*Elm_Web_Dialog_Confirm)(void *data, Evas_Object *obj, const char *message, Eina_Bool *ret);
299
300/**
301 * Callback type for the JS prompt hook.
302 *
303 * The function parameters are:
304 * @li @p data User data pointer set when setting the hook function
305 * @li @p obj The elm_web object requesting the new window
306 * @li @p message The message to show in the prompt dialog
307 * @li @p def_value The default value to present the user in the entry
308 * @li @p value Pointer to store the value given by the user. Must
309 * be a malloc'ed string or @c NULL if the user canceled the popup.
310 * @li @p ret Pointer to store the user selection. @c EINA_TRUE if
311 * the user selected @c Ok, @c EINA_FALSE otherwise.
312 *
313 * The function should return the object representing the prompt dialog.
314 * Elm_Web will run a second main loop to handle the dialog and normal
315 * flow of the application will be restored when the object is deleted, so
316 * the user should handle the popup properly in order to delete the object
317 * when the action is finished.
318 * If the function returns @c NULL the popup will be ignored.
319 *
320 * @see elm_web_dialog_prompt_hook_set()
321 *
322 * @ingroup Web
323 */
324typedef Evas_Object *(*Elm_Web_Dialog_Prompt)(void *data, Evas_Object *obj, const char *message, const char *def_value, char **value, Eina_Bool *ret);
325
326/**
327 * Callback type for the JS file selector hook.
328 *
329 * The function parameters are:
330 * @li @p data User data pointer set when setting the hook function
331 * @li @p obj The elm_web object requesting the new window
332 * @li @p allows_multiple @c EINA_TRUE if multiple files can be selected.
333 * @li @p accept_types Mime types accepted
334 * @li @p selected Pointer to store the list of malloc'ed strings
335 * containing the path to each file selected. Must be @c NULL if the file
336 * dialog is canceled
337 * @li @p ret Pointer to store the user selection. @c EINA_TRUE if
338 * the user selected @c Ok, @c EINA_FALSE otherwise.
339 *
340 * The function should return the object representing the file selector
341 * dialog.
342 * Elm_Web will run a second main loop to handle the dialog and normal
343 * flow of the application will be restored when the object is deleted, so
344 * the user should handle the popup properly in order to delete the object
345 * when the action is finished.
346 * If the function returns @c NULL the popup will be ignored.
347 *
348 * @see elm_web_dialog_file selector_hook_set()
349 *
350 * @ingroup Web
351 */
352typedef Evas_Object *(*Elm_Web_Dialog_File_Selector)(void *data, Evas_Object *obj, Eina_Bool allows_multiple, Eina_List *accept_types, Eina_List **selected, Eina_Bool *ret);
353
354/**
355 * Callback type for the JS console message hook.
356 *
357 * When a console message is added from JavaScript, any set function to the
358 * console message hook will be called for the user to handle. There is no
359 * default implementation of this hook.
360 *
361 * The function parameters are:
362 * @li @p data User data pointer set when setting the hook function
363 * @li @p obj The elm_web object that originated the message
364 * @li @p message The message sent
365 * @li @p line_number The line number
366 * @li @p source_id Source id
367 *
368 * @see elm_web_console_message_hook_set()
369 *
370 * @ingroup Web
371 */
372typedef void (*Elm_Web_Console_Message)(void *data, Evas_Object *obj, const char *message, unsigned int line_number, const char *source_id);
373
374/**
375 * Add a new web object to the parent.
376 *
377 * @param parent The parent object.
378 * @return The new object or NULL if it cannot be created.
379 *
380 * @see elm_web_uri_set()
381 * @see elm_web_webkit_view_get()
382 *
383 * @ingroup Web
384 */
385EAPI Evas_Object *elm_web_add(Evas_Object *parent);
386
387/**
388 * Change useragent of a elm_web object
389 *
390 * @param obj The object
391 * @param user_agent String for useragent
392 *
393 * @ingroup Web
394 */
395EAPI void elm_web_useragent_set(Evas_Object *obj, const char *user_agent);
396
397/**
398 * Return current useragent of elm_web object
399 *
400 * @param obj The object
401 * @return Useragent string
402 *
403 * @ingroup Web
404 */
405EAPI const char* elm_web_useragent_get(const Evas_Object *obj);
406
407/**
408 * Get internal ewk_view object from web object.
409 *
410 * Elementary may not provide some low level features of EWebKit,
411 * instead of cluttering the API with proxy methods we opted to
412 * return the internal reference. Be careful using it as it may
413 * interfere with elm_web behavior.
414 *
415 * @param obj The web object.
416 * @return The internal ewk_view object or NULL if it does not
417 * exist. (Failure to create or Elementary compiled without
418 * ewebkit)
419 *
420 * @see elm_web_add()
421 *
422 * @ingroup Web
423 */
424EAPI Evas_Object *elm_web_webkit_view_get(const Evas_Object *obj);
425
426/**
427 * Sets the function to call when a new window is requested
428 *
429 * This hook will be called when a request to create a new window is
430 * issued from the web page loaded.
431 * There is no default implementation for this feature, so leaving this
432 * unset or passing @c NULL in @p func will prevent new windows from
433 * opening.
434 *
435 * @param obj The web object where to set the hook function
436 * @param func The hook function to be called when a window is requested
437 * @param data User data
438 *
439 * @ingroup Web
440 */
441EAPI void elm_web_window_create_hook_set(Evas_Object *obj, Elm_Web_Window_Open func, void *data);
442
443/**
444 * Sets the function to call when an alert dialog
445 *
446 * This hook will be called when a JavaScript alert dialog is requested.
447 * If no function is set or @c NULL is passed in @p func, the default
448 * implementation will take place.
449 *
450 * @param obj The web object where to set the hook function
451 * @param func The callback function to be used
452 * @param data User data
453 *
454 * @see elm_web_inwin_mode_set()
455 *
456 * @ingroup Web
457 */
458EAPI void elm_web_dialog_alert_hook_set(Evas_Object *obj, Elm_Web_Dialog_Alert func, void *data);
459
460/**
461 * Sets the function to call when an confirm dialog
462 *
463 * This hook will be called when a JavaScript confirm dialog is requested.
464 * If no function is set or @c NULL is passed in @p func, the default
465 * implementation will take place.
466 *
467 * @param obj The web object where to set the hook function
468 * @param func The callback function to be used
469 * @param data User data
470 *
471 * @see elm_web_inwin_mode_set()
472 *
473 * @ingroup Web
474 */
475EAPI void elm_web_dialog_confirm_hook_set(Evas_Object *obj, Elm_Web_Dialog_Confirm func, void *data);
476
477/**
478 * Sets the function to call when an prompt dialog
479 *
480 * This hook will be called when a JavaScript prompt dialog is requested.
481 * If no function is set or @c NULL is passed in @p func, the default
482 * implementation will take place.
483 *
484 * @param obj The web object where to set the hook function
485 * @param func The callback function to be used
486 * @param data User data
487 *
488 * @see elm_web_inwin_mode_set()
489 *
490 * @ingroup Web
491 */
492EAPI void elm_web_dialog_prompt_hook_set(Evas_Object *obj, Elm_Web_Dialog_Prompt func, void *data);
493
494/**
495 * Sets the function to call when an file selector dialog
496 *
497 * This hook will be called when a JavaScript file selector dialog is
498 * requested.
499 * If no function is set or @c NULL is passed in @p func, the default
500 * implementation will take place.
501 *
502 * @param obj The web object where to set the hook function
503 * @param func The callback function to be used
504 * @param data User data
505 *
506 * @see elm_web_inwin_mode_set()
507 *
508 * @ingroup Web
509 */
510EAPI void elm_web_dialog_file_selector_hook_set(Evas_Object *obj, Elm_Web_Dialog_File_Selector func, void *data);
511
512/**
513 * Sets the function to call when a console message is emitted from JS
514 *
515 * This hook will be called when a console message is emitted from
516 * JavaScript. There is no default implementation for this feature.
517 *
518 * @param obj The web object where to set the hook function
519 * @param func The callback function to be used
520 * @param data User data
521 *
522 * @ingroup Web
523 */
524EAPI void elm_web_console_message_hook_set(Evas_Object *obj, Elm_Web_Console_Message func, void *data);
525
526/**
527 * Gets the status of the tab propagation
528 *
529 * @param obj The web object to query
530 * @return EINA_TRUE if tab propagation is enabled, EINA_FALSE otherwise
531 *
532 * @see elm_web_tab_propagate_set()
533 *
534 * @ingroup Web
535 */
536EAPI Eina_Bool elm_web_tab_propagate_get(const Evas_Object *obj);
537
538/**
539 * Sets whether to use tab propagation
540 *
541 * If tab propagation is enabled, whenever the user presses the Tab key,
542 * Elementary will handle it and switch focus to the next widget.
543 * The default value is disabled, where WebKit will handle the Tab key to
544 * cycle focus though its internal objects, jumping to the next widget
545 * only when that cycle ends.
546 *
547 * @param obj The web object
548 * @param propagate Whether to propagate Tab keys to Elementary or not
549 *
550 * @ingroup Web
551 */
552EAPI void elm_web_tab_propagate_set(Evas_Object *obj, Eina_Bool propagate);
553
554/**
555 * Sets the URI for the web object
556 *
557 * It must be a full URI, with resource included, in the form
558 * http://www.enlightenment.org or file:///tmp/something.html
559 *
560 * @param obj The web object
561 * @param uri The URI to set
562 * @return EINA_TRUE if the URI could be set, EINA_FALSE if an error occurred
563 *
564 * @ingroup Web
565 */
566EAPI Eina_Bool elm_web_uri_set(Evas_Object *obj, const char *uri);
567
568/**
569 * Gets the current URI for the object
570 *
571 * The returned string must not be freed and is guaranteed to be
572 * stringshared.
573 *
574 * @param obj The web object
575 * @return A stringshared internal string with the current URI, or NULL on
576 * failure
577 *
578 * @ingroup Web
579 */
580EAPI const char *elm_web_uri_get(const Evas_Object *obj);
581
582/**
583 * Gets the current title
584 *
585 * The returned string must not be freed and is guaranteed to be
586 * stringshared.
587 *
588 * @param obj The web object
589 * @return A stringshared internal string with the current title, or NULL on
590 * failure
591 *
592 * @ingroup Web
593 */
594EAPI const char *elm_web_title_get(const Evas_Object *obj);
595
596/**
597 * Sets the background color to be used by the web object
598 *
599 * This is the color that will be used by default when the loaded page
600 * does not set it's own. Color values are pre-multiplied.
601 *
602 * @param obj The web object
603 * @param r Red component
604 * @param g Green component
605 * @param b Blue component
606 * @param a Alpha component
607 *
608 * @ingroup Web
609 */
610EAPI void elm_web_bg_color_set(Evas_Object *obj, int r, int g, int b, int a);
611
612/**
613 * Gets the background color to be used by the web object
614 *
615 * This is the color that will be used by default when the loaded page
616 * does not set it's own. Color values are pre-multiplied.
617 *
618 * @param obj The web object
619 * @param r Red component
620 * @param g Green component
621 * @param b Blue component
622 * @param a Alpha component
623 *
624 * @ingroup Web
625 */
626EAPI void elm_web_bg_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a);
627
628/**
629 * Gets a copy of the currently selected text
630 *
631 * The string returned must be freed by the user when it's done with it.
632 *
633 * @param obj The web object
634 * @return A newly allocated string, or NULL if nothing is selected or an
635 * error occurred
636 *
637 * @ingroup Web
638 */
639EAPI char *elm_web_selection_get(const Evas_Object *obj);
640
641/**
642 * Tells the web object which index in the currently open popup was selected
643 *
644 * When the user handles the popup creation from the "popup,created" signal,
645 * it needs to tell the web object which item was selected by calling this
646 * function with the index corresponding to the item.
647 *
648 * @param obj The web object
649 * @param index The index selected
650 *
651 * @see elm_web_popup_destroy()
652 *
653 * @ingroup Web
654 */
655EAPI void elm_web_popup_selected_set(Evas_Object *obj, int index);
656
657/**
658 * Dismisses an open dropdown popup
659 *
660 * When the popup from a dropdown widget is to be dismissed, either after
661 * selecting an option or to cancel it, this function must be called, which
662 * will later emit an "popup,willdelete" signal to notify the user that
663 * any memory and objects related to this popup can be freed.
664 *
665 * @param obj The web object
666 * @return EINA_TRUE if the menu was successfully destroyed, or EINA_FALSE
667 * if there was no menu to destroy
668 *
669 * @ingroup Web
670 */
671EAPI Eina_Bool elm_web_popup_destroy(Evas_Object *obj);
672
673/**
674 * Searches the given string in a document.
675 *
676 * @param obj The web object where to search the text
677 * @param string String to search
678 * @param case_sensitive If search should be case sensitive or not
679 * @param forward If search is from cursor and on or backwards
680 * @param wrap If search should wrap at the end
681 *
682 * @return @c EINA_TRUE if the given string was found, @c EINA_FALSE if not
683 * or failure
684 *
685 * @ingroup Web
686 */
687EAPI Eina_Bool elm_web_text_search(const Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool forward, Eina_Bool wrap);
688
689/**
690 * Marks matches of the given string in a document.
691 *
692 * @param obj The web object where to search text
693 * @param string String to match
694 * @param case_sensitive If match should be case sensitive or not
695 * @param highlight If matches should be highlighted
696 * @param limit Maximum amount of matches, or zero to unlimited
697 *
698 * @return number of matched @a string
699 *
700 * @ingroup Web
701 */
702EAPI unsigned int elm_web_text_matches_mark(Evas_Object *obj, const char *string, Eina_Bool case_sensitive, Eina_Bool highlight, unsigned int limit);
703
704/**
705 * Clears all marked matches in the document
706 *
707 * @param obj The web object
708 *
709 * @return EINA_TRUE on success, EINA_FALSE otherwise
710 *
711 * @ingroup Web
712 */
713EAPI Eina_Bool elm_web_text_matches_unmark_all(Evas_Object *obj);
714
715/**
716 * Sets whether to highlight the matched marks
717 *
718 * If enabled, marks set with elm_web_text_matches_mark() will be
719 * highlighted.
720 *
721 * @param obj The web object
722 * @param highlight Whether to highlight the marks or not
723 *
724 * @return EINA_TRUE on success, EINA_FALSE otherwise
725 *
726 * @ingroup Web
727 */
728EAPI Eina_Bool elm_web_text_matches_highlight_set(Evas_Object *obj, Eina_Bool highlight);
729
730/**
731 * Gets whether highlighting marks is enabled
732 *
733 * @param obj The web object
734 *
735 * @return EINA_TRUE is marks are set to be highlighted, EINA_FALSE
736 * otherwise
737 *
738 * @ingroup Web
739 */
740EAPI Eina_Bool elm_web_text_matches_highlight_get(const Evas_Object *obj);
741
742/**
743 * Gets the overall loading progress of the page
744 *
745 * Returns the estimated loading progress of the page, with a value between
746 * 0.0 and 1.0. This is an estimated progress accounting for all the frames
747 * included in the page.
748 *
749 * @param obj The web object
750 *
751 * @return A value between 0.0 and 1.0 indicating the progress, or -1.0 on
752 * failure
753 *
754 * @ingroup Web
755 */
756EAPI double elm_web_load_progress_get(const Evas_Object *obj);
757
758/**
759 * Stops loading the current page
760 *
761 * Cancels the loading of the current page in the web object. This will
762 * cause a "load,error" signal to be emitted, with the is_cancellation
763 * flag set to EINA_TRUE.
764 *
765 * @param obj The web object
766 *
767 * @return EINA_TRUE if the cancel was successful, EINA_FALSE otherwise
768 *
769 * @ingroup Web
770 */
771EAPI Eina_Bool elm_web_stop(Evas_Object *obj);
772
773/**
774 * Requests a reload of the current document in the object
775 *
776 * @param obj The web object
777 *
778 * @return EINA_TRUE on success, EINA_FALSE otherwise
779 *
780 * @ingroup Web
781 */
782EAPI Eina_Bool elm_web_reload(Evas_Object *obj);
783
784/**
785 * Requests a reload of the current document, avoiding any existing caches
786 *
787 * @param obj The web object
788 *
789 * @return EINA_TRUE on success, EINA_FALSE otherwise
790 *
791 * @ingroup Web
792 */
793EAPI Eina_Bool elm_web_reload_full(Evas_Object *obj);
794
795/**
796 * Goes back one step in the browsing history
797 *
798 * This is equivalent to calling elm_web_object_navigate(obj, -1);
799 *
800 * @param obj The web object
801 *
802 * @return EINA_TRUE on success, EINA_FALSE otherwise
803 *
804 * @see elm_web_history_enabled_set()
805 * @see elm_web_back_possible()
806 * @see elm_web_forward()
807 * @see elm_web_navigate()
808 *
809 * @ingroup Web
810 */
811EAPI Eina_Bool elm_web_back(Evas_Object *obj);
812
813/**
814 * Goes forward one step in the browsing history
815 *
816 * This is equivalent to calling elm_web_object_navigate(obj, 1);
817 *
818 * @param obj The web object
819 *
820 * @return EINA_TRUE on success, EINA_FALSE otherwise
821 *
822 * @see elm_web_history_enabled_set()
823 * @see elm_web_forward_possible_get()
824 * @see elm_web_back()
825 * @see elm_web_navigate()
826 *
827 * @ingroup Web
828 */
829EAPI Eina_Bool elm_web_forward(Evas_Object *obj);
830
831/**
832 * Jumps the given number of steps in the browsing history
833 *
834 * The @p steps value can be a negative integer to back in history, or a
835 * positive to move forward.
836 *
837 * @param obj The web object
838 * @param steps The number of steps to jump
839 *
840 * @return EINA_TRUE on success, EINA_FALSE on error or if not enough
841 * history exists to jump the given number of steps
842 *
843 * @see elm_web_history_enabled_set()
844 * @see elm_web_back()
845 * @see elm_web_forward()
846 *
847 * @ingroup Web
848 */
849EAPI Eina_Bool elm_web_navigate(Evas_Object *obj, int steps);
850
851/**
852 * Queries whether it's possible to go back in history
853 *
854 * @param obj The web object
855 *
856 * @return EINA_TRUE if it's possible to back in history, EINA_FALSE
857 * otherwise
858 *
859 * @ingroup Web
860 */
861EAPI Eina_Bool elm_web_back_possible_get(Evas_Object *obj);
862
863/**
864 * Queries whether it's possible to go forward in history
865 *
866 * @param obj The web object
867 *
868 * @return EINA_TRUE if it's possible to forward in history, EINA_FALSE
869 * otherwise
870 *
871 * @ingroup Web
872 */
873EAPI Eina_Bool elm_web_forward_possible_get(Evas_Object *obj);
874
875/**
876 * Queries whether it's possible to jump the given number of steps
877 *
878 * The @p steps value can be a negative integer to back in history, or a
879 * positive to move forward.
880 *
881 * @param obj The web object
882 * @param steps The number of steps to check for
883 *
884 * @return EINA_TRUE if enough history exists to perform the given jump,
885 * EINA_FALSE otherwise
886 *
887 * @ingroup Web
888 */
889EAPI Eina_Bool elm_web_navigate_possible_get(Evas_Object *obj, int steps);
890
891/**
892 * Gets whether browsing history is enabled for the given object
893 *
894 * @param obj The web object
895 *
896 * @return EINA_TRUE if history is enabled, EINA_FALSE otherwise
897 *
898 * @ingroup Web
899 */
900EAPI Eina_Bool elm_web_history_enabled_get(const Evas_Object *obj);
901
902/**
903 * Enables or disables the browsing history
904 *
905 * @param obj The web object
906 * @param enabled Whether to enable or disable the browsing history
907 *
908 * @ingroup Web
909 */
910EAPI void elm_web_history_enabled_set(Evas_Object *obj, Eina_Bool enabled);
911
912/**
913 * Sets the zoom level of the web object
914 *
915 * Zoom level matches the Webkit API, so 1.0 means normal zoom, with higher
916 * values meaning zoom in and lower meaning zoom out. This function will
917 * only affect the zoom level if the mode set with elm_web_zoom_mode_set()
918 * is ::ELM_WEB_ZOOM_MODE_MANUAL.
919 *
920 * @param obj The web object
921 * @param zoom The zoom level to set
922 *
923 * @ingroup Web
924 */
925EAPI void elm_web_zoom_set(Evas_Object *obj, double zoom);
926
927/**
928 * Gets the current zoom level set on the web object
929 *
930 * Note that this is the zoom level set on the web object and not that
931 * of the underlying Webkit one. In the ::ELM_WEB_ZOOM_MODE_MANUAL mode,
932 * the two zoom levels should match, but for the other two modes the
933 * Webkit zoom is calculated internally to match the chosen mode without
934 * changing the zoom level set for the web object.
935 *
936 * @param obj The web object
937 *
938 * @return The zoom level set on the object
939 *
940 * @ingroup Web
941 */
942EAPI double elm_web_zoom_get(const Evas_Object *obj);
943
944/**
945 * Sets the zoom mode to use
946 *
947 * The modes can be any of those defined in ::Elm_Web_Zoom_Mode, except
948 * ::ELM_WEB_ZOOM_MODE_LAST. The default is ::ELM_WEB_ZOOM_MODE_MANUAL.
949 *
950 * ::ELM_WEB_ZOOM_MODE_MANUAL means the zoom level will be controlled
951 * with the elm_web_zoom_set() function.
952 * ::ELM_WEB_ZOOM_MODE_AUTO_FIT will calculate the needed zoom level to
953 * make sure the entirety of the web object's contents are shown.
954 * ::ELM_WEB_ZOOM_MODE_AUTO_FILL will calculate the needed zoom level to
955 * fit the contents in the web object's size, without leaving any space
956 * unused.
957 *
958 * @param obj The web object
959 * @param mode The mode to set
960 *
961 * @ingroup Web
962 */
963EAPI void elm_web_zoom_mode_set(Evas_Object *obj, Elm_Web_Zoom_Mode mode);
964
965/**
966 * Gets the currently set zoom mode
967 *
968 * @param obj The web object
969 *
970 * @return The current zoom mode set for the object, or
971 * ::ELM_WEB_ZOOM_MODE_LAST on error
972 *
973 * @ingroup Web
974 */
975EAPI Elm_Web_Zoom_Mode elm_web_zoom_mode_get(const Evas_Object *obj);
976
977/**
978 * Shows the given region in the web object
979 *
980 * @param obj The web object
981 * @param x The x coordinate of the region to show
982 * @param y The y coordinate of the region to show
983 * @param w The width of the region to show
984 * @param h The height of the region to show
985 *
986 * @ingroup Web
987 */
988EAPI void elm_web_region_show(Evas_Object *obj, int x, int y, int w, int h);
989
990/**
991 * Brings in the region to the visible area
992 *
993 * Like elm_web_region_show(), but it animates the scrolling of the object
994 * to show the area
995 *
996 * @param obj The web object
997 * @param x The x coordinate of the region to show
998 * @param y The y coordinate of the region to show
999 * @param w The width of the region to show
1000 * @param h The height of the region to show
1001 *
1002 * @ingroup Web
1003 */
1004EAPI void elm_web_region_bring_in(Evas_Object *obj, int x, int y, int w, int h);
1005
1006/**
1007 * Sets the default dialogs to use an Inwin instead of a normal window
1008 *
1009 * If set, then the default implementation for the JavaScript dialogs and
1010 * file selector will be opened in an Inwin. Otherwise they will use a
1011 * normal separated window.
1012 *
1013 * @param obj The web object
1014 * @param value EINA_TRUE to use Inwin, EINA_FALSE to use a normal window
1015 *
1016 * @ingroup Web
1017 */
1018EAPI void elm_web_inwin_mode_set(Evas_Object *obj, Eina_Bool value);
1019
1020/**
1021 * Gets whether Inwin mode is set for the current object
1022 *
1023 * @param obj The web object
1024 *
1025 * @return EINA_TRUE if Inwin mode is set, EINA_FALSE otherwise
1026 *
1027 * @ingroup Web
1028 */
1029EAPI Eina_Bool elm_web_inwin_mode_get(const Evas_Object *obj);
1030
1031EAPI void elm_web_window_features_ref(Elm_Web_Window_Features *wf);
1032EAPI void elm_web_window_features_unref(Elm_Web_Window_Features *wf);
1033
1034/**
1035 * Gets boolean properties from Elm_Web_Window_Features
1036 * (such as statusbar, menubar, etc) that are on a window.
1037 *
1038 * @param wf The web window features object
1039 * @param flag The web window feature flag whose value is required.
1040 *
1041 * @return EINA_TRUE if the flag is set, EINA_FALSE otherwise
1042 *
1043 * @ingroup Web
1044 */
1045EAPI Eina_Bool elm_web_window_features_property_get(const Elm_Web_Window_Features *wf, Elm_Web_Window_Feature_Flag flag);
1046
1047/**
1048 *
1049 * TODO : Add documentation.
1050 *
1051 * @param wf The web window features object
1052 * @param x, y, w, h - the co-ordinates of the web view window.
1053 *
1054 * @ingroup Web
1055 */
1056EAPI void elm_web_window_features_region_get(const Elm_Web_Window_Features *wf, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
1057
1058/**
1059 * @}
1060 */
diff --git a/libraries/elementary/src/lib/elm_widget.c b/libraries/elementary/src/lib/elm_widget.c
new file mode 100644
index 0000000..4b62b63
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_widget.c
@@ -0,0 +1,3949 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4static const char SMART_NAME[] = "elm_widget";
5
6#define API_ENTRY \
7 Smart_Data * sd = evas_object_smart_data_get(obj); \
8 if ((!sd) || (!_elm_widget_is(obj)))
9#define INTERNAL_ENTRY \
10 Smart_Data * sd = evas_object_smart_data_get(obj); \
11 if (!sd) return
12
13#undef elm_widget_text_set_hook_set
14#undef elm_widget_text_get_hook_set
15#undef elm_widget_content_set_hook_set
16#undef elm_widget_content_get_hook_set
17#undef elm_widget_content_unset_hook_set
18
19typedef struct _Smart_Data Smart_Data;
20typedef struct _Edje_Signal_Data Edje_Signal_Data;
21typedef struct _Elm_Event_Cb_Data Elm_Event_Cb_Data;
22typedef struct _Elm_Translate_String_Data Elm_Translate_String_Data;
23
24struct _Smart_Data
25{
26 Evas_Object *obj;
27 const char *type;
28 Evas_Object *parent_obj;
29 Evas_Object *parent2;
30 Evas_Coord x, y, w, h;
31 Eina_List *subobjs;
32 Evas_Object *resize_obj;
33 Evas_Object *hover_obj;
34 Eina_List *tooltips, *cursors;
35 void (*del_func)(Evas_Object *obj);
36 void (*del_pre_func)(Evas_Object *obj);
37 void (*focus_func)(Evas_Object *obj);
38 void (*activate_func)(Evas_Object *obj);
39 void (*disable_func)(Evas_Object *obj);
40 void (*theme_func)(Evas_Object *obj);
41 void (*translate_func)(Evas_Object *obj);
42 Eina_Bool (*event_func)(Evas_Object *obj,
43 Evas_Object *source,
44 Evas_Callback_Type type,
45 void *event_info);
46 void (*signal_func)(Evas_Object *obj,
47 const char *emission,
48 const char *source);
49 void (*callback_add_func)(Evas_Object *obj,
50 const char *emission,
51 const char *source,
52 Edje_Signal_Cb func,
53 void *data);
54 void (*callback_del_func)(Evas_Object *obj,
55 const char *emission,
56 const char *source,
57 Edje_Signal_Cb func,
58 void *data);
59 void (*changed_func)(Evas_Object *obj);
60 Eina_Bool (*focus_next_func)(const Evas_Object *obj,
61 Elm_Focus_Direction dir,
62 Evas_Object **next);
63 void (*on_focus_func)(void *data,
64 Evas_Object *obj);
65 void *on_focus_data;
66 void (*on_change_func)(void *data,
67 Evas_Object *obj);
68 void *on_change_data;
69 void (*on_show_region_func)(void *data,
70 Evas_Object *obj);
71 void *on_show_region_data;
72 void (*focus_region_func)(Evas_Object *obj,
73 Evas_Coord x,
74 Evas_Coord y,
75 Evas_Coord w,
76 Evas_Coord h);
77 void (*on_focus_region_func)(const Evas_Object *obj,
78 Evas_Coord *x,
79 Evas_Coord *y,
80 Evas_Coord *w,
81 Evas_Coord *h);
82 Elm_Widget_Text_Set_Cb text_set_func;
83 Elm_Widget_Text_Get_Cb text_get_func;
84 Elm_Widget_Content_Set_Cb content_set_func;
85 Elm_Widget_Content_Get_Cb content_get_func;
86 Elm_Widget_Content_Unset_Cb content_unset_func;
87 void *data;
88 Evas_Coord rx, ry, rw, rh;
89 int scroll_hold;
90 int scroll_freeze;
91 double scale;
92 Elm_Theme *theme;
93 const char *style;
94 const char *access_info;
95 unsigned int focus_order;
96 Eina_Bool focus_order_on_calc;
97
98 int child_drag_x_locked;
99 int child_drag_y_locked;
100
101 Eina_List *edje_signals;
102 Eina_List *translate_strings;
103
104 Eina_Bool drag_x_locked : 1;
105 Eina_Bool drag_y_locked : 1;
106
107 Eina_Bool can_focus : 1;
108 Eina_Bool child_can_focus : 1;
109 Eina_Bool focused : 1;
110 Eina_Bool top_win_focused : 1;
111 Eina_Bool tree_unfocusable : 1;
112 Eina_Bool highlight_ignore : 1;
113 Eina_Bool highlight_in_theme : 1;
114 Eina_Bool disabled : 1;
115 Eina_Bool is_mirrored : 1;
116 Eina_Bool mirrored_auto_mode : 1; /* This is TRUE by default */
117 Eina_Bool still_in : 1;
118
119 Eina_List *focus_chain;
120 Eina_List *event_cb;
121};
122
123struct _Edje_Signal_Data
124{
125 Evas_Object *obj;
126 Edje_Signal_Cb func;
127 const char *emission;
128 const char *source;
129 void *data;
130};
131
132struct _Elm_Event_Cb_Data
133{
134 Elm_Event_Cb func;
135 const void *data;
136};
137
138struct _Elm_Translate_String_Data
139{
140 const char *id;
141 const char *domain;
142 const char *string;
143};
144
145/* local subsystem functions */
146static void _smart_reconfigure(Smart_Data *sd);
147static void _smart_add(Evas_Object *obj);
148static void _smart_del(Evas_Object *obj);
149static void _smart_move(Evas_Object *obj,
150 Evas_Coord x,
151 Evas_Coord y);
152static void _smart_resize(Evas_Object *obj,
153 Evas_Coord w,
154 Evas_Coord h);
155static void _smart_show(Evas_Object *obj);
156static void _smart_hide(Evas_Object *obj);
157static void _smart_color_set(Evas_Object *obj,
158 int r,
159 int g,
160 int b,
161 int a);
162static void _smart_clip_set(Evas_Object *obj,
163 Evas_Object *clip);
164static void _smart_clip_unset(Evas_Object *obj);
165static void _smart_calculate(Evas_Object *obj);
166static void _smart_member_add(Evas_Object *obj, Evas_Object *child);
167static void _smart_member_del(Evas_Object *obj, Evas_Object *child);
168static void _smart_init(void);
169
170static void _if_focused_revert(Evas_Object *obj,
171 Eina_Bool can_focus_only);
172static Evas_Object *_newest_focus_order_get(Evas_Object *obj,
173 unsigned int *newest_focus_order,
174 Eina_Bool can_focus_only);
175
176/* local subsystem globals */
177static Evas_Smart *_e_smart = NULL;
178static Eina_List *widtypes = NULL;
179
180static unsigned int focus_order = 0;
181
182// internal funcs
183static inline Eina_Bool
184_elm_widget_is(const Evas_Object *obj)
185{
186 const char *type = evas_object_type_get(obj);
187 return type == SMART_NAME;
188}
189
190static inline Eina_Bool
191_is_focusable(Evas_Object *obj)
192{
193 API_ENTRY return EINA_FALSE;
194 return sd->can_focus || (sd->child_can_focus);
195}
196
197static void
198_unfocus_parents(Evas_Object *obj)
199{
200 for (; obj; obj = elm_widget_parent_get(obj))
201 {
202 INTERNAL_ENTRY;
203 if (!sd->focused) return;
204 sd->focused = 0;
205 }
206}
207
208static void
209_focus_parents(Evas_Object *obj)
210{
211 for (; obj; obj = elm_widget_parent_get(obj))
212 {
213 INTERNAL_ENTRY;
214 if (sd->focused) return;
215 sd->focused = 1;
216 }
217}
218
219static void
220_sub_obj_del(void *data,
221 Evas *e __UNUSED__,
222 Evas_Object *obj,
223 void *event_info __UNUSED__)
224{
225 Smart_Data *sd = data;
226
227 if (_elm_widget_is(obj))
228 {
229 if (elm_widget_focus_get(obj)) _unfocus_parents(sd->obj);
230 }
231 if (obj == sd->resize_obj)
232 sd->resize_obj = NULL;
233 else if (obj == sd->hover_obj)
234 sd->hover_obj = NULL;
235 else
236 sd->subobjs = eina_list_remove(sd->subobjs, obj);
237 evas_object_smart_callback_call(sd->obj, "sub-object-del", obj);
238}
239
240static void
241_sub_obj_hide(void *data __UNUSED__,
242 Evas *e __UNUSED__,
243 Evas_Object *obj,
244 void *event_info __UNUSED__)
245{
246 elm_widget_focus_hide_handle(obj);
247}
248
249static void
250_sub_obj_mouse_down(void *data,
251 Evas *e __UNUSED__,
252 Evas_Object *obj __UNUSED__,
253 void *event_info)
254{
255 Smart_Data *sd = data;
256 Evas_Event_Mouse_Down *ev = event_info;
257 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
258 sd->still_in = EINA_TRUE;
259}
260
261static void
262_sub_obj_mouse_move(void *data,
263 Evas *e __UNUSED__,
264 Evas_Object *obj,
265 void *event_info)
266{
267 Smart_Data *sd = data;
268 Evas_Event_Mouse_Move *ev = event_info;
269 if (sd->still_in)
270 {
271 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
272 sd->still_in = EINA_FALSE;
273 else
274 {
275 Evas_Coord x, y, w, h;
276 evas_object_geometry_get(obj, &x, &y, &w, &h);
277 if ((ev->cur.canvas.x < x) || (ev->cur.canvas.y < y) ||
278 (ev->cur.canvas.x >= (x + w)) || (ev->cur.canvas.y >= (y + h)))
279 sd->still_in = EINA_FALSE;
280 }
281 }
282}
283
284static void
285_sub_obj_mouse_up(void *data,
286 Evas *e __UNUSED__,
287 Evas_Object *obj,
288 void *event_info __UNUSED__)
289{
290 Smart_Data *sd = data;
291 if (sd->still_in)
292 elm_widget_focus_mouse_up_handle(obj);
293 sd->still_in = EINA_FALSE;
294}
295
296static void
297_propagate_x_drag_lock(Evas_Object *obj,
298 int dir)
299{
300 INTERNAL_ENTRY;
301 if (sd->parent_obj)
302 {
303 Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
304 if (sd2)
305 {
306 sd2->child_drag_x_locked += dir;
307 _propagate_x_drag_lock(sd->parent_obj, dir);
308 }
309 }
310}
311
312static void
313_propagate_y_drag_lock(Evas_Object *obj,
314 int dir)
315{
316 INTERNAL_ENTRY;
317 if (sd->parent_obj)
318 {
319 Smart_Data *sd2 = evas_object_smart_data_get(sd->parent_obj);
320 if (sd2)
321 {
322 sd2->child_drag_y_locked += dir;
323 _propagate_y_drag_lock(sd->parent_obj, dir);
324 }
325 }
326}
327
328static void
329_propagate_event(void *data,
330 Evas *e __UNUSED__,
331 Evas_Object *obj,
332 void *event_info)
333{
334 INTERNAL_ENTRY;
335 Evas_Callback_Type type = (Evas_Callback_Type)(long)data;
336 Evas_Event_Flags *event_flags = NULL;
337
338 switch (type)
339 {
340 case EVAS_CALLBACK_KEY_DOWN:
341 {
342 Evas_Event_Key_Down *ev = event_info;
343 event_flags = &(ev->event_flags);
344 }
345 break;
346
347 case EVAS_CALLBACK_KEY_UP:
348 {
349 Evas_Event_Key_Up *ev = event_info;
350 event_flags = &(ev->event_flags);
351 }
352 break;
353
354 case EVAS_CALLBACK_MOUSE_WHEEL:
355 {
356 Evas_Event_Mouse_Wheel *ev = event_info;
357 event_flags = &(ev->event_flags);
358 }
359 break;
360
361 default:
362 break;
363 }
364
365 elm_widget_event_propagate(obj, type, event_info, event_flags);
366}
367
368static void
369_parent_focus(Evas_Object *obj)
370{
371 API_ENTRY return;
372 if (sd->focused) return;
373
374 Evas_Object *o = elm_widget_parent_get(obj);
375 sd->focus_order_on_calc = EINA_TRUE;
376
377 if (o) _parent_focus(o);
378
379 if (!sd->focus_order_on_calc)
380 return; /* we don't want to override it if by means of any of the
381 callbacks below one gets to calculate our order
382 first. */
383
384 focus_order++;
385 sd->focus_order = focus_order;
386 if (sd->top_win_focused)
387 {
388 sd->focused = EINA_TRUE;
389 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
390 if (sd->focus_func) sd->focus_func(obj);
391 _elm_widget_focus_region_show(obj);
392 }
393 sd->focus_order_on_calc = EINA_FALSE;
394}
395
396static void
397_elm_object_focus_chain_del_cb(void *data,
398 Evas *e __UNUSED__,
399 Evas_Object *obj,
400 void *event_info __UNUSED__)
401{
402 Smart_Data *sd = data;
403
404 sd->focus_chain = eina_list_remove(sd->focus_chain, obj);
405}
406
407// exposed util funcs to elm
408void
409_elm_widget_type_clear(void)
410{
411 const char **ptr;
412
413 EINA_LIST_FREE(widtypes, ptr)
414 {
415 eina_stringshare_del(*ptr);
416 *ptr = NULL;
417 }
418}
419
420void
421_elm_widget_focus_region_show(const Evas_Object *obj)
422{
423 Evas_Coord x, y, w, h, ox, oy;
424 Smart_Data *sd2;
425 Evas_Object *o;
426
427 API_ENTRY return;
428
429 o = elm_widget_parent_get(obj);
430 if (!o) return;
431
432 elm_widget_focus_region_get(obj, &x, &y, &w, &h);
433 evas_object_geometry_get(obj, &ox, &oy, NULL, NULL);
434 while (o)
435 {
436 Evas_Coord px, py;
437 sd2 = evas_object_smart_data_get(o);
438 if (sd2->focus_region_func)
439 {
440 sd2->focus_region_func(o, x, y, w, h);
441 elm_widget_focus_region_get(o, &x, &y, &w, &h);
442 }
443 else
444 {
445 evas_object_geometry_get(o, &px, &py, NULL, NULL);
446 x += ox - px;
447 y += oy - py;
448 ox = px;
449 oy = py;
450 }
451 o = elm_widget_parent_get(o);
452 }
453}
454
455/**
456 * @defgroup Widget Widget
457 *
458 * @internal
459 * Exposed api for making widgets
460 */
461EAPI void
462elm_widget_type_register(const char **ptr)
463{
464 widtypes = eina_list_append(widtypes, (void *)ptr);
465}
466
467/**
468 * @defgroup Widget Widget
469 *
470 * @internal
471 * Disposed api for making widgets
472 */
473EAPI void
474elm_widget_type_unregister(const char **ptr)
475{
476 widtypes = eina_list_remove(widtypes, (void *)ptr);
477}
478
479EAPI Eina_Bool
480elm_widget_api_check(int ver)
481{
482 if (ver != ELM_INTERNAL_API_VERSION)
483 {
484 CRITICAL("Elementary widget api versions do not match");
485 return EINA_FALSE;
486 }
487 return EINA_TRUE;
488}
489
490EAPI Evas_Object *
491elm_widget_add(Evas *evas)
492{
493 Evas_Object *obj;
494 _smart_init();
495 obj = evas_object_smart_add(evas, _e_smart);
496 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
497 return obj;
498}
499
500EAPI void
501elm_widget_del_hook_set(Evas_Object *obj,
502 void (*func)(Evas_Object *obj))
503{
504 API_ENTRY return;
505 sd->del_func = func;
506}
507
508EAPI void
509elm_widget_del_pre_hook_set(Evas_Object *obj,
510 void (*func)(Evas_Object *obj))
511{
512 API_ENTRY return;
513 sd->del_pre_func = func;
514}
515
516EAPI void
517elm_widget_focus_hook_set(Evas_Object *obj,
518 void (*func)(Evas_Object *obj))
519{
520 API_ENTRY return;
521 sd->focus_func = func;
522}
523
524EAPI void
525elm_widget_activate_hook_set(Evas_Object *obj,
526 void (*func)(Evas_Object *obj))
527{
528 API_ENTRY return;
529 sd->activate_func = func;
530}
531
532EAPI void
533elm_widget_disable_hook_set(Evas_Object *obj,
534 void (*func)(Evas_Object *obj))
535{
536 API_ENTRY return;
537 sd->disable_func = func;
538}
539
540EAPI void
541elm_widget_theme_hook_set(Evas_Object *obj,
542 void (*func)(Evas_Object *obj))
543{
544 API_ENTRY return;
545 sd->theme_func = func;
546}
547
548EAPI void
549elm_widget_translate_hook_set(Evas_Object *obj,
550 void (*func)(Evas_Object *obj))
551{
552 API_ENTRY return;
553 sd->translate_func = func;
554}
555
556EAPI void
557elm_widget_event_hook_set(Evas_Object *obj,
558 Eina_Bool (*func)(Evas_Object *obj,
559 Evas_Object *source,
560 Evas_Callback_Type type,
561 void *event_info))
562{
563 API_ENTRY return;
564 sd->event_func = func;
565}
566
567EAPI void
568elm_widget_text_set_hook_set(Evas_Object *obj,
569 Elm_Widget_Text_Set_Cb func)
570{
571 API_ENTRY return;
572 sd->text_set_func = func;
573}
574
575EAPI void
576elm_widget_text_get_hook_set(Evas_Object *obj,
577 Elm_Widget_Text_Get_Cb func)
578{
579 API_ENTRY return;
580 sd->text_get_func = func;
581}
582
583EAPI void
584elm_widget_content_set_hook_set(Evas_Object *obj,
585 Elm_Widget_Content_Set_Cb func)
586{
587 API_ENTRY return;
588 sd->content_set_func = func;
589}
590
591EAPI void
592elm_widget_content_get_hook_set(Evas_Object *obj,
593 Elm_Widget_Content_Get_Cb func)
594{
595 API_ENTRY return;
596 sd->content_get_func = func;
597}
598
599EAPI void
600elm_widget_content_unset_hook_set(Evas_Object *obj,
601 Elm_Widget_Content_Unset_Cb func)
602{
603 API_ENTRY return;
604 sd->content_unset_func = func;
605}
606
607EAPI void
608elm_widget_changed_hook_set(Evas_Object *obj,
609 void (*func)(Evas_Object *obj))
610{
611 API_ENTRY return;
612 sd->changed_func = func;
613}
614
615EAPI void
616elm_widget_signal_emit_hook_set(Evas_Object *obj,
617 void (*func)(Evas_Object *obj,
618 const char *emission,
619 const char *source))
620{
621 API_ENTRY return;
622 sd->signal_func = func;
623}
624
625EAPI void
626elm_widget_signal_callback_add_hook_set(Evas_Object *obj,
627 void (*func)(Evas_Object *obj,
628 const char *emission,
629 const char *source,
630 Edje_Signal_Cb func_cb,
631 void *data))
632{
633 API_ENTRY return;
634 sd->callback_add_func = func;
635}
636
637EAPI void
638elm_widget_signal_callback_del_hook_set(Evas_Object *obj,
639 void (*func)(Evas_Object *obj,
640 const char *emission,
641 const char *source,
642 Edje_Signal_Cb func_cb,
643 void *data))
644{
645 API_ENTRY return;
646 sd->callback_del_func = func;
647}
648
649EAPI Eina_Bool
650elm_widget_theme(Evas_Object *obj)
651{
652 const Eina_List *l;
653 Evas_Object *child;
654 Elm_Tooltip *tt;
655 Elm_Cursor *cur;
656 Eina_Bool ret = EINA_TRUE;
657
658 API_ENTRY return EINA_FALSE;
659 EINA_LIST_FOREACH(sd->subobjs, l, child) ret &= elm_widget_theme(child);
660 if (sd->resize_obj && _elm_widget_is(sd->resize_obj))
661 ret &= elm_widget_theme(sd->resize_obj);
662 if (sd->hover_obj) ret &= elm_widget_theme(sd->hover_obj);
663 EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
664 EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
665 if (sd->theme_func) sd->theme_func(obj);
666
667 return ret;
668}
669
670EAPI void
671elm_widget_theme_specific(Evas_Object *obj,
672 Elm_Theme *th,
673 Eina_Bool force)
674{
675 const Eina_List *l;
676 Evas_Object *child;
677 Elm_Tooltip *tt;
678 Elm_Cursor *cur;
679 Elm_Theme *th2, *thdef;
680
681 API_ENTRY return;
682 thdef = elm_theme_default_get();
683 if (!th) th = thdef;
684 if (!force)
685 {
686 th2 = sd->theme;
687 if (!th2) th2 = thdef;
688 while (th2)
689 {
690 if (th2 == th)
691 {
692 force = EINA_TRUE;
693 break;
694 }
695 if (th2 == thdef) break;
696 th2 = th2->ref_theme;
697 if (!th2) th2 = thdef;
698 }
699 }
700 if (!force) return;
701 EINA_LIST_FOREACH(sd->subobjs, l, child)
702 elm_widget_theme_specific(child, th, force);
703 if (sd->resize_obj) elm_widget_theme(sd->resize_obj);
704 if (sd->hover_obj) elm_widget_theme(sd->hover_obj);
705 EINA_LIST_FOREACH(sd->tooltips, l, tt) elm_tooltip_theme(tt);
706 EINA_LIST_FOREACH(sd->cursors, l, cur) elm_cursor_theme(cur);
707 if (sd->theme_func) sd->theme_func(obj);
708}
709
710/**
711 * @internal
712 *
713 * Set hook to get next object in object focus chain.
714 *
715 * @param obj The widget object.
716 * @param func The hook to be used with this widget.
717 *
718 * @ingroup Widget
719 */
720EAPI void
721elm_widget_focus_next_hook_set(Evas_Object *obj,
722 Eina_Bool (*func)(const Evas_Object *obj,
723 Elm_Focus_Direction dir,
724 Evas_Object **next))
725{
726 API_ENTRY return;
727 sd->focus_next_func = func;
728}
729
730/**
731 * Returns the widget's mirrored mode.
732 *
733 * @param obj The widget.
734 * @return mirrored mode of the object.
735 *
736 **/
737EAPI Eina_Bool
738elm_widget_mirrored_get(const Evas_Object *obj)
739{
740 API_ENTRY return EINA_FALSE;
741 return sd->is_mirrored;
742}
743
744/**
745 * Sets the widget's mirrored mode.
746 *
747 * @param obj The widget.
748 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
749 */
750EAPI void
751elm_widget_mirrored_set(Evas_Object *obj,
752 Eina_Bool mirrored)
753{
754 API_ENTRY return;
755 if (sd->is_mirrored != mirrored)
756 {
757 sd->is_mirrored = mirrored;
758 elm_widget_theme(obj);
759 }
760}
761
762/**
763 * @internal
764 * Resets the mirrored mode from the system mirror mode for widgets that are in
765 * automatic mirroring mode. This function does not call elm_widget_theme.
766 *
767 * @param obj The widget.
768 * @param mirrored EINA_TRUE to set mirrored mode. EINA_FALSE to unset.
769 */
770void
771_elm_widget_mirrored_reload(Evas_Object *obj)
772{
773 API_ENTRY return;
774 Eina_Bool mirrored = elm_config_mirrored_get();
775 if (elm_widget_mirrored_automatic_get(obj) && (sd->is_mirrored != mirrored))
776 {
777 sd->is_mirrored = mirrored;
778 }
779}
780
781/**
782 * Returns the widget's mirrored mode setting.
783 *
784 * @param obj The widget.
785 * @return mirrored mode setting of the object.
786 *
787 **/
788EAPI Eina_Bool
789elm_widget_mirrored_automatic_get(const Evas_Object *obj)
790{
791 API_ENTRY return EINA_FALSE;
792 return sd->mirrored_auto_mode;
793}
794
795/**
796 * Sets the widget's mirrored mode setting.
797 * When widget in automatic mode, it follows the system mirrored mode set by
798 * elm_mirrored_set().
799 * @param obj The widget.
800 * @param automatic EINA_TRUE for auto mirrored mode. EINA_FALSE for manual.
801 */
802EAPI void
803elm_widget_mirrored_automatic_set(Evas_Object *obj,
804 Eina_Bool automatic)
805{
806 API_ENTRY return;
807 if (sd->mirrored_auto_mode != automatic)
808 {
809 sd->mirrored_auto_mode = automatic;
810
811 if (automatic)
812 {
813 elm_widget_mirrored_set(obj, elm_config_mirrored_get());
814 }
815 }
816}
817
818EAPI void
819elm_widget_on_focus_hook_set(Evas_Object *obj,
820 void (*func)(void *data,
821 Evas_Object *obj),
822 void *data)
823{
824 API_ENTRY return;
825 sd->on_focus_func = func;
826 sd->on_focus_data = data;
827}
828
829EAPI void
830elm_widget_on_change_hook_set(Evas_Object *obj,
831 void (*func)(void *data,
832 Evas_Object *obj),
833 void *data)
834{
835 API_ENTRY return;
836 sd->on_change_func = func;
837 sd->on_change_data = data;
838}
839
840EAPI void
841elm_widget_on_show_region_hook_set(Evas_Object *obj,
842 void (*func)(void *data,
843 Evas_Object *obj),
844 void *data)
845{
846 API_ENTRY return;
847 sd->on_show_region_func = func;
848 sd->on_show_region_data = data;
849}
850
851/**
852 * @internal
853 *
854 * Set the hook to use to show the focused region.
855 *
856 * Whenever a new widget gets focused or it's needed to show the focused
857 * area of the current one, this hook will be called on objects that may
858 * want to move their children into their visible area.
859 * The area given in the hook function is relative to the @p obj widget.
860 *
861 * @param obj The widget object
862 * @param func The function to call to show the specified area.
863 *
864 * @ingroup Widget
865 */
866EAPI void
867elm_widget_focus_region_hook_set(Evas_Object *obj,
868 void (*func)(Evas_Object *obj,
869 Evas_Coord x,
870 Evas_Coord y,
871 Evas_Coord w,
872 Evas_Coord h))
873{
874 API_ENTRY return;
875 sd->focus_region_func = func;
876}
877
878/**
879 * @internal
880 *
881 * Set the hook to retrieve the focused region of a widget.
882 *
883 * This hook will be called by elm_widget_focus_region_get() whenever
884 * it's needed to get the focused area of a widget. The area must be relative
885 * to the widget itself and if no hook is set, it will default to the entire
886 * object.
887 *
888 * @param obj The widget object
889 * @param func The function used to retrieve the focus region.
890 *
891 * @ingroup Widget
892 */
893EAPI void
894elm_widget_on_focus_region_hook_set(Evas_Object *obj,
895 void (*func)(const Evas_Object *obj,
896 Evas_Coord *x,
897 Evas_Coord *y,
898 Evas_Coord *w,
899 Evas_Coord *h))
900{
901 API_ENTRY return;
902 sd->on_focus_region_func = func;
903}
904
905EAPI void
906elm_widget_data_set(Evas_Object *obj,
907 void *data)
908{
909 API_ENTRY return;
910 sd->data = data;
911}
912
913EAPI void *
914elm_widget_data_get(const Evas_Object *obj)
915{
916 API_ENTRY return NULL;
917 return sd->data;
918}
919
920EAPI void
921elm_widget_sub_object_add(Evas_Object *obj,
922 Evas_Object *sobj)
923{
924 API_ENTRY return;
925 EINA_SAFETY_ON_TRUE_RETURN(obj == sobj);
926 double scale, pscale = elm_widget_scale_get(sobj);
927 Elm_Theme *th, *pth = elm_widget_theme_get(sobj);
928 Eina_Bool mirrored, pmirrored = elm_widget_mirrored_get(obj);
929
930 if (sobj == sd->parent_obj)
931 {
932 elm_widget_sub_object_del(sobj, obj);
933 WRN("You passed a parent object of obj = %p as the sub object = %p!", obj, sobj);
934 }
935
936 if (_elm_widget_is(sobj))
937 {
938 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
939 if (sd2)
940 {
941 if (sd2->parent_obj == obj)
942 return;
943 if (sd2->parent_obj)
944 elm_widget_sub_object_del(sd2->parent_obj, sobj);
945 sd2->parent_obj = obj;
946 _elm_widget_top_win_focused_set(sobj, sd->top_win_focused);
947 if (!sd->child_can_focus && (_is_focusable(sobj)))
948 sd->child_can_focus = EINA_TRUE;
949 }
950 }
951 else
952 {
953 void *data = evas_object_data_get(sobj, "elm-parent");
954 if (data)
955 {
956 if (data == obj) return;
957 evas_object_event_callback_del(sobj, EVAS_CALLBACK_DEL,
958 _sub_obj_del);
959 }
960 }
961 sd->subobjs = eina_list_append(sd->subobjs, sobj);
962 evas_object_data_set(sobj, "elm-parent", obj);
963 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
964 if (_elm_widget_is(sobj))
965 evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE, _sub_obj_hide, sd);
966 evas_object_smart_callback_call(obj, "sub-object-add", sobj);
967 scale = elm_widget_scale_get(sobj);
968 th = elm_widget_theme_get(sobj);
969 mirrored = elm_widget_mirrored_get(sobj);
970 if ((scale != pscale) || (th != pth) || (pmirrored != mirrored)) elm_widget_theme(sobj);
971 if (elm_widget_focus_get(sobj)) _focus_parents(obj);
972}
973
974EAPI void
975elm_widget_sub_object_del(Evas_Object *obj,
976 Evas_Object *sobj)
977{
978 Evas_Object *sobj_parent;
979 API_ENTRY return;
980 if (!sobj) return;
981
982 sobj_parent = evas_object_data_del(sobj, "elm-parent");
983 if (sobj_parent != obj)
984 {
985 static int abort_on_warn = -1;
986 ERR("removing sub object %p (%s) from parent %p (%s), "
987 "but elm-parent is different %p (%s)!",
988 sobj, elm_widget_type_get(sobj), obj, elm_widget_type_get(obj),
989 sobj_parent, elm_widget_type_get(sobj_parent));
990 if (EINA_UNLIKELY(abort_on_warn == -1))
991 {
992 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
993 else abort_on_warn = 0;
994 }
995 if (abort_on_warn == 1) abort();
996 }
997 if (_elm_widget_is(sobj))
998 {
999 if (elm_widget_focus_get(sobj))
1000 {
1001 elm_widget_tree_unfocusable_set(sobj, EINA_TRUE);
1002 elm_widget_tree_unfocusable_set(sobj, EINA_FALSE);
1003 }
1004 if ((sd->child_can_focus) && (_is_focusable(sobj)))
1005 {
1006 Evas_Object *subobj;
1007 const Eina_List *l;
1008 sd->child_can_focus = EINA_FALSE;
1009 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1010 {
1011 if (_is_focusable(subobj))
1012 {
1013 sd->child_can_focus = EINA_TRUE;
1014 break;
1015 }
1016 }
1017 }
1018 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1019 if (sd2)
1020 {
1021 sd2->parent_obj = NULL;
1022 if (sd2->resize_obj == sobj)
1023 sd2->resize_obj = NULL;
1024 else
1025 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1026 }
1027 else
1028 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1029 }
1030 else
1031 sd->subobjs = eina_list_remove(sd->subobjs, sobj);
1032 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1033 _sub_obj_del, sd);
1034 if (_elm_widget_is(sobj))
1035 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1036 _sub_obj_hide, sd);
1037 evas_object_smart_callback_call(obj, "sub-object-del", sobj);
1038}
1039
1040EAPI const Eina_List *
1041elm_widget_sub_object_list_get(const Evas_Object *obj)
1042{
1043 API_ENTRY return NULL;
1044 return (const Eina_List *)sd->subobjs;
1045}
1046
1047EAPI void
1048elm_widget_resize_object_set(Evas_Object *obj,
1049 Evas_Object *sobj)
1050{
1051 API_ENTRY return;
1052 // orphan previous resize obj
1053 if (sd->resize_obj)
1054 {
1055 evas_object_clip_unset(sd->resize_obj);
1056 evas_object_data_del(sd->resize_obj, "elm-parent");
1057 if (_elm_widget_is(sd->resize_obj))
1058 {
1059 Smart_Data *sd2 = evas_object_smart_data_get(sd->resize_obj);
1060 if (sd2) sd2->parent_obj = NULL;
1061 evas_object_event_callback_del_full(sd->resize_obj,
1062 EVAS_CALLBACK_HIDE,
1063 _sub_obj_hide, sd);
1064 }
1065 evas_object_event_callback_del_full(sd->resize_obj, EVAS_CALLBACK_DEL,
1066 _sub_obj_del, sd);
1067 evas_object_event_callback_del_full(sd->resize_obj,
1068 EVAS_CALLBACK_MOUSE_DOWN,
1069 _sub_obj_mouse_down, sd);
1070 evas_object_event_callback_del_full(sd->resize_obj,
1071 EVAS_CALLBACK_MOUSE_MOVE,
1072 _sub_obj_mouse_move, sd);
1073 evas_object_event_callback_del_full(sd->resize_obj,
1074 EVAS_CALLBACK_MOUSE_UP,
1075 _sub_obj_mouse_up, sd);
1076 evas_object_smart_member_del(sd->resize_obj);
1077
1078 if (_elm_widget_is(sd->resize_obj))
1079 {
1080 if (elm_widget_focus_get(sd->resize_obj)) _unfocus_parents(obj);
1081 }
1082 }
1083
1084 sd->resize_obj = sobj;
1085 if (!sobj) return;
1086
1087 // orphan new resize obj
1088 evas_object_data_del(sobj, "elm-parent");
1089 if (_elm_widget_is(sobj))
1090 {
1091 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1092 if (sd2) sd2->parent_obj = NULL;
1093 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_HIDE,
1094 _sub_obj_hide, sd);
1095 }
1096 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL,
1097 _sub_obj_del, sd);
1098 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1099 _sub_obj_mouse_down, sd);
1100 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1101 _sub_obj_mouse_move, sd);
1102 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_MOUSE_UP,
1103 _sub_obj_mouse_up, sd);
1104 evas_object_smart_member_del(sobj);
1105 if (_elm_widget_is(sobj))
1106 {
1107 if (elm_widget_focus_get(sobj)) _unfocus_parents(obj);
1108 }
1109
1110 // set the resize obj up
1111 if (_elm_widget_is(sobj))
1112 {
1113 Smart_Data *sd2 = evas_object_smart_data_get(sobj);
1114 if (sd2)
1115 {
1116 sd2->parent_obj = obj;
1117 sd2->top_win_focused = sd->top_win_focused;
1118 }
1119 evas_object_event_callback_add(sobj, EVAS_CALLBACK_HIDE,
1120 _sub_obj_hide, sd);
1121 }
1122 evas_object_smart_member_add(sobj, obj);
1123 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1124 _sub_obj_del, sd);
1125 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_DOWN,
1126 _sub_obj_mouse_down, sd);
1127 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_MOVE,
1128 _sub_obj_mouse_move, sd);
1129 evas_object_event_callback_add(sobj, EVAS_CALLBACK_MOUSE_UP,
1130 _sub_obj_mouse_up, sd);
1131 _smart_reconfigure(sd);
1132 evas_object_data_set(sobj, "elm-parent", obj);
1133 evas_object_smart_callback_call(obj, "sub-object-add", sobj);
1134 if (_elm_widget_is(sobj))
1135 {
1136 if (elm_widget_focus_get(sobj)) _focus_parents(obj);
1137 }
1138}
1139
1140EAPI void
1141elm_widget_hover_object_set(Evas_Object *obj,
1142 Evas_Object *sobj)
1143{
1144 API_ENTRY return;
1145 if (sd->hover_obj)
1146 {
1147 evas_object_event_callback_del_full(sd->hover_obj, EVAS_CALLBACK_DEL,
1148 _sub_obj_del, sd);
1149 }
1150 sd->hover_obj = sobj;
1151 if (sd->hover_obj)
1152 {
1153 evas_object_event_callback_add(sobj, EVAS_CALLBACK_DEL,
1154 _sub_obj_del, sd);
1155 _smart_reconfigure(sd);
1156 }
1157}
1158
1159EAPI void
1160elm_widget_can_focus_set(Evas_Object *obj,
1161 Eina_Bool can_focus)
1162{
1163 API_ENTRY return;
1164
1165 can_focus = !!can_focus;
1166
1167 if (sd->can_focus == can_focus) return;
1168 sd->can_focus = can_focus;
1169 if (sd->can_focus)
1170 {
1171 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN,
1172 _propagate_event,
1173 (void *)(long)EVAS_CALLBACK_KEY_DOWN);
1174 evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP,
1175 _propagate_event,
1176 (void *)(long)EVAS_CALLBACK_KEY_UP);
1177 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1178 _propagate_event,
1179 (void *)(long)EVAS_CALLBACK_MOUSE_WHEEL);
1180 }
1181 else
1182 {
1183 evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_DOWN,
1184 _propagate_event);
1185 evas_object_event_callback_del(obj, EVAS_CALLBACK_KEY_UP,
1186 _propagate_event);
1187 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_WHEEL,
1188 _propagate_event);
1189 }
1190}
1191
1192EAPI Eina_Bool
1193elm_widget_can_focus_get(const Evas_Object *obj)
1194{
1195 API_ENTRY return EINA_FALSE;
1196 return sd->can_focus;
1197}
1198
1199EAPI Eina_Bool
1200elm_widget_child_can_focus_get(const Evas_Object *obj)
1201{
1202 API_ENTRY return EINA_FALSE;
1203 return sd->child_can_focus;
1204}
1205
1206/**
1207 * @internal
1208 *
1209 * This API makes the widget object and its children to be unfocusable.
1210 *
1211 * This API can be helpful for an object to be deleted.
1212 * When an object will be deleted soon, it and its children may not
1213 * want to get focus (by focus reverting or by other focus controls).
1214 * Then, just use this API before deleting.
1215 *
1216 * @param obj The widget root of sub-tree
1217 * @param tree_unfocusable If true, set the object sub-tree as unfocusable
1218 *
1219 * @ingroup Widget
1220 */
1221EAPI void
1222elm_widget_tree_unfocusable_set(Evas_Object *obj,
1223 Eina_Bool tree_unfocusable)
1224{
1225 API_ENTRY return;
1226
1227 tree_unfocusable = !!tree_unfocusable;
1228 if (sd->tree_unfocusable == tree_unfocusable) return;
1229 sd->tree_unfocusable = tree_unfocusable;
1230 elm_widget_focus_tree_unfocusable_handle(obj);
1231}
1232
1233/**
1234 * @internal
1235 *
1236 * This returns true, if the object sub-tree is unfocusable.
1237 *
1238 * @param obj The widget root of sub-tree
1239 * @return EINA_TRUE if the object sub-tree is unfocusable
1240 *
1241 * @ingroup Widget
1242 */
1243EAPI Eina_Bool
1244elm_widget_tree_unfocusable_get(const Evas_Object *obj)
1245{
1246 API_ENTRY return EINA_FALSE;
1247 return sd->tree_unfocusable;
1248}
1249
1250/**
1251 * @internal
1252 *
1253 * Get the list of focusable child objects.
1254 *
1255 * This function retruns list of child objects which can get focus.
1256 *
1257 * @param obj The parent widget
1258 * @retrun list of focusable child objects.
1259 *
1260 * @ingroup Widget
1261 */
1262EAPI Eina_List *
1263elm_widget_can_focus_child_list_get(const Evas_Object *obj)
1264{
1265 API_ENTRY return NULL;
1266
1267 const Eina_List *l;
1268 Eina_List *child_list = NULL;
1269 Evas_Object *child;
1270
1271 if (sd->subobjs)
1272 {
1273 EINA_LIST_FOREACH(sd->subobjs, l, child)
1274 {
1275 if ((elm_widget_can_focus_get(child)) &&
1276 (evas_object_visible_get(child)) &&
1277 (!elm_widget_disabled_get(child)))
1278 child_list = eina_list_append(child_list, child);
1279 else if (elm_widget_is(child))
1280 {
1281 Eina_List *can_focus_list;
1282 can_focus_list = elm_widget_can_focus_child_list_get(child);
1283 if (can_focus_list)
1284 child_list = eina_list_merge(child_list, can_focus_list);
1285 }
1286 }
1287 }
1288 return child_list;
1289}
1290
1291EAPI void
1292elm_widget_highlight_ignore_set(Evas_Object *obj,
1293 Eina_Bool ignore)
1294{
1295 API_ENTRY return;
1296 sd->highlight_ignore = !!ignore;
1297}
1298
1299EAPI Eina_Bool
1300elm_widget_highlight_ignore_get(const Evas_Object *obj)
1301{
1302 API_ENTRY return EINA_FALSE;
1303 return sd->highlight_ignore;
1304}
1305
1306EAPI void
1307elm_widget_highlight_in_theme_set(Evas_Object *obj,
1308 Eina_Bool highlight)
1309{
1310 API_ENTRY return;
1311 sd->highlight_in_theme = !!highlight;
1312 /* FIXME: if focused, it should switch from one mode to the other */
1313}
1314
1315EAPI Eina_Bool
1316elm_widget_highlight_in_theme_get(const Evas_Object *obj)
1317{
1318 API_ENTRY return EINA_FALSE;
1319 return sd->highlight_in_theme;
1320}
1321
1322EAPI Eina_Bool
1323elm_widget_focus_get(const Evas_Object *obj)
1324{
1325 API_ENTRY return EINA_FALSE;
1326 return sd->focused;
1327}
1328
1329EAPI Evas_Object *
1330elm_widget_focused_object_get(const Evas_Object *obj)
1331{
1332 const Evas_Object *subobj;
1333 const Eina_List *l;
1334 API_ENTRY return NULL;
1335
1336 if (!sd->focused) return NULL;
1337 EINA_LIST_FOREACH(sd->subobjs, l, subobj)
1338 {
1339 Evas_Object *fobj = elm_widget_focused_object_get(subobj);
1340 if (fobj) return fobj;
1341 }
1342 return (Evas_Object *)obj;
1343}
1344
1345EAPI Evas_Object *
1346elm_widget_top_get(const Evas_Object *obj)
1347{
1348 API_ENTRY return NULL;
1349 if (sd->parent_obj) return elm_widget_top_get(sd->parent_obj);
1350 return (Evas_Object *)obj;
1351}
1352
1353EAPI Eina_Bool
1354elm_widget_is(const Evas_Object *obj)
1355{
1356 return _elm_widget_is(obj);
1357}
1358
1359EAPI Evas_Object *
1360elm_widget_parent_widget_get(const Evas_Object *obj)
1361{
1362 Evas_Object *parent;
1363
1364 if (_elm_widget_is(obj))
1365 {
1366 Smart_Data *sd = evas_object_smart_data_get(obj);
1367 if (!sd) return NULL;
1368 parent = sd->parent_obj;
1369 }
1370 else
1371 {
1372 parent = evas_object_data_get(obj, "elm-parent");
1373 if (!parent) parent = evas_object_smart_parent_get(obj);
1374 }
1375
1376 while (parent)
1377 {
1378 Evas_Object *elm_parent;
1379 if (_elm_widget_is(parent)) break;
1380 elm_parent = evas_object_data_get(parent, "elm-parent");
1381 if (elm_parent) parent = elm_parent;
1382 else parent = evas_object_smart_parent_get(parent);
1383 }
1384 return parent;
1385}
1386
1387EAPI Evas_Object *
1388elm_widget_parent2_get(const Evas_Object *obj)
1389{
1390 if (_elm_widget_is(obj))
1391 {
1392 Smart_Data *sd = evas_object_smart_data_get(obj);
1393 if (sd) return sd->parent2;
1394 }
1395 return NULL;
1396}
1397
1398EAPI void
1399elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent)
1400{
1401 API_ENTRY return;
1402 sd->parent2 = parent;
1403}
1404
1405EAPI void
1406elm_widget_event_callback_add(Evas_Object *obj,
1407 Elm_Event_Cb func,
1408 const void *data)
1409{
1410 API_ENTRY return;
1411 EINA_SAFETY_ON_NULL_RETURN(func);
1412 Elm_Event_Cb_Data *ecb = ELM_NEW(Elm_Event_Cb_Data);
1413 ecb->func = func;
1414 ecb->data = data;
1415 sd->event_cb = eina_list_append(sd->event_cb, ecb);
1416}
1417
1418EAPI void *
1419elm_widget_event_callback_del(Evas_Object *obj,
1420 Elm_Event_Cb func,
1421 const void *data)
1422{
1423 API_ENTRY return NULL;
1424 EINA_SAFETY_ON_NULL_RETURN_VAL(func, NULL);
1425 Eina_List *l;
1426 Elm_Event_Cb_Data *ecd;
1427 EINA_LIST_FOREACH(sd->event_cb, l, ecd)
1428 if ((ecd->func == func) && (ecd->data == data))
1429 {
1430 free(ecd);
1431 sd->event_cb = eina_list_remove_list(sd->event_cb, l);
1432 return (void *)data;
1433 }
1434 return NULL;
1435}
1436
1437EAPI Eina_Bool
1438elm_widget_event_propagate(Evas_Object *obj,
1439 Evas_Callback_Type type,
1440 void *event_info,
1441 Evas_Event_Flags *event_flags)
1442{
1443 API_ENTRY return EINA_FALSE; //TODO reduce.
1444 if (!_elm_widget_is(obj)) return EINA_FALSE;
1445 Evas_Object *parent = obj;
1446 Elm_Event_Cb_Data *ecd;
1447 Eina_List *l, *l_prev;
1448
1449 while (parent &&
1450 (!(event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD))))
1451 {
1452 sd = evas_object_smart_data_get(parent);
1453 if ((!sd) || (!_elm_widget_is(obj)))
1454 return EINA_FALSE; //Not Elm Widget
1455
1456 if (sd->event_func && (sd->event_func(parent, obj, type, event_info)))
1457 return EINA_TRUE;
1458
1459 EINA_LIST_FOREACH_SAFE(sd->event_cb, l, l_prev, ecd)
1460 {
1461 if (ecd->func((void *)ecd->data, parent, obj, type, event_info) ||
1462 (event_flags && ((*event_flags) & EVAS_EVENT_FLAG_ON_HOLD)))
1463 return EINA_TRUE;
1464 }
1465 parent = sd->parent_obj;
1466 }
1467
1468 return EINA_FALSE;
1469}
1470
1471/**
1472 * @internal
1473 *
1474 * Set custom focus chain.
1475 *
1476 * This function i set one new and overwrite any previous custom focus chain
1477 * with the list of objects. The previous list will be deleted and this list
1478 * will be managed. After setted, don't modity it.
1479 *
1480 * @note On focus cycle, only will be evaluated children of this container.
1481 *
1482 * @param obj The container widget
1483 * @param objs Chain of objects to pass focus
1484 * @ingroup Widget
1485 */
1486EAPI void
1487elm_widget_focus_custom_chain_set(Evas_Object *obj,
1488 Eina_List *objs)
1489{
1490 API_ENTRY return;
1491 if (!sd->focus_next_func)
1492 return;
1493
1494 elm_widget_focus_custom_chain_unset(obj);
1495
1496 Eina_List *l;
1497 Evas_Object *o;
1498
1499 EINA_LIST_FOREACH(objs, l, o)
1500 {
1501 evas_object_event_callback_add(o, EVAS_CALLBACK_DEL,
1502 _elm_object_focus_chain_del_cb, sd);
1503 }
1504
1505 sd->focus_chain = objs;
1506}
1507
1508/**
1509 * @internal
1510 *
1511 * Get custom focus chain
1512 *
1513 * @param obj The container widget
1514 * @ingroup Widget
1515 */
1516EAPI const Eina_List *
1517elm_widget_focus_custom_chain_get(const Evas_Object *obj)
1518{
1519 API_ENTRY return NULL;
1520 return (const Eina_List *)sd->focus_chain;
1521}
1522
1523/**
1524 * @internal
1525 *
1526 * Unset custom focus chain
1527 *
1528 * @param obj The container widget
1529 * @ingroup Widget
1530 */
1531EAPI void
1532elm_widget_focus_custom_chain_unset(Evas_Object *obj)
1533{
1534 API_ENTRY return;
1535 Eina_List *l, *l_next;
1536 Evas_Object *o;
1537
1538 EINA_LIST_FOREACH_SAFE(sd->focus_chain, l, l_next, o)
1539 {
1540 evas_object_event_callback_del_full(o, EVAS_CALLBACK_DEL,
1541 _elm_object_focus_chain_del_cb, sd);
1542 sd->focus_chain = eina_list_remove_list(sd->focus_chain, l);
1543 }
1544}
1545
1546/**
1547 * @internal
1548 *
1549 * Append object to custom focus chain.
1550 *
1551 * @note If relative_child equal to NULL or not in custom chain, the object
1552 * will be added in end.
1553 *
1554 * @note On focus cycle, only will be evaluated children of this container.
1555 *
1556 * @param obj The container widget
1557 * @param child The child to be added in custom chain
1558 * @param relative_child The relative object to position the child
1559 * @ingroup Widget
1560 */
1561EAPI void
1562elm_widget_focus_custom_chain_append(Evas_Object *obj,
1563 Evas_Object *child,
1564 Evas_Object *relative_child)
1565{
1566 API_ENTRY return;
1567 EINA_SAFETY_ON_NULL_RETURN(child);
1568 if (!sd->focus_next_func) return;
1569
1570 evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1571 _elm_object_focus_chain_del_cb, sd);
1572
1573 if (!relative_child)
1574 sd->focus_chain = eina_list_append(sd->focus_chain, child);
1575 else
1576 sd->focus_chain = eina_list_append_relative(sd->focus_chain,
1577 child, relative_child);
1578}
1579
1580/**
1581 * @internal
1582 *
1583 * Prepend object to custom focus chain.
1584 *
1585 * @note If relative_child equal to NULL or not in custom chain, the object
1586 * will be added in begin.
1587 *
1588 * @note On focus cycle, only will be evaluated children of this container.
1589 *
1590 * @param obj The container widget
1591 * @param child The child to be added in custom chain
1592 * @param relative_child The relative object to position the child
1593 * @ingroup Widget
1594 */
1595EAPI void
1596elm_widget_focus_custom_chain_prepend(Evas_Object *obj,
1597 Evas_Object *child,
1598 Evas_Object *relative_child)
1599{
1600 API_ENTRY return;
1601 EINA_SAFETY_ON_NULL_RETURN(child);
1602
1603 if (!sd->focus_next_func) return;
1604
1605 evas_object_event_callback_del_full(child, EVAS_CALLBACK_DEL,
1606 _elm_object_focus_chain_del_cb, sd);
1607
1608 if (!relative_child)
1609 sd->focus_chain = eina_list_prepend(sd->focus_chain, child);
1610 else
1611 sd->focus_chain = eina_list_prepend_relative(sd->focus_chain,
1612 child, relative_child);
1613}
1614
1615/**
1616 * @internal
1617 *
1618 * Give focus to next object in object tree.
1619 *
1620 * Give focus to next object in focus chain of one object sub-tree.
1621 * If the last object of chain already have focus, the focus will go to the
1622 * first object of chain.
1623 *
1624 * @param obj The widget root of sub-tree
1625 * @param dir Direction to cycle the focus
1626 *
1627 * @ingroup Widget
1628 */
1629EAPI void
1630elm_widget_focus_cycle(Evas_Object *obj,
1631 Elm_Focus_Direction dir)
1632{
1633 Evas_Object *target = NULL;
1634 if (!_elm_widget_is(obj))
1635 return;
1636 elm_widget_focus_next_get(obj, dir, &target);
1637 if (target)
1638 elm_widget_focus_steal(target);
1639}
1640
1641/**
1642 * @internal
1643 *
1644 * Give focus to near object in one direction.
1645 *
1646 * Give focus to near object in direction of one object.
1647 * If none focusable object in given direction, the focus will not change.
1648 *
1649 * @param obj The reference widget
1650 * @param x Horizontal component of direction to focus
1651 * @param y Vertical component of direction to focus
1652 *
1653 * @ingroup Widget
1654 */
1655//FIXME: If x, y indicates the elements of the directional vector,
1656//It would be better if these values are the normalized value(float x, float y)
1657//or degree.
1658EINA_DEPRECATED EAPI void
1659elm_widget_focus_direction_go(Evas_Object *obj __UNUSED__,
1660 int x __UNUSED__,
1661 int y __UNUSED__)
1662{
1663 return; /* TODO */
1664}
1665
1666/**
1667 * @internal
1668 *
1669 * Get next object in focus chain of object tree.
1670 *
1671 * Get next object in focus chain of one object sub-tree.
1672 * Return the next object by reference. If don't have any candidate to receive
1673 * focus before chain end, the first candidate will be returned.
1674 *
1675 * @param obj The widget root of sub-tree
1676 * @param dir Direction os focus chain
1677 * @param next The next object in focus chain
1678 * @return EINA_TRUE if don't need focus chain restart/loop back
1679 * to use 'next' obj.
1680 *
1681 * @ingroup Widget
1682 */
1683EAPI Eina_Bool
1684elm_widget_focus_next_get(const Evas_Object *obj,
1685 Elm_Focus_Direction dir,
1686 Evas_Object **next)
1687{
1688 if (!next)
1689 return EINA_FALSE;
1690 *next = NULL;
1691
1692 API_ENTRY return EINA_FALSE;
1693
1694 /* Ignore if disabled */
1695 if ((!evas_object_visible_get(obj))
1696 || (elm_widget_disabled_get(obj))
1697 || (elm_widget_tree_unfocusable_get(obj)))
1698 return EINA_FALSE;
1699
1700 /* Try use hook */
1701 if (sd->focus_next_func)
1702 return sd->focus_next_func(obj, dir, next);
1703
1704 if (!elm_widget_can_focus_get(obj))
1705 return EINA_FALSE;
1706
1707 /* Return */
1708 *next = (Evas_Object *)obj;
1709 return !elm_widget_focus_get(obj);
1710}
1711
1712/**
1713 * @internal
1714 *
1715 * Get next object in focus chain of object tree in list.
1716 *
1717 * Get next object in focus chain of one object sub-tree ordered by one list.
1718 * Return the next object by reference. If don't have any candidate to receive
1719 * focus before list end, the first candidate will be returned.
1720 *
1721 * @param obj The widget root of sub-tree
1722 * @param dir Direction os focus chain
1723 * @param items list with ordered objects
1724 * @param list_data_get function to get the object from one item of list
1725 * @param next The next object in focus chain
1726 * @return EINA_TRUE if don't need focus chain restart/loop back
1727 * to use 'next' obj.
1728 *
1729 * @ingroup Widget
1730 */
1731EAPI Eina_Bool
1732elm_widget_focus_list_next_get(const Evas_Object *obj,
1733 const Eina_List *items,
1734 void *(*list_data_get)(const Eina_List * list),
1735 Elm_Focus_Direction dir,
1736 Evas_Object **next)
1737{
1738 Eina_List *(*list_next)(const Eina_List * list) = NULL;
1739
1740 if (!next)
1741 return EINA_FALSE;
1742 *next = NULL;
1743
1744 if (!_elm_widget_is(obj))
1745 return EINA_FALSE;
1746
1747 if (!items)
1748 return EINA_FALSE;
1749
1750 /* Direction */
1751 if (dir == ELM_FOCUS_PREVIOUS)
1752 {
1753 items = eina_list_last(items);
1754 list_next = eina_list_prev;
1755 }
1756 else if (dir == ELM_FOCUS_NEXT)
1757 list_next = eina_list_next;
1758 else
1759 return EINA_FALSE;
1760
1761 const Eina_List *l = items;
1762
1763 /* Recovery last focused sub item */
1764 if (elm_widget_focus_get(obj))
1765 for (; l; l = list_next(l))
1766 {
1767 Evas_Object *cur = list_data_get(l);
1768 if (elm_widget_focus_get(cur)) break;
1769 }
1770
1771 const Eina_List *start = l;
1772 Evas_Object *to_focus = NULL;
1773
1774 /* Interate sub items */
1775 /* Go to end of list */
1776 for (; l; l = list_next(l))
1777 {
1778 Evas_Object *tmp = NULL;
1779 Evas_Object *cur = list_data_get(l);
1780
1781 if (elm_widget_parent_get(cur) != obj)
1782 continue;
1783
1784 /* Try Focus cycle in subitem */
1785 if (elm_widget_focus_next_get(cur, dir, &tmp))
1786 {
1787 *next = tmp;
1788 return EINA_TRUE;
1789 }
1790 else if ((tmp) && (!to_focus))
1791 to_focus = tmp;
1792 }
1793
1794 l = items;
1795
1796 /* Get First possible */
1797 for (; l != start; l = list_next(l))
1798 {
1799 Evas_Object *tmp = NULL;
1800 Evas_Object *cur = list_data_get(l);
1801
1802 if (elm_widget_parent_get(cur) != obj)
1803 continue;
1804
1805 /* Try Focus cycle in subitem */
1806 elm_widget_focus_next_get(cur, dir, &tmp);
1807 if (tmp)
1808 {
1809 *next = tmp;
1810 return EINA_FALSE;
1811 }
1812 }
1813
1814 *next = to_focus;
1815 return EINA_FALSE;
1816}
1817
1818EAPI void
1819elm_widget_signal_emit(Evas_Object *obj,
1820 const char *emission,
1821 const char *source)
1822{
1823 API_ENTRY return;
1824 if (!sd->signal_func) return;
1825 sd->signal_func(obj, emission, source);
1826}
1827
1828static void
1829_edje_signal_callback(void *data,
1830 Evas_Object *obj __UNUSED__,
1831 const char *emission,
1832 const char *source)
1833{
1834 Edje_Signal_Data *esd = data;
1835 esd->func(esd->data, esd->obj, emission, source);
1836}
1837
1838EAPI void
1839elm_widget_signal_callback_add(Evas_Object *obj,
1840 const char *emission,
1841 const char *source,
1842 Edje_Signal_Cb func,
1843 void *data)
1844{
1845 Edje_Signal_Data *esd;
1846 API_ENTRY return;
1847 if (!sd->callback_add_func) return;
1848 EINA_SAFETY_ON_NULL_RETURN(func);
1849
1850 esd = ELM_NEW(Edje_Signal_Data);
1851 if (!esd) return;
1852
1853 esd->obj = obj;
1854 esd->func = func;
1855 esd->emission = eina_stringshare_add(emission);
1856 esd->source = eina_stringshare_add(source);
1857 esd->data = data;
1858 sd->edje_signals = eina_list_append(sd->edje_signals, esd);
1859 sd->callback_add_func(obj, emission, source, _edje_signal_callback, esd);
1860}
1861
1862EAPI void *
1863elm_widget_signal_callback_del(Evas_Object *obj,
1864 const char *emission,
1865 const char *source,
1866 Edje_Signal_Cb func)
1867{
1868 Edje_Signal_Data *esd;
1869 Eina_List *l;
1870 void *data = NULL;
1871 API_ENTRY return NULL;
1872 if (!sd->callback_del_func) return NULL;
1873
1874 EINA_LIST_FOREACH(sd->edje_signals, l, esd)
1875 {
1876 if ((esd->func == func) && (!strcmp(esd->emission, emission)) &&
1877 (!strcmp(esd->source, source)))
1878 {
1879 sd->edje_signals = eina_list_remove_list(sd->edje_signals, l);
1880 eina_stringshare_del(esd->emission);
1881 eina_stringshare_del(esd->source);
1882 data = esd->data;
1883 free(esd);
1884
1885 sd->callback_del_func
1886 (obj, emission, source, _edje_signal_callback, esd);
1887 return data;
1888 }
1889 }
1890
1891 return data;
1892}
1893
1894EAPI void
1895elm_widget_focus_set(Evas_Object *obj,
1896 int first)
1897{
1898 API_ENTRY return;
1899 if (!sd->focused)
1900 {
1901 focus_order++;
1902 sd->focus_order = focus_order;
1903 sd->focused = EINA_TRUE;
1904 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1905 }
1906 if (sd->focus_func)
1907 {
1908 sd->focus_func(obj);
1909 return;
1910 }
1911 else
1912 {
1913 if (first)
1914 {
1915 if ((_is_focusable(sd->resize_obj)) &&
1916 (!elm_widget_disabled_get(sd->resize_obj)))
1917 {
1918 elm_widget_focus_set(sd->resize_obj, first);
1919 }
1920 else
1921 {
1922 const Eina_List *l;
1923 Evas_Object *child;
1924 EINA_LIST_FOREACH(sd->subobjs, l, child)
1925 {
1926 if ((_is_focusable(child)) &&
1927 (!elm_widget_disabled_get(child)))
1928 {
1929 elm_widget_focus_set(child, first);
1930 break;
1931 }
1932 }
1933 }
1934 }
1935 else
1936 {
1937 const Eina_List *l;
1938 Evas_Object *child;
1939 EINA_LIST_REVERSE_FOREACH(sd->subobjs, l, child)
1940 {
1941 if ((_is_focusable(child)) &&
1942 (!elm_widget_disabled_get(child)))
1943 {
1944 elm_widget_focus_set(child, first);
1945 break;
1946 }
1947 }
1948 if (!l)
1949 {
1950 if ((_is_focusable(sd->resize_obj)) &&
1951 (!elm_widget_disabled_get(sd->resize_obj)))
1952 {
1953 elm_widget_focus_set(sd->resize_obj, first);
1954 }
1955 }
1956 }
1957 }
1958}
1959
1960EAPI Evas_Object *
1961elm_widget_parent_get(const Evas_Object *obj)
1962{
1963 API_ENTRY return NULL;
1964 return sd->parent_obj;
1965}
1966
1967EAPI void
1968elm_widget_focused_object_clear(Evas_Object *obj)
1969{
1970 API_ENTRY return;
1971 if (!sd->focused) return;
1972 if (sd->resize_obj && elm_widget_focus_get(sd->resize_obj))
1973 elm_widget_focused_object_clear(sd->resize_obj);
1974 else
1975 {
1976 const Eina_List *l;
1977 Evas_Object *child;
1978 EINA_LIST_FOREACH(sd->subobjs, l, child)
1979 {
1980 if (elm_widget_focus_get(child))
1981 {
1982 elm_widget_focused_object_clear(child);
1983 break;
1984 }
1985 }
1986 }
1987 sd->focused = EINA_FALSE;
1988 if (sd->on_focus_func) sd->on_focus_func(sd->on_focus_data, obj);
1989 if (sd->focus_func) sd->focus_func(obj);
1990}
1991
1992EAPI void
1993elm_widget_focus_steal(Evas_Object *obj)
1994{
1995 Evas_Object *parent, *parent2, *o;
1996 API_ENTRY return;
1997
1998 if (sd->focused) return;
1999 if (sd->disabled) return;
2000 if (!sd->can_focus) return;
2001 if (sd->tree_unfocusable) return;
2002 parent = obj;
2003 for (;;)
2004 {
2005 o = elm_widget_parent_get(parent);
2006 if (!o) break;
2007 sd = evas_object_smart_data_get(o);
2008 if (sd->disabled || sd->tree_unfocusable) return;
2009 if (sd->focused) break;
2010 parent = o;
2011 }
2012 if ((!elm_widget_parent_get(parent)) &&
2013 (!elm_widget_parent2_get(parent)))
2014 elm_widget_focused_object_clear(parent);
2015 else
2016 {
2017 parent2 = elm_widget_parent_get(parent);
2018 if (!parent2) parent2 = elm_widget_parent2_get(parent);
2019 parent = parent2;
2020 sd = evas_object_smart_data_get(parent);
2021 if (sd)
2022 {
2023 if ((sd->resize_obj) && (elm_widget_focus_get(sd->resize_obj)))
2024 elm_widget_focused_object_clear(sd->resize_obj);
2025 else
2026 {
2027 const Eina_List *l;
2028 Evas_Object *child;
2029 EINA_LIST_FOREACH(sd->subobjs, l, child)
2030 {
2031 if (elm_widget_focus_get(child))
2032 {
2033 elm_widget_focused_object_clear(child);
2034 break;
2035 }
2036 }
2037 }
2038 }
2039 }
2040 _parent_focus(obj);
2041 return;
2042}
2043
2044EAPI void
2045elm_widget_focus_restore(Evas_Object *obj)
2046{
2047 Evas_Object *newest = NULL;
2048 unsigned int newest_focus_order = 0;
2049 API_ENTRY return;
2050
2051 newest = _newest_focus_order_get(obj, &newest_focus_order, EINA_TRUE);
2052 if (newest)
2053 {
2054 elm_object_focus_set(newest, EINA_FALSE);
2055 elm_object_focus_set(newest, EINA_TRUE);
2056 }
2057}
2058
2059void
2060_elm_widget_top_win_focused_set(Evas_Object *obj, Eina_Bool top_win_focused)
2061{
2062 const Eina_List *l;
2063 Evas_Object *child;
2064 API_ENTRY return;
2065
2066 if (sd->top_win_focused == top_win_focused) return;
2067 if (sd->resize_obj)
2068 _elm_widget_top_win_focused_set(sd->resize_obj, top_win_focused);
2069 EINA_LIST_FOREACH(sd->subobjs, l, child)
2070 {
2071 _elm_widget_top_win_focused_set(child, top_win_focused);
2072 }
2073 sd->top_win_focused = top_win_focused;
2074}
2075
2076Eina_Bool
2077_elm_widget_top_win_focused_get(const Evas_Object *obj)
2078{
2079 API_ENTRY return EINA_FALSE;
2080 return sd->top_win_focused;
2081}
2082
2083EAPI void
2084elm_widget_activate(Evas_Object *obj)
2085{
2086 API_ENTRY return;
2087 elm_widget_change(obj);
2088 if (sd->activate_func) sd->activate_func(obj);
2089}
2090
2091EAPI void
2092elm_widget_change(Evas_Object *obj)
2093{
2094 API_ENTRY return;
2095 elm_widget_change(elm_widget_parent_get(obj));
2096 if (sd->on_change_func) sd->on_change_func(sd->on_change_data, obj);
2097}
2098
2099EAPI void
2100elm_widget_disabled_set(Evas_Object *obj,
2101 Eina_Bool disabled)
2102{
2103 API_ENTRY return;
2104
2105 if (sd->disabled == disabled) return;
2106 sd->disabled = !!disabled;
2107 elm_widget_focus_disabled_handle(obj);
2108 if (sd->disable_func) sd->disable_func(obj);
2109}
2110
2111EAPI Eina_Bool
2112elm_widget_disabled_get(const Evas_Object *obj)
2113{
2114 API_ENTRY return 0;
2115 return sd->disabled;
2116}
2117
2118EAPI void
2119elm_widget_show_region_set(Evas_Object *obj,
2120 Evas_Coord x,
2121 Evas_Coord y,
2122 Evas_Coord w,
2123 Evas_Coord h,
2124 Eina_Bool forceshow)
2125{
2126 Evas_Object *parent_obj, *child_obj;
2127 Evas_Coord px, py, cx, cy;
2128
2129 API_ENTRY return;
2130
2131 evas_smart_objects_calculate(evas_object_evas_get(obj));
2132
2133 if (!forceshow && (x == sd->rx) && (y == sd->ry) &&
2134 (w == sd->rw) && (h == sd->rh)) return;
2135 sd->rx = x;
2136 sd->ry = y;
2137 sd->rw = w;
2138 sd->rh = h;
2139 if (sd->on_show_region_func)
2140 sd->on_show_region_func(sd->on_show_region_data, obj);
2141
2142 do
2143 {
2144 parent_obj = sd->parent_obj;
2145 child_obj = sd->obj;
2146 if ((!parent_obj) || (!_elm_widget_is(parent_obj))) break;
2147 sd = evas_object_smart_data_get(parent_obj);
2148 if (!sd) break;
2149
2150 evas_object_geometry_get(parent_obj, &px, &py, NULL, NULL);
2151 evas_object_geometry_get(child_obj, &cx, &cy, NULL, NULL);
2152
2153 x += (cx - px);
2154 y += (cy - py);
2155 sd->rx = x;
2156 sd->ry = y;
2157 sd->rw = w;
2158 sd->rh = h;
2159
2160 if (sd->on_show_region_func)
2161 {
2162 sd->on_show_region_func(sd->on_show_region_data, parent_obj);
2163 }
2164 }
2165 while (parent_obj);
2166}
2167
2168EAPI void
2169elm_widget_show_region_get(const Evas_Object *obj,
2170 Evas_Coord *x,
2171 Evas_Coord *y,
2172 Evas_Coord *w,
2173 Evas_Coord *h)
2174{
2175 API_ENTRY return;
2176 if (x) *x = sd->rx;
2177 if (y) *y = sd->ry;
2178 if (w) *w = sd->rw;
2179 if (h) *h = sd->rh;
2180}
2181
2182/**
2183 * @internal
2184 *
2185 * Get the focus region of the given widget.
2186 *
2187 * The focus region is the area of a widget that should brought into the
2188 * visible area when the widget is focused. Mostly used to show the part of
2189 * an entry where the cursor is, for example. The area returned is relative
2190 * to the object @p obj.
2191 * If the @p obj doesn't have the proper on_focus_region_hook set, this
2192 * function will return the full size of the object.
2193 *
2194 * @param obj The widget object
2195 * @param x Where to store the x coordinate of the area
2196 * @param y Where to store the y coordinate of the area
2197 * @param w Where to store the width of the area
2198 * @param h Where to store the height of the area
2199 *
2200 * @ingroup Widget
2201 */
2202EAPI void
2203elm_widget_focus_region_get(const Evas_Object *obj,
2204 Evas_Coord *x,
2205 Evas_Coord *y,
2206 Evas_Coord *w,
2207 Evas_Coord *h)
2208{
2209 Smart_Data *sd;
2210
2211 if (!obj) return;
2212
2213 sd = evas_object_smart_data_get(obj);
2214 if (!sd || !_elm_widget_is(obj) || !sd->on_focus_region_func)
2215 {
2216 evas_object_geometry_get(obj, NULL, NULL, w, h);
2217 if (x) *x = 0;
2218 if (y) *y = 0;
2219 return;
2220 }
2221 sd->on_focus_region_func(obj, x, y, w, h);
2222}
2223
2224EAPI void
2225elm_widget_scroll_hold_push(Evas_Object *obj)
2226{
2227 API_ENTRY return;
2228 sd->scroll_hold++;
2229 if (sd->scroll_hold == 1)
2230 evas_object_smart_callback_call(obj, "scroll-hold-on", obj);
2231 if (sd->parent_obj) elm_widget_scroll_hold_push(sd->parent_obj);
2232 // FIXME: on delete/reparent hold pop
2233}
2234
2235EAPI void
2236elm_widget_scroll_hold_pop(Evas_Object *obj)
2237{
2238 API_ENTRY return;
2239 sd->scroll_hold--;
2240 if (!sd->scroll_hold)
2241 evas_object_smart_callback_call(obj, "scroll-hold-off", obj);
2242 if (sd->parent_obj) elm_widget_scroll_hold_pop(sd->parent_obj);
2243 if (sd->scroll_hold < 0) sd->scroll_hold = 0;
2244}
2245
2246EAPI int
2247elm_widget_scroll_hold_get(const Evas_Object *obj)
2248{
2249 API_ENTRY return 0;
2250 return sd->scroll_hold;
2251}
2252
2253EAPI void
2254elm_widget_scroll_freeze_push(Evas_Object *obj)
2255{
2256 API_ENTRY return;
2257 sd->scroll_freeze++;
2258 if (sd->scroll_freeze == 1)
2259 evas_object_smart_callback_call(obj, "scroll-freeze-on", obj);
2260 if (sd->parent_obj) elm_widget_scroll_freeze_push(sd->parent_obj);
2261 // FIXME: on delete/reparent freeze pop
2262}
2263
2264EAPI void
2265elm_widget_scroll_freeze_pop(Evas_Object *obj)
2266{
2267 API_ENTRY return;
2268 sd->scroll_freeze--;
2269 if (!sd->scroll_freeze)
2270 evas_object_smart_callback_call(obj, "scroll-freeze-off", obj);
2271 if (sd->parent_obj) elm_widget_scroll_freeze_pop(sd->parent_obj);
2272 if (sd->scroll_freeze < 0) sd->scroll_freeze = 0;
2273}
2274
2275EAPI int
2276elm_widget_scroll_freeze_get(const Evas_Object *obj)
2277{
2278 API_ENTRY return 0;
2279 return sd->scroll_freeze;
2280}
2281
2282EAPI void
2283elm_widget_scale_set(Evas_Object *obj,
2284 double scale)
2285{
2286 API_ENTRY return;
2287 if (scale <= 0.0) scale = 0.0;
2288 if (sd->scale != scale)
2289 {
2290 sd->scale = scale;
2291 elm_widget_theme(obj);
2292 }
2293}
2294
2295EAPI double
2296elm_widget_scale_get(const Evas_Object *obj)
2297{
2298 API_ENTRY return 1.0;
2299 // FIXME: save walking up the tree by storing/caching parent scale
2300 if (sd->scale == 0.0)
2301 {
2302 if (sd->parent_obj)
2303 return elm_widget_scale_get(sd->parent_obj);
2304 else
2305 return 1.0;
2306 }
2307 return sd->scale;
2308}
2309
2310EAPI void
2311elm_widget_theme_set(Evas_Object *obj,
2312 Elm_Theme *th)
2313{
2314 API_ENTRY return;
2315 if (sd->theme != th)
2316 {
2317 if (sd->theme) elm_theme_free(sd->theme);
2318 sd->theme = th;
2319 if (th) th->ref++;
2320 elm_widget_theme(obj);
2321 }
2322}
2323
2324EAPI void
2325elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label)
2326{
2327 API_ENTRY return;
2328
2329 if (!sd->text_set_func)
2330 return;
2331
2332 sd->text_set_func(obj, part, label);
2333}
2334
2335EAPI const char *
2336elm_widget_text_part_get(const Evas_Object *obj, const char *part)
2337{
2338 API_ENTRY return NULL;
2339
2340 if (!sd->text_get_func)
2341 return NULL;
2342
2343 return sd->text_get_func(obj, part);
2344}
2345
2346EAPI void
2347elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *label)
2348{
2349 const char *str;
2350 Eina_List *l;
2351 Elm_Translate_String_Data *ts = NULL;
2352 API_ENTRY return;
2353
2354 str = eina_stringshare_add(part);
2355 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2356 if (ts->id == str)
2357 break;
2358 else
2359 ts = NULL;
2360
2361 if (!ts && !label)
2362 eina_stringshare_del(str);
2363 else if (!ts)
2364 {
2365 ts = malloc(sizeof(Elm_Translate_String_Data));
2366 if (!ts) return;
2367
2368 ts->id = str;
2369 ts->domain = eina_stringshare_add(domain);
2370 ts->string = eina_stringshare_add(label);
2371 sd->translate_strings = eina_list_append(sd->translate_strings, ts);
2372 }
2373 else
2374 {
2375 if (label)
2376 {
2377 eina_stringshare_replace(&ts->domain, domain);
2378 eina_stringshare_replace(&ts->string, label);
2379 }
2380 else
2381 {
2382 sd->translate_strings = eina_list_remove_list(
2383 sd->translate_strings, l);
2384 eina_stringshare_del(ts->id);
2385 eina_stringshare_del(ts->domain);
2386 eina_stringshare_del(ts->string);
2387 free(ts);
2388 }
2389 eina_stringshare_del(str);
2390 }
2391
2392#ifdef HAVE_GETTEXT
2393 if (label && label[0])
2394 label = dgettext(domain, label);
2395#endif
2396 elm_widget_text_part_set(obj, part, label);
2397}
2398
2399EAPI const char *
2400elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part)
2401{
2402 const char *str, *ret = NULL;
2403 Eina_List *l;
2404 Elm_Translate_String_Data *ts;
2405 API_ENTRY return NULL;
2406
2407 str = eina_stringshare_add(part);
2408 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2409 if (ts->id == str)
2410 {
2411 ret = ts->string;
2412 break;
2413 }
2414 eina_stringshare_del(str);
2415 return ret;
2416}
2417
2418EAPI void
2419elm_widget_translate(Evas_Object *obj)
2420{
2421 const Eina_List *l;
2422 Evas_Object *child;
2423#ifdef HAVE_GETTEXT
2424 Elm_Translate_String_Data *ts;
2425#endif
2426
2427 API_ENTRY return;
2428 EINA_LIST_FOREACH(sd->subobjs, l, child) elm_widget_translate(child);
2429 if (sd->resize_obj) elm_widget_translate(sd->resize_obj);
2430 if (sd->hover_obj) elm_widget_translate(sd->hover_obj);
2431 if (sd->translate_func) sd->translate_func(obj);
2432
2433#ifdef HAVE_GETTEXT
2434 EINA_LIST_FOREACH(sd->translate_strings, l, ts)
2435 {
2436 const char *s = dgettext(ts->domain, ts->string);
2437 elm_widget_text_part_set(obj, ts->id, s);
2438 }
2439#endif
2440}
2441
2442EAPI void
2443elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content)
2444{
2445 API_ENTRY return;
2446
2447 if (!sd->content_set_func) return;
2448 sd->content_set_func(obj, part, content);
2449}
2450
2451EAPI Evas_Object *
2452elm_widget_content_part_get(const Evas_Object *obj, const char *part)
2453{
2454 API_ENTRY return NULL;
2455
2456 if (!sd->content_get_func) return NULL;
2457 return sd->content_get_func(obj, part);
2458}
2459
2460EAPI Evas_Object *
2461elm_widget_content_part_unset(Evas_Object *obj, const char *part)
2462{
2463 API_ENTRY return NULL;
2464
2465 if (!sd->content_unset_func) return NULL;
2466 return sd->content_unset_func(obj, part);
2467}
2468
2469EAPI void
2470elm_widget_access_info_set(Evas_Object *obj, const char *txt)
2471{
2472 API_ENTRY return;
2473 if (sd->access_info) eina_stringshare_del(sd->access_info);
2474 if (!txt) sd->access_info = NULL;
2475 else sd->access_info = eina_stringshare_add(txt);
2476}
2477
2478EAPI const char *
2479elm_widget_access_info_get(const Evas_Object *obj)
2480{
2481 API_ENTRY return NULL;
2482 return sd->access_info;
2483}
2484
2485EAPI Elm_Theme *
2486elm_widget_theme_get(const Evas_Object *obj)
2487{
2488 API_ENTRY return NULL;
2489 if (!sd->theme)
2490 {
2491 if (sd->parent_obj)
2492 return elm_widget_theme_get(sd->parent_obj);
2493 else
2494 return NULL;
2495 }
2496 return sd->theme;
2497}
2498
2499EAPI Eina_Bool
2500elm_widget_style_set(Evas_Object *obj,
2501 const char *style)
2502{
2503 API_ENTRY return EINA_FALSE;
2504
2505 if (eina_stringshare_replace(&sd->style, style))
2506 return elm_widget_theme(obj);
2507
2508 return EINA_TRUE;
2509}
2510
2511EAPI const char *
2512elm_widget_style_get(const Evas_Object *obj)
2513{
2514 API_ENTRY return NULL;
2515 if (sd->style) return sd->style;
2516 return "default";
2517}
2518
2519EAPI void
2520elm_widget_type_set(Evas_Object *obj,
2521 const char *type)
2522{
2523 API_ENTRY return;
2524 eina_stringshare_replace(&sd->type, type);
2525}
2526
2527EAPI const char *
2528elm_widget_type_get(const Evas_Object *obj)
2529{
2530 API_ENTRY return NULL;
2531 if (sd->type) return sd->type;
2532 return "";
2533}
2534
2535EAPI void
2536elm_widget_tooltip_add(Evas_Object *obj,
2537 Elm_Tooltip *tt)
2538{
2539 API_ENTRY return;
2540 sd->tooltips = eina_list_append(sd->tooltips, tt);
2541}
2542
2543EAPI void
2544elm_widget_tooltip_del(Evas_Object *obj,
2545 Elm_Tooltip *tt)
2546{
2547 API_ENTRY return;
2548 sd->tooltips = eina_list_remove(sd->tooltips, tt);
2549}
2550
2551EAPI void
2552elm_widget_cursor_add(Evas_Object *obj,
2553 Elm_Cursor *cur)
2554{
2555 API_ENTRY return;
2556 sd->cursors = eina_list_append(sd->cursors, cur);
2557}
2558
2559EAPI void
2560elm_widget_cursor_del(Evas_Object *obj,
2561 Elm_Cursor *cur)
2562{
2563 API_ENTRY return;
2564 sd->cursors = eina_list_remove(sd->cursors, cur);
2565}
2566
2567EAPI void
2568elm_widget_drag_lock_x_set(Evas_Object *obj,
2569 Eina_Bool lock)
2570{
2571 API_ENTRY return;
2572 if (sd->drag_x_locked == lock) return;
2573 sd->drag_x_locked = lock;
2574 if (sd->drag_x_locked) _propagate_x_drag_lock(obj, 1);
2575 else _propagate_x_drag_lock(obj, -1);
2576}
2577
2578EAPI void
2579elm_widget_drag_lock_y_set(Evas_Object *obj,
2580 Eina_Bool lock)
2581{
2582 API_ENTRY return;
2583 if (sd->drag_y_locked == lock) return;
2584 sd->drag_y_locked = lock;
2585 if (sd->drag_y_locked) _propagate_y_drag_lock(obj, 1);
2586 else _propagate_y_drag_lock(obj, -1);
2587}
2588
2589EAPI Eina_Bool
2590elm_widget_drag_lock_x_get(const Evas_Object *obj)
2591{
2592 API_ENTRY return EINA_FALSE;
2593 return sd->drag_x_locked;
2594}
2595
2596EAPI Eina_Bool
2597elm_widget_drag_lock_y_get(const Evas_Object *obj)
2598{
2599 API_ENTRY return EINA_FALSE;
2600 return sd->drag_y_locked;
2601}
2602
2603EAPI int
2604elm_widget_drag_child_locked_x_get(const Evas_Object *obj)
2605{
2606 API_ENTRY return 0;
2607 return sd->child_drag_x_locked;
2608}
2609
2610EAPI int
2611elm_widget_drag_child_locked_y_get(const Evas_Object *obj)
2612{
2613 API_ENTRY return 0;
2614 return sd->child_drag_y_locked;
2615}
2616
2617EAPI Eina_Bool
2618elm_widget_theme_object_set(Evas_Object *obj,
2619 Evas_Object *edj,
2620 const char *wname,
2621 const char *welement,
2622 const char *wstyle)
2623{
2624 API_ENTRY return EINA_FALSE;
2625 return _elm_theme_object_set(obj, edj, wname, welement, wstyle);
2626}
2627
2628EAPI Eina_Bool
2629elm_widget_is_check(const Evas_Object *obj)
2630{
2631 static int abort_on_warn = -1;
2632 if (elm_widget_is(obj))
2633 return EINA_TRUE;
2634
2635 ERR("Passing Object: %p.", obj);
2636 if (abort_on_warn == -1)
2637 {
2638 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2639 else abort_on_warn = 0;
2640 }
2641 if (abort_on_warn == 1) abort();
2642 return EINA_FALSE;
2643}
2644
2645EAPI Eina_Bool
2646elm_widget_type_check(const Evas_Object *obj,
2647 const char *type,
2648 const char *func)
2649{
2650 const char *provided, *expected = "(unknown)";
2651 static int abort_on_warn = -1;
2652 provided = elm_widget_type_get(obj);
2653 if (EINA_LIKELY(provided == type)) return EINA_TRUE;
2654 if (type) expected = type;
2655 if ((!provided) || (!provided[0]))
2656 {
2657 provided = evas_object_type_get(obj);
2658 if ((!provided) || (!provided[0]))
2659 provided = "(unknown)";
2660 }
2661 ERR("Passing Object: %p in function: %s, of type: '%s' when expecting type: '%s'", obj, func, provided, expected);
2662 if (abort_on_warn == -1)
2663 {
2664 if (getenv("ELM_ERROR_ABORT")) abort_on_warn = 1;
2665 else abort_on_warn = 0;
2666 }
2667 if (abort_on_warn == 1) abort();
2668 return EINA_FALSE;
2669}
2670
2671static Evas_Object *
2672_widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2673{
2674 Eina_List *l;
2675 Evas_Object *child;
2676 const char *s;
2677 INTERNAL_ENTRY NULL;
2678
2679 if (!_elm_widget_is(obj)) return NULL;
2680 if (sd->resize_obj)
2681 {
2682 s = evas_object_name_get(sd->resize_obj);
2683 if ((s) && (!strcmp(s, name))) return sd->resize_obj;
2684 if ((recurse != 0) &&
2685 ((child = _widget_name_find(sd->resize_obj, name, recurse - 1))))
2686 return child;
2687 }
2688 EINA_LIST_FOREACH(sd->subobjs, l, child)
2689 {
2690 s = evas_object_name_get(child);
2691 if ((s) && (!strcmp(s, name))) return child;
2692 if ((recurse != 0) &&
2693 ((child = _widget_name_find(child, name, recurse - 1))))
2694 return child;
2695 }
2696 if (sd->hover_obj)
2697 {
2698 s = evas_object_name_get(sd->hover_obj);
2699 if ((s) && (!strcmp(s, name))) return sd->hover_obj;
2700 if ((recurse != 0) &&
2701 ((child = _widget_name_find(sd->hover_obj, name, recurse - 1))))
2702 return child;
2703 }
2704 return NULL;
2705}
2706
2707EAPI Evas_Object *
2708elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse)
2709{
2710 API_ENTRY return NULL;
2711 if (!name) return NULL;
2712 return _widget_name_find(obj, name, recurse);
2713}
2714
2715/**
2716 * @internal
2717 *
2718 * Split string in words
2719 *
2720 * @param str Source string
2721 * @return List of const words
2722 *
2723 * @see elm_widget_stringlist_free()
2724 * @ingroup Widget
2725 */
2726EAPI Eina_List *
2727elm_widget_stringlist_get(const char *str)
2728{
2729 Eina_List *list = NULL;
2730 const char *s, *b;
2731 if (!str) return NULL;
2732 for (b = s = str; 1; s++)
2733 {
2734 if ((*s == ' ') || (!*s))
2735 {
2736 char *t = malloc(s - b + 1);
2737 if (t)
2738 {
2739 strncpy(t, b, s - b);
2740 t[s - b] = 0;
2741 list = eina_list_append(list, eina_stringshare_add(t));
2742 free(t);
2743 }
2744 b = s + 1;
2745 }
2746 if (!*s) break;
2747 }
2748 return list;
2749}
2750
2751EAPI void
2752elm_widget_stringlist_free(Eina_List *list)
2753{
2754 const char *s;
2755 EINA_LIST_FREE(list, s) eina_stringshare_del(s);
2756}
2757
2758EAPI void
2759elm_widget_focus_hide_handle(Evas_Object *obj)
2760{
2761 if (!_elm_widget_is(obj))
2762 return;
2763 _if_focused_revert(obj, EINA_TRUE);
2764}
2765
2766EAPI void
2767elm_widget_focus_mouse_up_handle(Evas_Object *obj)
2768{
2769 Evas_Object *o = obj;
2770 do
2771 {
2772 if (_elm_widget_is(o)) break;
2773 o = evas_object_smart_parent_get(o);
2774 }
2775 while (o);
2776 if (!o) return;
2777 if (!_is_focusable(o)) return;
2778 elm_widget_focus_steal(o);
2779}
2780
2781EAPI void
2782elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj)
2783{
2784 API_ENTRY return;
2785
2786 //FIXME: Need to check whether the object is unfocusable or not.
2787
2788 if (!elm_widget_parent_get(obj))
2789 elm_widget_focused_object_clear(obj);
2790 else
2791 _if_focused_revert(obj, EINA_TRUE);
2792}
2793
2794EAPI void
2795elm_widget_focus_disabled_handle(Evas_Object *obj)
2796{
2797 API_ENTRY return;
2798
2799 elm_widget_focus_tree_unfocusable_handle(obj);
2800}
2801
2802EAPI unsigned int
2803elm_widget_focus_order_get(const Evas_Object *obj)
2804{
2805 API_ENTRY return 0;
2806 return sd->focus_order;
2807}
2808
2809/**
2810 * @internal
2811 *
2812 * Allocate a new Elm_Widget_Item-derived structure.
2813 *
2814 * The goal of this structure is to provide common ground for actions
2815 * that a widget item have, such as the owner widget, callback to
2816 * notify deletion, data pointer and maybe more.
2817 *
2818 * @param widget the owner widget that holds this item, must be an elm_widget!
2819 * @param alloc_size any number greater than sizeof(Elm_Widget_Item) that will
2820 * be used to allocate memory.
2821 *
2822 * @return allocated memory that is already zeroed out, or NULL on errors.
2823 *
2824 * @see elm_widget_item_new() convenience macro.
2825 * @see elm_widget_item_del() to release memory.
2826 * @ingroup Widget
2827 */
2828EAPI Elm_Widget_Item *
2829_elm_widget_item_new(Evas_Object *widget,
2830 size_t alloc_size)
2831{
2832 if (!_elm_widget_is(widget))
2833 return NULL;
2834
2835 Elm_Widget_Item *item;
2836
2837 EINA_SAFETY_ON_TRUE_RETURN_VAL(alloc_size < sizeof(Elm_Widget_Item), NULL);
2838 EINA_SAFETY_ON_TRUE_RETURN_VAL(!_elm_widget_is(widget), NULL);
2839
2840 item = calloc(1, alloc_size);
2841 EINA_SAFETY_ON_NULL_RETURN_VAL(item, NULL);
2842
2843 EINA_MAGIC_SET(item, ELM_WIDGET_ITEM_MAGIC);
2844 item->widget = widget;
2845 return item;
2846}
2847
2848EAPI void
2849_elm_widget_item_free(Elm_Widget_Item *item)
2850{
2851 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2852
2853 _elm_access_item_unregister(item);
2854
2855 if (item->del_func)
2856 item->del_func((void *)item->data, item->widget, item);
2857
2858 if (item->view)
2859 evas_object_del(item->view);
2860
2861 if (item->access)
2862 {
2863 _elm_access_clear(item->access);
2864 free(item->access);
2865 }
2866
2867 if (item->access_info)
2868 eina_stringshare_del(item->access_info);
2869
2870 EINA_MAGIC_SET(item, EINA_MAGIC_NONE);
2871 free(item);
2872}
2873
2874/**
2875 * @internal
2876 *
2877 * Releases widget item memory, calling back del_cb() if it exists.
2878 *
2879 * If there is a Elm_Widget_Item::del_cb, then it will be called prior
2880 * to memory release. Note that elm_widget_item_pre_notify_del() calls
2881 * this function and then unset it, thus being useful for 2 step
2882 * cleanup whenever the del_cb may use any of the data that must be
2883 * deleted from item.
2884 *
2885 * The Elm_Widget_Item::view will be deleted (evas_object_del()) if it
2886 * is presented!
2887 *
2888 * @param item a valid #Elm_Widget_Item to be deleted.
2889 * @see elm_widget_item_del() convenience macro.
2890 * @ingroup Widget
2891 */
2892EAPI void
2893_elm_widget_item_del(Elm_Widget_Item *item)
2894{
2895 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2896
2897 //Widget item delete callback
2898 if (item->del_pre_func)
2899 {
2900 if (item->del_pre_func((Elm_Object_Item *)item))
2901 _elm_widget_item_free(item);
2902 }
2903 else
2904 _elm_widget_item_free(item);
2905}
2906
2907/**
2908 * @internal
2909 *
2910 * Set the function to notify to widgets when item is being deleted by user.
2911 *
2912 * @param item a valid #Elm_Widget_Item to be notified
2913 * @see elm_widget_item_del_pre_hook_set() convenience macro.
2914 * @ingroup Widget
2915 */
2916EAPI void
2917_elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item, Elm_Widget_Del_Pre_Cb func)
2918{
2919 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2920 item->del_pre_func = func;
2921}
2922
2923/**
2924 * @internal
2925 *
2926 * Notify object will be deleted without actually deleting it.
2927 *
2928 * This function will callback Elm_Widget_Item::del_cb if it is set
2929 * and then unset it so it is not called twice (ie: from
2930 * elm_widget_item_del()).
2931 *
2932 * @param item a valid #Elm_Widget_Item to be notified
2933 * @see elm_widget_item_pre_notify_del() convenience macro.
2934 * @ingroup Widget
2935 */
2936EAPI void
2937_elm_widget_item_pre_notify_del(Elm_Widget_Item *item)
2938{
2939 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2940 if (!item->del_func) return;
2941 item->del_func((void *)item->data, item->widget, item);
2942 item->del_func = NULL;
2943}
2944
2945/**
2946 * @internal
2947 *
2948 * Set the function to notify when item is being deleted.
2949 *
2950 * This function will complain if there was a callback set already,
2951 * however it will set the new one.
2952 *
2953 * The callback will be called from elm_widget_item_pre_notify_del()
2954 * or elm_widget_item_del() will be called with:
2955 * - data: the Elm_Widget_Item::data value.
2956 * - obj: the Elm_Widget_Item::widget evas object.
2957 * - event_info: the item being deleted.
2958 *
2959 * @param item a valid #Elm_Widget_Item to be notified
2960 * @see elm_widget_item_del_cb_set() convenience macro.
2961 * @ingroup Widget
2962 */
2963EAPI void
2964_elm_widget_item_del_cb_set(Elm_Widget_Item *item,
2965 Evas_Smart_Cb func)
2966{
2967 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2968
2969 if ((item->del_func) && (item->del_func != func))
2970 WRN("You're replacing a previously set del_cb %p of item %p with %p",
2971 item->del_func, item, func);
2972
2973 item->del_func = func;
2974}
2975
2976/**
2977 * @internal
2978 *
2979 * Set user-data in this item.
2980 *
2981 * User data may be used to identify this item or just store any
2982 * application data. It is automatically given as the first parameter
2983 * of the deletion notify callback.
2984 *
2985 * @param item a valid #Elm_Widget_Item to store data in.
2986 * @param data user data to store.
2987 * @see elm_widget_item_del_cb_set() convenience macro.
2988 * @ingroup Widget
2989 */
2990EAPI void
2991_elm_widget_item_data_set(Elm_Widget_Item *item,
2992 const void *data)
2993{
2994 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
2995 if ((item->data) && (item->data != data))
2996 DBG("Replacing item %p data %p with %p", item, item->data, data);
2997 item->data = data;
2998}
2999
3000/**
3001 * @internal
3002 *
3003 * Retrieves user-data of this item.
3004 *
3005 * @param item a valid #Elm_Widget_Item to get data from.
3006 * @see elm_widget_item_data_set()
3007 * @ingroup Widget
3008 */
3009EAPI void *
3010_elm_widget_item_data_get(const Elm_Widget_Item *item)
3011{
3012 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3013 return (void *)item->data;
3014}
3015
3016EAPI void
3017_elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled)
3018{
3019 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3020
3021 if (item->disabled == disabled) return;
3022 item->disabled = !!disabled;
3023 if (item->disable_func) item->disable_func(item);
3024}
3025
3026EAPI Eina_Bool
3027_elm_widget_item_disabled_get(const Elm_Widget_Item *item)
3028{
3029 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3030 return item->disabled;
3031}
3032
3033EAPI void
3034_elm_widget_item_disable_hook_set(Elm_Widget_Item *item,
3035 Elm_Widget_Disable_Cb func)
3036{
3037 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3038 item->disable_func = func;
3039}
3040
3041typedef struct _Elm_Widget_Item_Tooltip Elm_Widget_Item_Tooltip;
3042
3043struct _Elm_Widget_Item_Tooltip
3044{
3045 Elm_Widget_Item *item;
3046 Elm_Tooltip_Item_Content_Cb func;
3047 Evas_Smart_Cb del_cb;
3048 const void *data;
3049};
3050
3051static Evas_Object *
3052_elm_widget_item_tooltip_label_create(void *data,
3053 Evas_Object *obj __UNUSED__,
3054 Evas_Object *tooltip,
3055 void *item __UNUSED__)
3056{
3057 Evas_Object *label = elm_label_add(tooltip);
3058 if (!label)
3059 return NULL;
3060 elm_object_style_set(label, "tooltip");
3061 elm_object_text_set(label, data);
3062 return label;
3063}
3064
3065static Evas_Object *
3066_elm_widget_item_tooltip_trans_label_create(void *data,
3067 Evas_Object *obj __UNUSED__,
3068 Evas_Object *tooltip,
3069 void *item __UNUSED__)
3070{
3071 Evas_Object *label = elm_label_add(tooltip);
3072 if (!label)
3073 return NULL;
3074 elm_object_style_set(label, "tooltip");
3075 elm_object_translatable_text_set(label, data);
3076 return label;
3077}
3078
3079static void
3080_elm_widget_item_tooltip_label_del_cb(void *data,
3081 Evas_Object *obj __UNUSED__,
3082 void *event_info __UNUSED__)
3083{
3084 eina_stringshare_del(data);
3085}
3086
3087/**
3088 * @internal
3089 *
3090 * Set the text to be shown in the widget item.
3091 *
3092 * @param item Target item
3093 * @param text The text to set in the content
3094 *
3095 * Setup the text as tooltip to object. The item can have only one tooltip,
3096 * so any previous tooltip data is removed.
3097 *
3098 * @ingroup Widget
3099 */
3100EAPI void
3101_elm_widget_item_tooltip_text_set(Elm_Widget_Item *item,
3102 const char *text)
3103{
3104 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3105 EINA_SAFETY_ON_NULL_RETURN(text);
3106
3107 text = eina_stringshare_add(text);
3108 _elm_widget_item_tooltip_content_cb_set
3109 (item, _elm_widget_item_tooltip_label_create, text,
3110 _elm_widget_item_tooltip_label_del_cb);
3111}
3112
3113EAPI void
3114_elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item,
3115 const char *text)
3116{
3117 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3118 EINA_SAFETY_ON_NULL_RETURN(text);
3119
3120 text = eina_stringshare_add(text);
3121 _elm_widget_item_tooltip_content_cb_set
3122 (item, _elm_widget_item_tooltip_trans_label_create, text,
3123 _elm_widget_item_tooltip_label_del_cb);
3124}
3125
3126static Evas_Object *
3127_elm_widget_item_tooltip_create(void *data,
3128 Evas_Object *obj,
3129 Evas_Object *tooltip)
3130{
3131 Elm_Widget_Item_Tooltip *wit = data;
3132 return wit->func((void *)wit->data, obj, tooltip, wit->item);
3133}
3134
3135static void
3136_elm_widget_item_tooltip_del_cb(void *data,
3137 Evas_Object *obj,
3138 void *event_info __UNUSED__)
3139{
3140 Elm_Widget_Item_Tooltip *wit = data;
3141 if (wit->del_cb) wit->del_cb((void *)wit->data, obj, wit->item);
3142 free(wit);
3143}
3144
3145/**
3146 * @internal
3147 *
3148 * Set the content to be shown in the tooltip item
3149 *
3150 * Setup the tooltip to item. The item can have only one tooltip,
3151 * so any previous tooltip data is removed. @p func(with @p data) will
3152 * be called every time that need show the tooltip and it should
3153 * return a valid Evas_Object. This object is then managed fully by
3154 * tooltip system and is deleted when the tooltip is gone.
3155 *
3156 * @param item the widget item being attached a tooltip.
3157 * @param func the function used to create the tooltip contents.
3158 * @param data what to provide to @a func as callback data/context.
3159 * @param del_cb called when data is not needed anymore, either when
3160 * another callback replaces @func, the tooltip is unset with
3161 * elm_widget_item_tooltip_unset() or the owner @a item
3162 * dies. This callback receives as the first parameter the
3163 * given @a data, and @c event_info is the item.
3164 *
3165 * @ingroup Widget
3166 */
3167EAPI void
3168_elm_widget_item_tooltip_content_cb_set(Elm_Widget_Item *item,
3169 Elm_Tooltip_Item_Content_Cb func,
3170 const void *data,
3171 Evas_Smart_Cb del_cb)
3172{
3173 Elm_Widget_Item_Tooltip *wit;
3174
3175 ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, error_noitem);
3176
3177 if (!func)
3178 {
3179 _elm_widget_item_tooltip_unset(item);
3180 return;
3181 }
3182
3183 wit = ELM_NEW(Elm_Widget_Item_Tooltip);
3184 if (!wit) goto error;
3185 wit->item = item;
3186 wit->func = func;
3187 wit->data = data;
3188 wit->del_cb = del_cb;
3189
3190 elm_object_sub_tooltip_content_cb_set
3191 (item->view, item->widget, _elm_widget_item_tooltip_create, wit,
3192 _elm_widget_item_tooltip_del_cb);
3193
3194 return;
3195
3196error_noitem:
3197 if (del_cb) del_cb((void *)data, NULL, item);
3198 return;
3199error:
3200 if (del_cb) del_cb((void *)data, item->widget, item);
3201}
3202
3203/**
3204 * @internal
3205 *
3206 * Unset tooltip from item
3207 *
3208 * @param item widget item to remove previously set tooltip.
3209 *
3210 * Remove tooltip from item. The callback provided as del_cb to
3211 * elm_widget_item_tooltip_content_cb_set() will be called to notify
3212 * it is not used anymore.
3213 *
3214 * @see elm_widget_item_tooltip_content_cb_set()
3215 *
3216 * @ingroup Widget
3217 */
3218EAPI void
3219_elm_widget_item_tooltip_unset(Elm_Widget_Item *item)
3220{
3221 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3222 elm_object_tooltip_unset(item->view);
3223}
3224
3225/**
3226 * @internal
3227 *
3228 * Sets a different style for this item tooltip.
3229 *
3230 * @note before you set a style you should define a tooltip with
3231 * elm_widget_item_tooltip_content_cb_set() or
3232 * elm_widget_item_tooltip_text_set()
3233 *
3234 * @param item widget item with tooltip already set.
3235 * @param style the theme style to use (default, transparent, ...)
3236 *
3237 * @ingroup Widget
3238 */
3239EAPI void
3240_elm_widget_item_tooltip_style_set(Elm_Widget_Item *item,
3241 const char *style)
3242{
3243 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3244 elm_object_tooltip_style_set(item->view, style);
3245}
3246
3247EAPI Eina_Bool
3248_elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item, Eina_Bool disable)
3249{
3250 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3251 return elm_object_tooltip_window_mode_set(item->view, disable);
3252}
3253
3254EAPI Eina_Bool
3255_elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item)
3256{
3257 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3258 return elm_object_tooltip_window_mode_get(item->view);
3259}
3260
3261/**
3262 * @internal
3263 *
3264 * Get the style for this item tooltip.
3265 *
3266 * @param item widget item with tooltip already set.
3267 * @return style the theme style in use, defaults to "default". If the
3268 * object does not have a tooltip set, then NULL is returned.
3269 *
3270 * @ingroup Widget
3271 */
3272EAPI const char *
3273_elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item)
3274{
3275 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3276 return elm_object_tooltip_style_get(item->view);
3277}
3278
3279EAPI void
3280_elm_widget_item_cursor_set(Elm_Widget_Item *item,
3281 const char *cursor)
3282{
3283 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3284 elm_object_sub_cursor_set(item->view, item->widget, cursor);
3285}
3286
3287EAPI const char *
3288_elm_widget_item_cursor_get(const Elm_Widget_Item *item)
3289{
3290 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3291 return elm_object_cursor_get(item->view);
3292}
3293
3294EAPI void
3295_elm_widget_item_cursor_unset(Elm_Widget_Item *item)
3296{
3297 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3298 elm_object_cursor_unset(item->view);
3299}
3300
3301/**
3302 * @internal
3303 *
3304 * Sets a different style for this item cursor.
3305 *
3306 * @note before you set a style you should define a cursor with
3307 * elm_widget_item_cursor_set()
3308 *
3309 * @param item widget item with cursor already set.
3310 * @param style the theme style to use (default, transparent, ...)
3311 *
3312 * @ingroup Widget
3313 */
3314EAPI void
3315_elm_widget_item_cursor_style_set(Elm_Widget_Item *item,
3316 const char *style)
3317{
3318 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3319 elm_object_cursor_style_set(item->view, style);
3320}
3321
3322/**
3323 * @internal
3324 *
3325 * Get the style for this item cursor.
3326 *
3327 * @param item widget item with cursor already set.
3328 * @return style the theme style in use, defaults to "default". If the
3329 * object does not have a cursor set, then NULL is returned.
3330 *
3331 * @ingroup Widget
3332 */
3333EAPI const char *
3334_elm_widget_item_cursor_style_get(const Elm_Widget_Item *item)
3335{
3336 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3337 return elm_object_cursor_style_get(item->view);
3338}
3339
3340/**
3341 * @internal
3342 *
3343 * Set if the cursor set should be searched on the theme or should use
3344 * the provided by the engine, only.
3345 *
3346 * @note before you set if should look on theme you should define a cursor
3347 * with elm_object_cursor_set(). By default it will only look for cursors
3348 * provided by the engine.
3349 *
3350 * @param item widget item with cursor already set.
3351 * @param engine_only boolean to define it cursors should be looked only
3352 * between the provided by the engine or searched on widget's theme as well.
3353 *
3354 * @ingroup Widget
3355 */
3356EAPI void
3357_elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item,
3358 Eina_Bool engine_only)
3359{
3360 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3361 elm_object_cursor_theme_search_enabled_set(item->view, engine_only);
3362}
3363
3364/**
3365 * @internal
3366 *
3367 * Get the cursor engine only usage for this item cursor.
3368 *
3369 * @param item widget item with cursor already set.
3370 * @return engine_only boolean to define it cursors should be looked only
3371 * between the provided by the engine or searched on widget's theme as well. If
3372 * the object does not have a cursor set, then EINA_FALSE is returned.
3373 *
3374 * @ingroup Widget
3375 */
3376EAPI Eina_Bool
3377_elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item)
3378{
3379 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, EINA_FALSE);
3380 return elm_object_cursor_theme_search_enabled_get(item->view);
3381}
3382
3383// smart object funcs
3384static void
3385_smart_reconfigure(Smart_Data *sd)
3386{
3387 if (sd->resize_obj)
3388 {
3389 evas_object_move(sd->resize_obj, sd->x, sd->y);
3390 evas_object_resize(sd->resize_obj, sd->w, sd->h);
3391 }
3392 if (sd->hover_obj)
3393 {
3394 evas_object_move(sd->hover_obj, sd->x, sd->y);
3395 evas_object_resize(sd->hover_obj, sd->w, sd->h);
3396 }
3397}
3398
3399EAPI void
3400_elm_widget_item_part_content_set(Elm_Widget_Item *item,
3401 const char *part,
3402 Evas_Object *content)
3403{
3404 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3405 if (!item->content_set_func)
3406 {
3407 ERR("%s does not support elm_object_item_part_content_set() API.",
3408 elm_widget_type_get(item->widget));
3409 return;
3410 }
3411 item->content_set_func((Elm_Object_Item *)item, part, content);
3412}
3413
3414EAPI Evas_Object *
3415_elm_widget_item_part_content_get(const Elm_Widget_Item *item,
3416 const char *part)
3417{
3418 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3419 if (!item->content_get_func)
3420 {
3421 ERR("%s does not support elm_object_item_part_content_get() API.",
3422 elm_widget_type_get(item->widget));
3423 return NULL;
3424 }
3425 return item->content_get_func((Elm_Object_Item *)item, part);
3426}
3427
3428EAPI Evas_Object *
3429_elm_widget_item_part_content_unset(Elm_Widget_Item *item,
3430 const char *part)
3431{
3432 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3433 if (!item->content_unset_func)
3434 {
3435 ERR("%s does not support elm_object_item_part_content_unset() API.",
3436 elm_widget_type_get(item->widget));
3437 return NULL;
3438 }
3439 return item->content_unset_func((Elm_Object_Item *)item, part);
3440}
3441
3442EAPI void
3443_elm_widget_item_part_text_set(Elm_Widget_Item *item,
3444 const char *part,
3445 const char *label)
3446{
3447 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3448 if (!item->text_set_func)
3449 {
3450 ERR("%s does not support elm_object_item_part_text_set() API.",
3451 elm_widget_type_get(item->widget));
3452 return;
3453 }
3454 item->text_set_func((Elm_Object_Item *)item, part, label);
3455}
3456
3457EAPI const char *
3458_elm_widget_item_part_text_get(const Elm_Widget_Item *item,
3459 const char *part)
3460{
3461 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, NULL);
3462 if (!item->text_get_func)
3463 {
3464 ERR("%s does not support elm_object_item_part_text_get() API.",
3465 elm_widget_type_get(item->widget));
3466 return NULL;
3467 }
3468 return item->text_get_func((Elm_Object_Item *)item, part);
3469}
3470
3471EAPI void
3472_elm_widget_item_content_set_hook_set(Elm_Widget_Item *item,
3473 Elm_Widget_Content_Set_Cb func)
3474{
3475 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3476 item->content_set_func = func;
3477}
3478
3479EAPI void
3480_elm_widget_item_content_get_hook_set(Elm_Widget_Item *item,
3481 Elm_Widget_Content_Get_Cb func)
3482{
3483 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3484 item->content_get_func = func;
3485}
3486
3487EAPI void
3488_elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item,
3489 Elm_Widget_Content_Unset_Cb func)
3490{
3491 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3492 item->content_unset_func = func;
3493}
3494
3495EAPI void
3496_elm_widget_item_text_set_hook_set(Elm_Widget_Item *item,
3497 Elm_Widget_Text_Set_Cb func)
3498{
3499 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3500 item->text_set_func = func;
3501}
3502
3503EAPI void
3504_elm_widget_item_text_get_hook_set(Elm_Widget_Item *item,
3505 Elm_Widget_Text_Get_Cb func)
3506{
3507 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3508 item->text_get_func = func;
3509}
3510
3511EAPI void
3512_elm_widget_item_signal_emit(Elm_Widget_Item *item,
3513 const char *emission,
3514 const char *source)
3515{
3516 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3517 if (item->signal_emit_func)
3518 item->signal_emit_func((Elm_Object_Item *)item, emission, source);
3519}
3520
3521EAPI void
3522_elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *item,
3523 Elm_Widget_Signal_Emit_Cb func)
3524{
3525 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3526 item->signal_emit_func = func;
3527}
3528
3529EAPI void
3530_elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt)
3531{
3532 ELM_WIDGET_ITEM_CHECK_OR_RETURN(item);
3533 if (item->access_info) eina_stringshare_del(item->access_info);
3534 if (!txt) item->access_info = NULL;
3535 else item->access_info = eina_stringshare_add(txt);
3536}
3537
3538static void
3539_smart_add(Evas_Object *obj)
3540{
3541 Smart_Data *sd;
3542
3543 sd = calloc(1, sizeof(Smart_Data));
3544 if (!sd) return;
3545 sd->obj = obj;
3546 sd->x = sd->y = sd->w = sd->h = 0;
3547 sd->mirrored_auto_mode = EINA_TRUE; /* will follow system locale settings */
3548 evas_object_smart_data_set(obj, sd);
3549 elm_widget_can_focus_set(obj, EINA_TRUE);
3550}
3551
3552static Evas_Object *
3553_newest_focus_order_get(Evas_Object *obj,
3554 unsigned int *newest_focus_order,
3555 Eina_Bool can_focus_only)
3556{
3557 const Eina_List *l;
3558 Evas_Object *child, *ret, *best;
3559
3560 API_ENTRY return NULL;
3561
3562 if (!evas_object_visible_get(obj)
3563 || (elm_widget_disabled_get(obj))
3564 || (elm_widget_tree_unfocusable_get(obj)))
3565 return NULL;
3566
3567 best = NULL;
3568 if (*newest_focus_order < sd->focus_order)
3569 {
3570 *newest_focus_order = sd->focus_order;
3571 best = obj;
3572 }
3573 EINA_LIST_FOREACH(sd->subobjs, l, child)
3574 {
3575 ret = _newest_focus_order_get(child, newest_focus_order, can_focus_only);
3576 if (!ret) continue;
3577 best = ret;
3578 }
3579 if (can_focus_only)
3580 {
3581 if ((!best) || (!elm_widget_can_focus_get(best)))
3582 return NULL;
3583 }
3584 return best;
3585}
3586
3587static void
3588_if_focused_revert(Evas_Object *obj,
3589 Eina_Bool can_focus_only)
3590{
3591 Evas_Object *top;
3592 Evas_Object *newest = NULL;
3593 unsigned int newest_focus_order = 0;
3594
3595 INTERNAL_ENTRY;
3596
3597 if (!sd->focused) return;
3598 if (!sd->parent_obj) return;
3599
3600 top = elm_widget_top_get(sd->parent_obj);
3601 if (top)
3602 {
3603 newest = _newest_focus_order_get(top, &newest_focus_order, can_focus_only);
3604 if (newest)
3605 {
3606 elm_object_focus_set(newest, EINA_FALSE);
3607 elm_object_focus_set(newest, EINA_TRUE);
3608 }
3609 }
3610}
3611
3612static void
3613_smart_del(Evas_Object *obj)
3614{
3615 Evas_Object *sobj;
3616 Edje_Signal_Data *esd;
3617 Elm_Translate_String_Data *ts;
3618
3619 INTERNAL_ENTRY;
3620
3621 if (sd->del_pre_func) sd->del_pre_func(obj);
3622 if (sd->resize_obj)
3623 {
3624 sobj = sd->resize_obj;
3625 sd->resize_obj = NULL;
3626 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3627 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3628 evas_object_del(sobj);
3629 sd->resize_obj = NULL;
3630 }
3631 if (sd->hover_obj)
3632 {
3633 sobj = sd->hover_obj;
3634 sd->hover_obj = NULL;
3635 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3636 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3637 evas_object_del(sobj);
3638 sd->hover_obj = NULL;
3639 }
3640 EINA_LIST_FREE(sd->subobjs, sobj)
3641 {
3642 evas_object_event_callback_del_full(sobj, EVAS_CALLBACK_DEL, _sub_obj_del, sd);
3643 evas_object_smart_callback_call(sd->obj, "sub-object-del", sobj);
3644 evas_object_del(sobj);
3645 }
3646 sd->tooltips = eina_list_free(sd->tooltips); /* should be empty anyway */
3647 sd->cursors = eina_list_free(sd->cursors); /* should be empty anyway */
3648 EINA_LIST_FREE(sd->edje_signals, esd)
3649 {
3650 eina_stringshare_del(esd->emission);
3651 eina_stringshare_del(esd->source);
3652 free(esd);
3653 }
3654 EINA_LIST_FREE(sd->translate_strings, ts)
3655 {
3656 eina_stringshare_del(ts->id);
3657 eina_stringshare_del(ts->domain);
3658 eina_stringshare_del(ts->string);
3659 free(ts);
3660 }
3661 sd->event_cb = eina_list_free(sd->event_cb); /* should be empty anyway */
3662 if (sd->del_func) sd->del_func(obj);
3663 if (sd->style) eina_stringshare_del(sd->style);
3664 if (sd->type) eina_stringshare_del(sd->type);
3665 if (sd->theme) elm_theme_free(sd->theme);
3666 sd->data = NULL;
3667 _if_focused_revert(obj, EINA_TRUE);
3668 if (sd->access_info) eina_stringshare_del(sd->access_info);
3669 free(sd);
3670 evas_object_smart_data_set(obj, NULL);
3671}
3672
3673static void
3674_smart_move(Evas_Object *obj,
3675 Evas_Coord x,
3676 Evas_Coord y)
3677{
3678 INTERNAL_ENTRY;
3679 sd->x = x;
3680 sd->y = y;
3681 _smart_reconfigure(sd);
3682}
3683
3684static void
3685_smart_resize(Evas_Object *obj,
3686 Evas_Coord w,
3687 Evas_Coord h)
3688{
3689 INTERNAL_ENTRY;
3690 sd->w = w;
3691 sd->h = h;
3692 _smart_reconfigure(sd);
3693}
3694
3695static void
3696_smart_show(Evas_Object *obj)
3697{
3698 Eina_List *list;
3699 Evas_Object *o;
3700 INTERNAL_ENTRY;
3701 if ((list = evas_object_smart_members_get(obj)))
3702 {
3703 EINA_LIST_FREE(list, o)
3704 {
3705 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3706 evas_object_show(o);
3707 }
3708 }
3709}
3710
3711static void
3712_smart_hide(Evas_Object *obj)
3713{
3714 Eina_List *list;
3715 Evas_Object *o;
3716 INTERNAL_ENTRY;
3717
3718 list = evas_object_smart_members_get(obj);
3719 EINA_LIST_FREE(list, o)
3720 {
3721 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3722 evas_object_hide(o);
3723 }
3724}
3725
3726static void
3727_smart_color_set(Evas_Object *obj,
3728 int r,
3729 int g,
3730 int b,
3731 int a)
3732{
3733 Eina_List *list;
3734 Evas_Object *o;
3735 INTERNAL_ENTRY;
3736 if ((list = evas_object_smart_members_get(obj)))
3737 {
3738 EINA_LIST_FREE(list, o)
3739 {
3740 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3741 evas_object_color_set(o, r, g, b, a);
3742 }
3743 }
3744}
3745
3746static void
3747_smart_clip_set(Evas_Object *obj,
3748 Evas_Object *clip)
3749{
3750 Eina_List *list;
3751 Evas_Object *o;
3752 INTERNAL_ENTRY;
3753 if ((list = evas_object_smart_members_get(obj)))
3754 {
3755 EINA_LIST_FREE(list, o)
3756 {
3757 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3758 evas_object_clip_set(o, clip);
3759 }
3760 }
3761}
3762
3763static void
3764_smart_clip_unset(Evas_Object *obj)
3765{
3766 Eina_List *list;
3767 Evas_Object *o;
3768 INTERNAL_ENTRY;
3769 if ((list = evas_object_smart_members_get(obj)))
3770 {
3771 EINA_LIST_FREE(list, o)
3772 {
3773 if (evas_object_data_get(o, "_elm_leaveme")) continue;
3774 evas_object_clip_unset(o);
3775 }
3776 }
3777}
3778
3779static void
3780_smart_calculate(Evas_Object *obj)
3781{
3782 INTERNAL_ENTRY;
3783 if (sd->changed_func) sd->changed_func(obj);
3784}
3785
3786static void
3787_smart_member_add(Evas_Object *obj, Evas_Object *child)
3788{
3789 int r, g, b, a;
3790
3791 if (evas_object_data_get(child, "_elm_leaveme")) return;
3792
3793 evas_object_color_get(obj, &r, &g, &b, &a);
3794 evas_object_color_set(child, r, g, b, a);
3795
3796 evas_object_clip_set(child, evas_object_clip_get(obj));
3797
3798 if (evas_object_visible_get(obj))
3799 evas_object_show(child);
3800 else
3801 evas_object_hide(child);
3802}
3803
3804static void
3805_smart_member_del(Evas_Object *obj __UNUSED__, Evas_Object *child)
3806{
3807 if (evas_object_data_get(child, "_elm_leaveme")) return;
3808 evas_object_clip_unset(child);
3809}
3810
3811/* never need to touch this */
3812static void
3813_smart_init(void)
3814{
3815 if (_e_smart) return;
3816 {
3817 static const Evas_Smart_Class sc =
3818 {
3819 SMART_NAME,
3820 EVAS_SMART_CLASS_VERSION,
3821 _smart_add,
3822 _smart_del,
3823 _smart_move,
3824 _smart_resize,
3825 _smart_show,
3826 _smart_hide,
3827 _smart_color_set,
3828 _smart_clip_set,
3829 _smart_clip_unset,
3830 _smart_calculate,
3831 _smart_member_add,
3832 _smart_member_del,
3833 NULL,
3834 NULL,
3835 NULL,
3836 NULL
3837 };
3838 _e_smart = evas_smart_class_new(&sc);
3839 }
3840}
3841
3842/* happy debug functions */
3843#ifdef ELM_DEBUG
3844static void
3845_sub_obj_tree_dump(const Evas_Object *obj,
3846 int lvl)
3847{
3848 int i;
3849
3850 for (i = 0; i < lvl * 3; i++)
3851 putchar(' ');
3852
3853 if (_elm_widget_is(obj))
3854 {
3855 Eina_List *l;
3856 INTERNAL_ENTRY;
3857 printf("+ %s(%p)\n",
3858 sd->type,
3859 obj);
3860 if (sd->resize_obj)
3861 _sub_obj_tree_dump(sd->resize_obj, lvl + 1);
3862 EINA_LIST_FOREACH(sd->subobjs, l, obj)
3863 {
3864 if (obj != sd->resize_obj)
3865 _sub_obj_tree_dump(obj, lvl + 1);
3866 }
3867 }
3868 else
3869 printf("+ %s(%p)\n", evas_object_type_get(obj), obj);
3870}
3871
3872static void
3873_sub_obj_tree_dot_dump(const Evas_Object *obj,
3874 FILE *output)
3875{
3876 if (!_elm_widget_is(obj))
3877 return;
3878 INTERNAL_ENTRY;
3879
3880 Eina_Bool visible = evas_object_visible_get(obj);
3881 Eina_Bool disabled = elm_widget_disabled_get(obj);
3882 Eina_Bool focused = elm_widget_focus_get(obj);
3883 Eina_Bool can_focus = elm_widget_can_focus_get(obj);
3884
3885 if (sd->parent_obj)
3886 {
3887 fprintf(output, "\"%p\" -- \"%p\" [ color=black", sd->parent_obj, obj);
3888
3889 if (focused)
3890 fprintf(output, ", style=bold");
3891
3892 if (!visible)
3893 fprintf(output, ", color=gray28");
3894
3895 fprintf(output, " ];\n");
3896 }
3897
3898 fprintf(output, "\"%p\" [ label = \"{%p|%s|%s|visible: %d|"
3899 "disabled: %d|focused: %d/%d|focus order:%d}\"", obj, obj, sd->type,
3900 evas_object_name_get(obj), visible, disabled, focused, can_focus,
3901 sd->focus_order);
3902
3903 if (focused)
3904 fprintf(output, ", style=bold");
3905
3906 if (!visible)
3907 fprintf(output, ", fontcolor=gray28");
3908
3909 if ((disabled) || (!visible))
3910 fprintf(output, ", color=gray");
3911
3912 fprintf(output, " ];\n");
3913
3914 Eina_List *l;
3915 Evas_Object *o;
3916 EINA_LIST_FOREACH(sd->subobjs, l, o)
3917 _sub_obj_tree_dot_dump(o, output);
3918}
3919#endif
3920
3921EAPI void
3922elm_widget_tree_dump(const Evas_Object *top)
3923{
3924#ifdef ELM_DEBUG
3925 if (!_elm_widget_is(top))
3926 return;
3927 _sub_obj_tree_dump(top, 0);
3928#else
3929 return;
3930 (void)top;
3931#endif
3932}
3933
3934EAPI void
3935elm_widget_tree_dot_dump(const Evas_Object *top,
3936 FILE *output)
3937{
3938#ifdef ELM_DEBUG
3939 if (!_elm_widget_is(top))
3940 return;
3941 fprintf(output, "graph " " { node [shape=record];\n");
3942 _sub_obj_tree_dot_dump(top, output);
3943 fprintf(output, "}\n");
3944#else
3945 return;
3946 (void)top;
3947 (void)output;
3948#endif
3949}
diff --git a/libraries/elementary/src/lib/elm_widget.h b/libraries/elementary/src/lib/elm_widget.h
new file mode 100644
index 0000000..2f00121
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_widget.h
@@ -0,0 +1,751 @@
1#ifndef ELM_WIDGET_H
2#define ELM_WIDGET_H
3
4/* DO NOT USE THIS HEADER UNLESS YOU ARE PREPARED FOR BREAKING OF YOUR
5 * CODE. THIS IS ELEMENTARY'S INTERNAL WIDGET API (for now) AND IS NOT
6 * FINAL. CALL elm_widget_api_check(ELM_INTERNAL_API_VERSION) TO CHECK IT
7 * AT RUNTIME
8 *
9 * How to make your own widget? like this:
10 *
11 * #include <Elementary.h>
12 * #include "elm_priv.h"
13 *
14 * typedef struct _Widget_Data Widget_Data;
15 *
16 * struct _Widget_Data
17 * {
18 * Evas_Object *sub;
19 * // add any other widget data here too
20 * };
21 *
22 * static const char *widtype = NULL;
23 * static void _del_hook(Evas_Object *obj);
24 * static void _theme_hook(Evas_Object *obj);
25 * static void _disable_hook(Evas_Object *obj);
26 * static void _sizing_eval(Evas_Object *obj);
27 * static void _on_focus_hook(void *data, Evas_Object *obj);
28 *
29 * static const char SIG_CLICKED[] = "clicked";
30 * static const Evas_Smart_Cb_Description _signals[] = {
31 * {SIG_CLICKED, ""},
32 * {NULL, NULL}
33 * };
34 *
35 * static void
36 * _del_hook(Evas_Object *obj)
37 * {
38 * Widget_Data *wd = elm_widget_data_get(obj);
39 * if (!wd) return;
40 * // delete hook - on delete of object delete object struct etc.
41 * free(wd);
42 * }
43 *
44 * static void
45 * _on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
46 * {
47 * Widget_Data *wd = elm_widget_data_get(obj);
48 * if (!wd) return;
49 * // handle focus going in and out - optional, but if you want to, set
50 * // this hook and handle it (eg emit a signal to an edje obj)
51 * if (elm_widget_focus_get(obj))
52 * {
53 * edje_object_signal_emit(wd->sub, "elm,action,focus", "elm");
54 * evas_object_focus_set(wd->sub, EINA_TRUE);
55 * }
56 * else
57 * {
58 * edje_object_signal_emit(wd->sub, "elm,action,unfocus", "elm");
59 * evas_object_focus_set(wd->sub, EINA_FALSE);
60 * }
61 * }
62 *
63 * static void
64 * _theme_hook(Evas_Object *obj)
65 * {
66 * Widget_Data *wd = elm_widget_data_get(obj);
67 * if (!wd) return;
68 * // handle change in theme/scale etc.
69 * elm_widget_theme_object_set(obj, wd->sub, "mywidget", "base",
70 * elm_widget_style_get(obj));
71 * }
72 *
73 * static void
74 * _disable_hook(Evas_Object *obj)
75 * {
76 * Widget_Data *wd = elm_widget_data_get(obj);
77 * if (!wd) return;
78 * // optional, but handle if the widget gets disabled or not
79 * if (elm_widget_disabled_get(obj))
80 * edje_object_signal_emit(wd->sub, "elm,state,disabled", "elm");
81 * else
82 * edje_object_signal_emit(wd->sub, "elm,state,enabled", "elm");
83 * }
84 *
85 * static void
86 * _sizing_eval(Evas_Object *obj)
87 * {
88 * Widget_Data *wd = elm_widget_data_get(obj);
89 * Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
90 * if (!wd) return;
91 * elm_coords_finger_size_adjust(1, &minw, 1, &minh);
92 * edje_object_size_min_restricted_calc(wd->sub, &minw, &minh, minw, minh);
93 * elm_coords_finger_size_adjust(1, &minw, 1, &minh);
94 * evas_object_size_hint_min_set(obj, minw, minh);
95 * evas_object_size_hint_max_set(obj, maxw, maxh);
96 * }
97 *
98 * // actual api to create your widget. add more to manipulate it as needed
99 * // mark your calls with EAPI to make them "external api" calls.
100 * EAPI Evas_Object *
101 * elm_mywidget_add(Evas_Object *parent)
102 * {
103 * Evas_Object *obj;
104 * Evas *e;
105 * Widget_Data *wd;
106 *
107 * // ALWAYS call this - this checks that your widget matches that of
108 * // elementary and that the api hasn't broken. if it has this returns
109 * // false and you need to handle this error gracefully
110 * if (!elm_widget_api_check(ELM_INTERNAL_API_VERSION)) return NULL;
111 *
112 * // standard widget setup and allocate wd, create obj given parent etc.
113 * ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
114 *
115 * // give it a type name and set up a mywidget type string if needed
116 * ELM_SET_WIDTYPE(widtype, "mywidget");
117 * elm_widget_type_set(obj, "mywidget");
118 * // tell the parent widget that we are a sub object
119 * elm_widget_sub_object_add(parent, obj);
120 * // setup hooks we need (some are optional)
121 * elm_widget_on_focus_hook_set(obj, _on_focus_hook, NULL);
122 * elm_widget_data_set(obj, wd);
123 * elm_widget_del_hook_set(obj, _del_hook);
124 * elm_widget_theme_hook_set(obj, _theme_hook);
125 * elm_widget_disable_hook_set(obj, _disable_hook);
126 * // this widget can focus (true means yes it can, false means it can't)
127 * elm_widget_can_focus_set(obj, EINA_TRUE);
128 *
129 * // for this widget we will add 1 sub object that is an edje object
130 * wd->sub = edje_object_add(e);
131 * // set the theme. this follows a scheme for group name like this:
132 * // "elm/WIDGETNAME/ELEMENT/STYLE"
133 * // so here it will be:
134 * // "elm/mywidget/base/default"
135 * // changing style changes style name from default (all widgets start
136 * // with the default style) and element is for your widget internal
137 * // structure as you see fit
138 * elm_widget_theme_object_set(obj, wd->sub, "mywidget", "base", "default");
139 * // listen to a signal from the edje object to produce widget smart
140 * // callback (like click)
141 * edje_object_signal_callback_add(wd->sub, "elm,action,click", "",
142 * _signal_clicked, obj);
143 * // set this sub object as the "resize object". widgets get 1 resize
144 * // object that is resized along with the object wrapper.
145 * elm_widget_resize_object_set(obj, wd->sub);
146 *
147 * // evaluate sizing of the widget (minimum size calc etc.). optional but
148 * // not a bad idea to do here. it will get queued for later anyway
149 * _sizing_eval(obj);
150 *
151 * // register the smart callback descriptions so we can have some runtime
152 * // info as to what the smart callback strings mean
153 * evas_object_smart_callbacks_descriptions_set(obj, _signals);
154 * return obj;
155 * }
156 *
157 * // example - do "whatever" to the widget (here just emit a signal)
158 * EAPI void
159 * elm_mywidget_whatever(Evas_Object *obj)
160 * {
161 * // check if type is correct - check will return if it fails
162 * ELM_CHECK_WIDTYPE(obj, widtype);
163 * // get widget data - type is correct and sane by this point, so this
164 * // should never fail
165 * Widget_Data *wd = elm_widget_data_get(obj);
166 * // do whatever you like
167 * edje_object_signal_emit(wd->sub, "elm,state,action,whatever", "elm");
168 * }
169 *
170 * // you can add more - you need to see elementary's code to know how to
171 * // handle all cases. remember this api is not stable and may change. it's
172 * // internal
173 *
174 */
175
176#ifndef ELM_INTERNAL_API_ARGESFSDFEFC
177#warning "You are using an internal elementary API. This API is not stable"
178#warning "and is subject to change. You use this at your own risk."
179#warning "Remember to call elm_widget_api_check(ELM_INTERNAL_API_VERSION);"
180#warning "in your widgets before you call any other elm_widget calls to do"
181#warning "a correct runtime version check. Also remember - you don't NEED"
182#warning "to make an Elementary widget is almost ALL cases. You can easily"
183#warning "make a smart object with Evas's API and do everything you need"
184#warning "there. You only need a widget if you want to seamlessly be part"
185#warning "of the focus tree and want to transparently become a container"
186#warning "for any number of child Elementary widgets"
187#error "ERROR. Compile aborted."
188#endif
189#define ELM_INTERNAL_API_VERSION 7000
190
191typedef struct _Elm_Tooltip Elm_Tooltip;
192typedef struct _Elm_Cursor Elm_Cursor;
193
194/**< base structure for all widget items that are not Elm_Widget themselves */
195typedef struct _Elm_Widget_Item Elm_Widget_Item;
196
197/**< accessibility information to be able to set and get from the access API */
198typedef struct _Elm_Access_Info Elm_Access_Info;
199
200/**< accessibility info item */
201typedef struct _Elm_Access_Item Elm_Access_Item;
202
203typedef void (*Elm_Widget_Text_Set_Cb)(void *data, const char *part, const char *text);
204typedef void (*Elm_Widget_Content_Set_Cb)(void *data, const char *part, Evas_Object *content);
205typedef const char *(*Elm_Widget_Text_Get_Cb)(const void *data, const char *part);
206typedef Evas_Object *(*Elm_Widget_Content_Get_Cb)(const void *data, const char *part);
207typedef Evas_Object *(*Elm_Widget_Content_Unset_Cb)(const void *data, const char *part);
208typedef void (*Elm_Widget_Signal_Emit_Cb)(void *data, const char *emission, const char *source);
209typedef void (*Elm_Widget_Disable_Cb)(void *data);
210typedef Eina_Bool (*Elm_Widget_Del_Pre_Cb)(void *data);
211
212#define ELM_ACCESS_TYPE 0 // when reading out widget or item this is read first
213#define ELM_ACCESS_INFO 1 // next read is info - this is normally label
214#define ELM_ACCESS_STATE 2 // if there is a state (eg checkbox) then read state out
215#define ELM_ACCESS_CONTENT 3 // read ful content - eg all of the label, not a shortened version
216
217#define ELM_ACCESS_DONE -1 // sentence done - send done event here
218#define ELM_ACCESS_CANCEL -2 // stop reading immediately
219
220typedef char *(*Elm_Access_Content_Cb)(void *data, Evas_Object *obj, Elm_Widget_Item *item);
221
222struct _Elm_Access_Item
223{
224 int type;
225 const void *data;
226 Elm_Access_Content_Cb func;
227};
228
229struct _Elm_Access_Info
230{
231 Evas_Object *hoverobj;
232 Eina_List *items;
233 Ecore_Timer *delay_timer;
234};
235
236EAPI void _elm_access_clear(Elm_Access_Info *ac);
237EAPI void _elm_access_text_set(Elm_Access_Info *ac, int type, const char *text);
238EAPI void _elm_access_callback_set(Elm_Access_Info *ac, int type, Elm_Access_Content_Cb func, const void *data);
239EAPI char *_elm_access_text_get(const Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item); /* this is ok it actually returns a strduped string - it's meant to! */
240EAPI void _elm_access_read(Elm_Access_Info *ac, int type, Evas_Object *obj, Elm_Widget_Item *item);
241EAPI void _elm_access_say(const char *txt);
242EAPI Elm_Access_Info *_elm_access_object_get(const Evas_Object *obj);
243EAPI Elm_Access_Info *_elm_access_item_get(const Elm_Widget_Item *it);
244EAPI void _elm_access_object_hilight(Evas_Object *obj);
245EAPI void _elm_access_object_unhilight(Evas_Object *obj);
246EAPI void _elm_access_object_hilight_disable(Evas *e);
247EAPI void _elm_access_object_register(Evas_Object *obj, Evas_Object *hoverobj);
248EAPI void _elm_access_item_unregister(Elm_Widget_Item *item);
249EAPI void _elm_access_item_register(Elm_Widget_Item *item, Evas_Object *hoverobj);
250EAPI Eina_Bool _elm_access_2nd_click_timeout(Evas_Object *obj);
251
252/**< put this as the first member in your widget item struct */
253#define ELM_WIDGET_ITEM Elm_Widget_Item base
254
255struct _Elm_Widget_Item
256{
257/* ef1 ~~ efl, el3 ~~ elm */
258#define ELM_WIDGET_ITEM_MAGIC 0xef1e1301
259 EINA_MAGIC;
260/* simple accessor macros */
261#define VIEW(X) X->base.view
262#define WIDGET(X) X->base.widget
263 /**< the owner widget that owns this item */
264 Evas_Object *widget;
265 /**< the base view object */
266 Evas_Object *view;
267 /**< item specific data. used for del callback */
268 const void *data;
269 /**< user delete callback function */
270 Evas_Smart_Cb del_func;
271 /**< widget delete callback function. don't expose this callback call */
272 Elm_Widget_Del_Pre_Cb del_pre_func;
273
274 Elm_Widget_Content_Set_Cb content_set_func;
275 Elm_Widget_Content_Get_Cb content_get_func;
276 Elm_Widget_Content_Unset_Cb content_unset_func;
277 Elm_Widget_Text_Set_Cb text_set_func;
278 Elm_Widget_Text_Get_Cb text_get_func;
279 Elm_Widget_Signal_Emit_Cb signal_emit_func;
280 Elm_Widget_Disable_Cb disable_func;
281 Elm_Access_Info *access;
282 const char *access_info;
283
284 Eina_Bool disabled : 1;
285};
286
287struct _Elm_Object_Item
288{
289 ELM_WIDGET_ITEM;
290};
291
292#define ELM_NEW(t) calloc(1, sizeof(t))
293
294EAPI Eina_Bool elm_widget_api_check(int ver);
295EAPI Evas_Object *elm_widget_add(Evas *evas);
296EAPI void elm_widget_del_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
297EAPI void elm_widget_del_pre_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
298EAPI void elm_widget_focus_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
299EAPI void elm_widget_activate_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
300EAPI void elm_widget_disable_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
301EAPI void elm_widget_theme_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
302EAPI void elm_widget_translate_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
303EAPI 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));
304EAPI void elm_widget_changed_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj));
305EAPI void elm_widget_signal_emit_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj, const char *emission, const char *source));
306EAPI void elm_widget_signal_callback_add_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data));
307EAPI void elm_widget_signal_callback_del_hook_set(Evas_Object *obj, void (*func)(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func_cb, void *data));
308EAPI Eina_Bool elm_widget_theme(Evas_Object *obj);
309EAPI void elm_widget_theme_specific(Evas_Object *obj, Elm_Theme *th, Eina_Bool force);
310EAPI void elm_widget_translate(Evas_Object *obj);
311EAPI void elm_widget_focus_next_hook_set(Evas_Object *obj, Eina_Bool (*func)(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next));
312EAPI void elm_widget_on_focus_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data);
313EAPI void elm_widget_on_change_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data);
314EAPI void elm_widget_on_show_region_hook_set(Evas_Object *obj, void (*func)(void *data, Evas_Object *obj), void *data);
315EAPI 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));
316EAPI void elm_widget_text_set_hook_set(Evas_Object *obj, Elm_Widget_Text_Set_Cb func);
317#define elm_widget_text_set_hook_set(obj, func) elm_widget_text_set_hook_set(obj, (Elm_Widget_Text_Set_Cb)(func))
318EAPI void elm_widget_text_get_hook_set(Evas_Object *obj, Elm_Widget_Text_Get_Cb func);
319#define elm_widget_text_get_hook_set(obj, func) elm_widget_text_get_hook_set(obj, (Elm_Widget_Text_Get_Cb)(func))
320EAPI void elm_widget_content_set_hook_set(Evas_Object *obj, Elm_Widget_Content_Set_Cb func);
321#define elm_widget_content_set_hook_set(obj, func) elm_widget_content_set_hook_set(obj, (Elm_Widget_Content_Set_Cb)(func))
322EAPI void elm_widget_content_get_hook_set(Evas_Object *obj, Elm_Widget_Content_Get_Cb func);
323#define elm_widget_content_get_hook_set(obj, func) elm_widget_content_get_hook_set(obj, (Elm_Widget_Content_Get_Cb)(func))
324EAPI void elm_widget_content_unset_hook_set(Evas_Object *obj, Elm_Widget_Content_Unset_Cb func);
325#define elm_widget_content_unset_hook_set(obj, func) elm_widget_content_unset_hook_set(obj, (Elm_Widget_Content_Unset_Cb)(func))
326EAPI 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));
327EAPI void elm_widget_data_set(Evas_Object *obj, void *data);
328EAPI void *elm_widget_data_get(const Evas_Object *obj);
329EAPI void elm_widget_sub_object_add(Evas_Object *obj, Evas_Object *sobj);
330EAPI void elm_widget_sub_object_del(Evas_Object *obj, Evas_Object *sobj);
331EAPI const Eina_List *elm_widget_sub_object_list_get(const Evas_Object *obj);
332EAPI void elm_widget_resize_object_set(Evas_Object *obj, Evas_Object *sobj);
333EAPI void elm_widget_hover_object_set(Evas_Object *obj, Evas_Object *sobj);
334EAPI void elm_widget_signal_emit(Evas_Object *obj, const char *emission, const char *source);
335EAPI void elm_widget_signal_callback_add(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func, void *data);
336EAPI void *elm_widget_signal_callback_del(Evas_Object *obj, const char *emission, const char *source, Edje_Signal_Cb func);
337EAPI void elm_widget_can_focus_set(Evas_Object *obj, Eina_Bool can_focus);
338EAPI Eina_Bool elm_widget_can_focus_get(const Evas_Object *obj);
339EAPI Eina_Bool elm_widget_child_can_focus_get(const Evas_Object *obj);
340EAPI Eina_List *elm_widget_can_focus_child_list_get(const Evas_Object *obj);
341EAPI void elm_widget_tree_unfocusable_set(Evas_Object *obj, Eina_Bool tree_unfocusable);
342EAPI Eina_Bool elm_widget_tree_unfocusable_get(const Evas_Object *obj);
343EAPI void elm_widget_highlight_ignore_set(Evas_Object *obj, Eina_Bool ignore);
344EAPI Eina_Bool elm_widget_highlight_ignore_get(const Evas_Object *obj);
345EAPI void elm_widget_highlight_in_theme_set(Evas_Object *obj, Eina_Bool highlight);
346EAPI Eina_Bool elm_widget_highlight_in_theme_get(const Evas_Object *obj);
347EAPI Eina_Bool elm_widget_focus_get(const Evas_Object *obj);
348EAPI Evas_Object *elm_widget_focused_object_get(const Evas_Object *obj);
349EAPI Evas_Object *elm_widget_top_get(const Evas_Object *obj);
350EAPI Eina_Bool elm_widget_is(const Evas_Object *obj);
351EAPI Evas_Object *elm_widget_parent_widget_get(const Evas_Object *obj);
352EAPI void elm_widget_event_callback_add(Evas_Object *obj, Elm_Event_Cb func, const void *data);
353EAPI void *elm_widget_event_callback_del(Evas_Object *obj, Elm_Event_Cb func, const void *data);
354EAPI Eina_Bool elm_widget_event_propagate(Evas_Object *obj, Evas_Callback_Type type, void *event_info, Evas_Event_Flags *event_flags);
355EAPI void elm_widget_focus_custom_chain_set(Evas_Object *obj, Eina_List *objs);
356EAPI void elm_widget_focus_custom_chain_unset(Evas_Object *obj);
357EAPI const Eina_List *elm_widget_focus_custom_chain_get(const Evas_Object *obj);
358EAPI void elm_widget_focus_custom_chain_append(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
359EAPI void elm_widget_focus_custom_chain_prepend(Evas_Object *obj, Evas_Object *child, Evas_Object *relative_child);
360EAPI void elm_widget_focus_cycle(Evas_Object *obj, Elm_Focus_Direction dir);
361EAPI void elm_widget_focus_direction_go(Evas_Object *obj, int x, int y);
362EAPI Eina_Bool elm_widget_focus_next_get(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next);
363EAPI 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);
364EAPI void elm_widget_focus_set(Evas_Object *obj, int first);
365EAPI void elm_widget_focused_object_clear(Evas_Object *obj);
366EAPI Evas_Object *elm_widget_parent_get(const Evas_Object *obj);
367EAPI Evas_Object *elm_widget_parent2_get(const Evas_Object *obj);
368EAPI void elm_widget_parent2_set(Evas_Object *obj, Evas_Object *parent);
369EAPI void elm_widget_focus_steal(Evas_Object *obj);
370
371/**
372 * @internal
373 *
374 * Restore the focus state of the sub-tree.
375 *
376 * This API will restore the focus state of the sub-tree to the latest
377 * state. If a sub-tree is unfocused and wants to get back to the latest
378 * focus state, this API will be helpful.
379 *
380 * @param obj The widget root of sub-tree
381 *
382 * @ingroup Widget
383 */
384EAPI void elm_widget_focus_restore(Evas_Object *obj);
385
386EAPI void elm_widget_activate(Evas_Object *obj);
387EAPI void elm_widget_change(Evas_Object *obj);
388EAPI void elm_widget_disabled_set(Evas_Object *obj, Eina_Bool disabled);
389EAPI Eina_Bool elm_widget_disabled_get(const Evas_Object *obj);
390EAPI void elm_widget_show_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool forceshow);
391EAPI void elm_widget_show_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
392EAPI void elm_widget_focus_region_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
393EAPI void elm_widget_scroll_hold_push(Evas_Object *obj);
394EAPI void elm_widget_scroll_hold_pop(Evas_Object *obj);
395EAPI int elm_widget_scroll_hold_get(const Evas_Object *obj);
396EAPI void elm_widget_scroll_freeze_push(Evas_Object *obj);
397EAPI void elm_widget_scroll_freeze_pop(Evas_Object *obj);
398EAPI int elm_widget_scroll_freeze_get(const Evas_Object *obj);
399EAPI void elm_widget_scale_set(Evas_Object *obj, double scale);
400EAPI double elm_widget_scale_get(const Evas_Object *obj);
401EAPI Eina_Bool elm_widget_mirrored_get(const Evas_Object *obj);
402EAPI void elm_widget_mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
403EAPI Eina_Bool elm_widget_mirrored_automatic_get(const Evas_Object *obj);
404EAPI void elm_widget_mirrored_automatic_set(Evas_Object *obj, Eina_Bool automatic);
405EAPI void elm_widget_theme_set(Evas_Object *obj, Elm_Theme *th);
406EAPI Elm_Theme *elm_widget_theme_get(const Evas_Object *obj);
407EAPI Eina_Bool elm_widget_style_set(Evas_Object *obj, const char *style);
408EAPI const char *elm_widget_style_get(const Evas_Object *obj);
409EAPI void elm_widget_type_set(Evas_Object *obj, const char *type);
410EAPI const char *elm_widget_type_get(const Evas_Object *obj);
411EAPI void elm_widget_tooltip_add(Evas_Object *obj, Elm_Tooltip *tt);
412EAPI void elm_widget_tooltip_del(Evas_Object *obj, Elm_Tooltip *tt);
413EAPI void elm_widget_cursor_add(Evas_Object *obj, Elm_Cursor *cur);
414EAPI void elm_widget_cursor_del(Evas_Object *obj, Elm_Cursor *cur);
415EAPI void elm_widget_drag_lock_x_set(Evas_Object *obj, Eina_Bool lock);
416EAPI void elm_widget_drag_lock_y_set(Evas_Object *obj, Eina_Bool lock);
417EAPI Eina_Bool elm_widget_drag_lock_x_get(const Evas_Object *obj);
418EAPI Eina_Bool elm_widget_drag_lock_y_get(const Evas_Object *obj);
419EAPI int elm_widget_drag_child_locked_x_get(const Evas_Object *obj);
420EAPI int elm_widget_drag_child_locked_y_get(const Evas_Object *obj);
421EAPI Eina_Bool elm_widget_theme_object_set(Evas_Object *obj, Evas_Object *edj, const char *wname, const char *welement, const char *wstyle);
422EAPI void elm_widget_type_register(const char **ptr);
423EAPI void elm_widget_type_unregister(const char **ptr);
424EAPI Eina_Bool elm_widget_is_check(const Evas_Object *obj);
425EAPI Eina_Bool elm_widget_type_check(const Evas_Object *obj, const char *type, const char *func);
426EAPI Evas_Object *elm_widget_name_find(const Evas_Object *obj, const char *name, int recurse);
427EAPI Eina_List *elm_widget_stringlist_get(const char *str);
428EAPI void elm_widget_stringlist_free(Eina_List *list);
429EAPI void elm_widget_focus_hide_handle(Evas_Object *obj);
430EAPI void elm_widget_focus_mouse_up_handle(Evas_Object *obj);
431EAPI void elm_widget_focus_tree_unfocusable_handle(Evas_Object *obj);
432EAPI void elm_widget_focus_disabled_handle(Evas_Object *obj);
433EAPI unsigned int elm_widget_focus_order_get(const Evas_Object *obj);
434EAPI void elm_widget_text_part_set(Evas_Object *obj, const char *part, const char *label);
435EAPI const char *elm_widget_text_part_get(const Evas_Object *obj, const char *part);
436EAPI void elm_widget_domain_translatable_text_part_set(Evas_Object *obj, const char *part, const char *domain, const char *text);
437EAPI const char *elm_widget_translatable_text_part_get(const Evas_Object *obj, const char *part);
438EAPI void elm_widget_content_part_set(Evas_Object *obj, const char *part, Evas_Object *content);
439EAPI Evas_Object *elm_widget_content_part_get(const Evas_Object *obj, const char *part);
440EAPI Evas_Object *elm_widget_content_part_unset(Evas_Object *obj, const char *part);
441EAPI void elm_widget_access_info_set(Evas_Object *obj, const char *txt);
442EAPI const char *elm_widget_access_info_get(const Evas_Object *obj);
443EAPI Elm_Widget_Item *_elm_widget_item_new(Evas_Object *parent, size_t alloc_size);
444EAPI void _elm_widget_item_free(Elm_Widget_Item *item);
445EAPI void _elm_widget_item_del(Elm_Widget_Item *item);
446EAPI void _elm_widget_item_pre_notify_del(Elm_Widget_Item *item);
447EAPI void _elm_widget_item_del_cb_set(Elm_Widget_Item *item, Evas_Smart_Cb del_cb);
448EAPI void _elm_widget_item_data_set(Elm_Widget_Item *item, const void *data);
449EAPI void *_elm_widget_item_data_get(const Elm_Widget_Item *item);
450EAPI void _elm_widget_item_tooltip_text_set(Elm_Widget_Item *item, const char *text);
451EAPI void _elm_widget_item_tooltip_translatable_text_set(Elm_Widget_Item *item, const char *text);
452EAPI 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);
453EAPI void _elm_widget_item_tooltip_unset(Elm_Widget_Item *item);
454EAPI void _elm_widget_item_tooltip_style_set(Elm_Widget_Item *item, const char *style);
455EAPI Eina_Bool _elm_widget_item_tooltip_window_mode_set(Elm_Widget_Item *item, Eina_Bool disable);
456EAPI Eina_Bool _elm_widget_item_tooltip_window_mode_get(const Elm_Widget_Item *item);
457EAPI const char *_elm_widget_item_tooltip_style_get(const Elm_Widget_Item *item);
458EAPI void _elm_widget_item_cursor_set(Elm_Widget_Item *item, const char *cursor);
459EAPI const char *_elm_widget_item_cursor_get(const Elm_Widget_Item *item);
460EAPI void _elm_widget_item_cursor_unset(Elm_Widget_Item *item);
461EAPI void _elm_widget_item_cursor_style_set(Elm_Widget_Item *item, const char *style);
462EAPI const char *_elm_widget_item_cursor_style_get(const Elm_Widget_Item *item);
463EAPI void _elm_widget_item_cursor_engine_only_set(Elm_Widget_Item *item, Eina_Bool engine_only);
464EAPI Eina_Bool _elm_widget_item_cursor_engine_only_get(const Elm_Widget_Item *item);
465EAPI void _elm_widget_item_part_content_set(Elm_Widget_Item *item, const char *part, Evas_Object *content);
466EAPI Evas_Object *_elm_widget_item_part_content_get(const Elm_Widget_Item *item, const char *part);
467EAPI Evas_Object *_elm_widget_item_part_content_unset(Elm_Widget_Item *item, const char *part);
468EAPI void _elm_widget_item_part_text_set(Elm_Widget_Item *item, const char *part, const char *label);
469EAPI const char *_elm_widget_item_part_text_get(const Elm_Widget_Item *item, const char *part);
470EAPI void _elm_widget_item_signal_emit(Elm_Widget_Item *item, const char *emission, const char *source);
471EAPI void _elm_widget_item_content_set_hook_set(Elm_Widget_Item *item, Elm_Widget_Content_Set_Cb func);
472EAPI void _elm_widget_item_content_get_hook_set(Elm_Widget_Item *item, Elm_Widget_Content_Get_Cb func);
473EAPI void _elm_widget_item_content_unset_hook_set(Elm_Widget_Item *item, Elm_Widget_Content_Unset_Cb func);
474EAPI void _elm_widget_item_text_set_hook_set(Elm_Widget_Item *item, Elm_Widget_Text_Set_Cb func);
475EAPI void _elm_widget_item_text_get_hook_set(Elm_Widget_Item *item, Elm_Widget_Text_Get_Cb func);
476EAPI void _elm_widget_item_signal_emit_hook_set(Elm_Widget_Item *it, Elm_Widget_Signal_Emit_Cb func);
477EAPI void _elm_widget_item_access_info_set(Elm_Widget_Item *item, const char *txt);
478EAPI void _elm_widget_item_disabled_set(Elm_Widget_Item *item, Eina_Bool disabled);
479EAPI Eina_Bool _elm_widget_item_disabled_get(const Elm_Widget_Item *item);
480EAPI void _elm_widget_item_disable_hook_set(Elm_Widget_Item *item, Elm_Widget_Disable_Cb func);
481EAPI void _elm_widget_item_del_pre_hook_set(Elm_Widget_Item *item, Elm_Widget_Del_Pre_Cb func);
482
483/* debug function. don't use it unless you are tracking parenting issues */
484EAPI void elm_widget_tree_dump(const Evas_Object *top);
485EAPI void elm_widget_tree_dot_dump(const Evas_Object *top, FILE *output);
486
487/**
488 * Convenience macro to create new widget item, doing casts for you.
489 * @see _elm_widget_item_new()
490 * @param parent a valid elm_widget variant.
491 * @param type the C type that extends Elm_Widget_Item
492 */
493#define elm_widget_item_new(parent, type) \
494 (type *)_elm_widget_item_new((parent), sizeof(type))
495/**
496 * Convenience macro to free widget item, doing casts for you.
497 * @see _elm_widget_item_free()
498 * @param item a valid item.
499 */
500#define elm_widget_item_free(item) \
501 _elm_widget_item_free((Elm_Widget_Item *)item)
502
503/**
504 * Convenience macro to delete widget item, doing casts for you.
505 * @see _elm_widget_item_del()
506 * @param item a valid item.
507 */
508#define elm_widget_item_del(item) \
509 _elm_widget_item_del((Elm_Widget_Item *)item)
510/**
511 * Convenience macro to notify deletion of widget item, doing casts for you.
512 * @see _elm_widget_item_pre_notify_del()
513 */
514#define elm_widget_item_pre_notify_del(item) \
515 _elm_widget_item_pre_notify_del((Elm_Widget_Item *)item)
516/**
517 * Convenience macro to set deletion callback of widget item, doing casts for you.
518 * @see _elm_widget_item_del_cb_set()
519 */
520#define elm_widget_item_del_cb_set(item, del_cb) \
521 _elm_widget_item_del_cb_set((Elm_Widget_Item *)item, del_cb)
522
523/**
524 * Set item's data
525 * @see _elm_widget_item_data_set()
526 */
527#define elm_widget_item_data_set(item, data) \
528 _elm_widget_item_data_set((Elm_Widget_Item *)item, data)
529/**
530 * Get item's data
531 * @see _elm_widget_item_data_get()
532 */
533#define elm_widget_item_data_get(item) \
534 _elm_widget_item_data_get((const Elm_Widget_Item *)item)
535
536/**
537 * Convenience function to set widget item tooltip as a text string.
538 * @see _elm_widget_item_tooltip_text_set()
539 */
540#define elm_widget_item_tooltip_text_set(item, text) \
541 _elm_widget_item_tooltip_text_set((Elm_Widget_Item *)item, text)
542/**
543 * Convenience function to set widget item tooltip as a text string.
544 * @see _elm_widget_item_tooltip_text_set()
545 */
546#define elm_widget_item_tooltip_translatable_text_set(item, text) \
547 _elm_widget_item_tooltip_translatable_text_set((Elm_Widget_Item *)item, text)
548/**
549 * Convenience function to set widget item tooltip.
550 * @see _elm_widget_item_tooltip_content_cb_set()
551 */
552#define elm_widget_item_tooltip_content_cb_set(item, func, data, del_cb) \
553 _elm_widget_item_tooltip_content_cb_set((Elm_Widget_Item *)item, \
554 func, data, del_cb)
555/**
556 * Convenience function to unset widget item tooltip.
557 * @see _elm_widget_item_tooltip_unset()
558 */
559#define elm_widget_item_tooltip_unset(item) \
560 _elm_widget_item_tooltip_unset((Elm_Widget_Item *)item)
561/**
562 * Convenience function to change item's tooltip style.
563 * @see _elm_widget_item_tooltip_style_set()
564 */
565#define elm_widget_item_tooltip_style_set(item, style) \
566 _elm_widget_item_tooltip_style_set((Elm_Widget_Item *)item, style)
567
568#define elm_widget_item_tooltip_window_mode_set(item, disable) \
569 _elm_widget_item_tooltip_window_mode_set((Elm_Widget_Item *)item, disable)
570
571#define elm_widget_item_tooltip_window_mode_get(item) \
572 _elm_widget_item_tooltip_window_mode_get((Elm_Widget_Item *)item)
573/**
574 * Convenience function to query item's tooltip style.
575 * @see _elm_widget_item_tooltip_style_get()
576 */
577#define elm_widget_item_tooltip_style_get(item) \
578 _elm_widget_item_tooltip_style_get((const Elm_Widget_Item *)item)
579/**
580 * Convenience function to set widget item cursor.
581 * @see _elm_widget_item_cursor_set()
582 */
583#define elm_widget_item_cursor_set(item, cursor) \
584 _elm_widget_item_cursor_set((Elm_Widget_Item *)item, cursor)
585/**
586 * Convenience function to get widget item cursor.
587 * @see _elm_widget_item_cursor_get()
588 */
589#define elm_widget_item_cursor_get(item) \
590 _elm_widget_item_cursor_get((const Elm_Widget_Item *)item)
591/**
592 * Convenience function to unset widget item cursor.
593 * @see _elm_widget_item_cursor_unset()
594 */
595#define elm_widget_item_cursor_unset(item) \
596 _elm_widget_item_cursor_unset((Elm_Widget_Item *)item)
597/**
598 * Convenience function to change item's cursor style.
599 * @see _elm_widget_item_cursor_style_set()
600 */
601#define elm_widget_item_cursor_style_set(item, style) \
602 _elm_widget_item_cursor_style_set((Elm_Widget_Item *)item, style)
603/**
604 * Convenience function to query item's cursor style.
605 * @see _elm_widget_item_cursor_style_get()
606 */
607#define elm_widget_item_cursor_style_get(item) \
608 _elm_widget_item_cursor_style_get((const Elm_Widget_Item *)item)
609/**
610 * Convenience function to change item's cursor engine_only.
611 * @see _elm_widget_item_cursor_engine_only_set()
612 */
613#define elm_widget_item_cursor_engine_only_set(item, engine_only) \
614 _elm_widget_item_cursor_engine_only_set((Elm_Widget_Item *)item, engine_only)
615/**
616 * Convenience function to query item's cursor engine_only.
617 * @see _elm_widget_item_cursor_engine_only_get()
618 */
619#define elm_widget_item_cursor_engine_only_get(item) \
620 _elm_widget_item_cursor_engine_only_get((const Elm_Widget_Item *)item)
621/**
622 * Convenience function to query item's content set hook.
623 * @see _elm_widget_item_content_set_hook_set()
624 */
625#define elm_widget_item_content_set_hook_set(item, func) \
626 _elm_widget_item_content_set_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Content_Set_Cb)func)
627/**
628 * Convenience function to query item's content get hook.
629 * @see _elm_widget_item_content_get_hook_set()
630 */
631#define elm_widget_item_content_get_hook_set(item, func) \
632 _elm_widget_item_content_get_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Content_Get_Cb)func)
633/**
634 * Convenience function to query item's content unset hook.
635 * @see _elm_widget_item_content_unset_hook_set()
636 */
637#define elm_widget_item_content_unset_hook_set(item, func) \
638 _elm_widget_item_content_unset_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Content_Unset_Cb)func)
639/**
640 * Convenience function to query item's text set hook.
641 * @see _elm_widget_item_text_set_hook_set()
642 */
643#define elm_widget_item_text_set_hook_set(item, func) \
644 _elm_widget_item_text_set_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Text_Set_Cb)func)
645/**
646 * Convenience function to query item's text get hook.
647 * @see _elm_widget_item_text_get_hook_set()
648 */
649#define elm_widget_item_text_get_hook_set(item, func) \
650 _elm_widget_item_text_get_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Text_Get_Cb)func)
651/**
652 * Convenience function to query item's signal emit hook.
653 * @see _elm_widget_item_signal_emit_hook_set()
654 */
655#define elm_widget_item_signal_emit_hook_set(item, func) \
656 _elm_widget_item_signal_emit_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Signal_Emit_Cb)func)
657/**
658 * Convenience function to query disable get hook.
659 * @see _elm_widget_item_disabled_get()
660 */
661#define elm_widget_item_disabled_get(item) \
662 _elm_widget_item_disabled_get((Elm_Widget_Item *)item)
663/**
664 * Convenience function to query disable set hook.
665 * @see _elm_widget_item_disable_hook_set()
666 */
667#define elm_widget_item_disable_hook_set(item, func) \
668 _elm_widget_item_disable_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Disable_Cb)func)
669/**
670 * Convenience function to query del pre hook.
671 * @see _elm_widget_item_del_pre_hook_set()
672 */
673#define elm_widget_item_del_pre_hook_set(item, func) \
674 _elm_widget_item_del_pre_hook_set((Elm_Widget_Item *)item, (Elm_Widget_Del_Pre_Cb)func)
675
676#define ELM_WIDGET_ITEM_CHECK_OR_RETURN(item, ...) \
677 do { \
678 if (!item) { \
679 CRITICAL("Elm_Widget_Item " # item " is NULL"); \
680 return __VA_ARGS__; \
681 } \
682 if (!EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC)) { \
683 EINA_MAGIC_FAIL(item, ELM_WIDGET_ITEM_MAGIC); \
684 return __VA_ARGS__; \
685 } \
686 } while (0)
687
688#define ELM_WIDGET_ITEM_CHECK_OR_GOTO(item, label) \
689 do { \
690 if (!item) { \
691 CRITICAL("Elm_Widget_Item " # item " is NULL"); \
692 goto label; \
693 } \
694 if (!EINA_MAGIC_CHECK(item, ELM_WIDGET_ITEM_MAGIC)) { \
695 EINA_MAGIC_FAIL(item, ELM_WIDGET_ITEM_MAGIC); \
696 goto label; \
697 } \
698 } while (0)
699
700#define ELM_SET_WIDTYPE(widtype, type) \
701 do { \
702 if (!widtype) { \
703 widtype = eina_stringshare_add(type); \
704 elm_widget_type_register(&widtype); \
705 } \
706 } while (0)
707
708#define ELM_CHECK_WID_IS(obj) \
709 if (!elm_widget_is_check(obj)) return
710
711#define ELM_CHECK_WIDTYPE(obj, widtype) \
712 if (!obj || !elm_widget_type_check((obj), (widtype), __func__)) return
713
714#define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, ...) \
715 ELM_WIDGET_ITEM_CHECK_OR_RETURN((Elm_Widget_Item *)it, __VA_ARGS__); \
716 ELM_CHECK_WIDTYPE(it->base.widget, widtype) __VA_ARGS__;
717
718#define ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, label) \
719 ELM_WIDGET_ITEM_CHECK_OR_GOTO((Elm_Widget_Item *)it, label); \
720 if (!elm_widget_type_check((it->base.widget), (widtype), __func__)) goto label;
721
722#define ELM_WIDGET_STANDARD_SETUP(wdat, wdtype, par, evas, ob, ret) \
723 do { \
724 EINA_SAFETY_ON_NULL_RETURN_VAL((par), (ret)); \
725 evas = evas_object_evas_get(par); if (!(evas)) return (ret); \
726 wdat = ELM_NEW(wdtype); if (!(wdat)) return (ret); \
727 ob = elm_widget_add(evas); if (!(ob)) { free(wdat); return (ret); } \
728 } while (0)
729
730#define ELM_OBJ_ITEM_CHECK_OR_RETURN(it, ...) \
731 ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_RETURN(it, __VA_ARGS__);
732
733#define ELM_OBJ_ITEM_CHECK_OR_GOTO(it, label) \
734 ELM_WIDGET_ITEM_WIDTYPE_CHECK_OR_GOTO(it, label);
735
736/**
737 * The drag and drop API.
738 * Currently experimental, and will change when it does dynamic type
739 * addition RSN.
740 *
741 * Here so applications can start to use it, if they ask elm nicely.
742 *
743 * And yes, elm_widget, should probably be elm_experimental...
744 * Complaints about this code should go to /dev/null, or failing that nash.
745 */
746Eina_Bool elm_selection_selection_has_owner(void);
747Eina_Bool elm_drop_target_add(Evas_Object *widget, Elm_Sel_Type, Elm_Drop_Cb, void *);
748Eina_Bool elm_drop_target_del(Evas_Object *widget);
749Eina_Bool elm_drag_start(Evas_Object *, Elm_Sel_Format, const char *, void (*)(void *, Evas_Object *), void *);
750
751#endif
diff --git a/libraries/elementary/src/lib/elm_win.c b/libraries/elementary/src/lib/elm_win.c
new file mode 100644
index 0000000..54127c0
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_win.c
@@ -0,0 +1,3428 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4typedef struct _Elm_Win Elm_Win;
5
6struct _Elm_Win
7{
8 Ecore_Evas *ee;
9 Evas *evas;
10 Evas_Object *parent, *win_obj, *img_obj, *frame_obj;
11 Eina_List *subobjs;
12#ifdef HAVE_ELEMENTARY_X
13 Ecore_X_Window xwin;
14 Ecore_Event_Handler *client_message_handler;
15#endif
16 Ecore_Job *deferred_resize_job;
17 Ecore_Job *deferred_child_eval_job;
18
19 Elm_Win_Type type;
20 Elm_Win_Keyboard_Mode kbdmode;
21 Elm_Win_Indicator_Mode indmode;
22 Elm_Win_Indicator_Opacity_Mode ind_o_mode;
23 struct
24 {
25 const char *info;
26 Ecore_Timer *timer;
27 int repeat_count;
28 int shot_counter;
29 } shot;
30 int resize_location;
31 int *autodel_clear, rot;
32 int show_count;
33 struct
34 {
35 int x, y;
36 } screen;
37 struct
38 {
39 Ecore_Evas *ee;
40 Evas *evas;
41 Evas_Object *obj, *hot_obj;
42 int hot_x, hot_y;
43 } pointer;
44 struct
45 {
46 Evas_Object *top;
47
48 struct
49 {
50 Evas_Object *target;
51 Eina_Bool visible : 1;
52 Eina_Bool handled : 1;
53 } cur, prev;
54
55 const char *style;
56 Ecore_Job *reconf_job;
57
58 Eina_Bool enabled : 1;
59 Eina_Bool changed_theme : 1;
60 Eina_Bool top_animate : 1;
61 Eina_Bool geometry_changed : 1;
62 } focus_highlight;
63
64 Evas_Object *icon;
65 const char *title;
66 const char *icon_name;
67 const char *role;
68
69 double aspect;
70 Eina_Bool urgent : 1;
71 Eina_Bool modal : 1;
72 Eina_Bool demand_attention : 1;
73 Eina_Bool autodel : 1;
74 Eina_Bool constrain : 1;
75 Eina_Bool resizing : 1;
76 Eina_Bool iconified : 1;
77 Eina_Bool withdrawn : 1;
78 Eina_Bool sticky : 1;
79 Eina_Bool fullscreen : 1;
80 Eina_Bool maximized : 1;
81 Eina_Bool skip_focus : 1;
82};
83
84static const char *widtype = NULL;
85static void _elm_win_obj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
86static void _elm_win_obj_callback_img_obj_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
87static void _elm_win_obj_callback_parent_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
88static void _elm_win_obj_intercept_move(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y);
89static void _elm_win_obj_intercept_show(void *data, Evas_Object *obj);
90static void _elm_win_move(Ecore_Evas *ee);
91static void _elm_win_resize(Ecore_Evas *ee);
92static void _elm_win_delete_request(Ecore_Evas *ee);
93static void _elm_win_resize_job(void *data);
94#ifdef HAVE_ELEMENTARY_X
95static void _elm_win_xwin_update(Elm_Win *win);
96#endif
97static void _elm_win_eval_subobjs(Evas_Object *obj);
98static void _elm_win_subobj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info);
99static void _elm_win_subobj_callback_changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
100static void _elm_win_focus_highlight_init(Elm_Win *win);
101static void _elm_win_focus_highlight_shutdown(Elm_Win *win);
102static void _elm_win_focus_highlight_visible_set(Elm_Win *win, Eina_Bool visible);
103static void _elm_win_focus_highlight_reconfigure_job_start(Elm_Win *win);
104static void _elm_win_focus_highlight_reconfigure_job_stop(Elm_Win *win);
105static void _elm_win_focus_highlight_anim_end(void *data, Evas_Object *obj, const char *emission, const char *source);
106static void _elm_win_focus_highlight_reconfigure(Elm_Win *win);
107
108static void _elm_win_frame_add(Elm_Win *win, const char *style);
109static void _elm_win_frame_cb_move_start(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__);
110static void _elm_win_frame_cb_resize_start(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source);
111static void _elm_win_frame_cb_minimize(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__);
112static void _elm_win_frame_cb_maximize(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__);
113static void _elm_win_frame_cb_close(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__);
114
115//static void _elm_win_pointer_add(Elm_Win *win, const char *style);
116
117static const char SIG_DELETE_REQUEST[] = "delete,request";
118static const char SIG_FOCUS_OUT[] = "focus,out";
119static const char SIG_FOCUS_IN[] = "focus,in";
120static const char SIG_MOVED[] = "moved";
121static const char SIG_THEME_CHANGED[] = "theme,changed";
122static const char SIG_WITHDRAWN[] = "withdrawn";
123static const char SIG_ICONIFIED[] = "iconified";
124static const char SIG_NORMAL[] = "normal";
125static const char SIG_STICK[] = "stick";
126static const char SIG_UNSTICK[] = "unstick";
127static const char SIG_FULLSCREEN[] = "fullscreen";
128static const char SIG_UNFULLSCREEN[] = "unfullscreen";
129static const char SIG_MAXIMIZED[] = "maximized";
130static const char SIG_UNMAXIMIZED[] = "unmaximized";
131
132static const Evas_Smart_Cb_Description _signals[] = {
133 {SIG_DELETE_REQUEST, ""},
134 {SIG_FOCUS_OUT, ""},
135 {SIG_FOCUS_IN, ""},
136 {SIG_MOVED, ""},
137 {SIG_WITHDRAWN, ""},
138 {SIG_ICONIFIED, ""},
139 {SIG_NORMAL, ""},
140 {SIG_STICK, ""},
141 {SIG_UNSTICK, ""},
142 {SIG_FULLSCREEN, ""},
143 {SIG_UNFULLSCREEN, ""},
144 {SIG_MAXIMIZED, ""},
145 {SIG_UNMAXIMIZED, ""},
146 {NULL, NULL}
147};
148
149
150
151Eina_List *_elm_win_list = NULL;
152int _elm_win_deferred_free = 0;
153
154// exmaple shot spec (wait 0.1 sec then save as my-window.png):
155// ELM_ENGINE="shot:delay=0.1:file=my-window.png"
156
157static double
158_shot_delay_get(Elm_Win *win)
159{
160 char *p, *pd;
161 char *d = strdup(win->shot.info);
162
163 if (!d) return 0.5;
164 for (p = (char *)win->shot.info; *p; p++)
165 {
166 if (!strncmp(p, "delay=", 6))
167 {
168 double v;
169
170 for (pd = d, p += 6; (*p) && (*p != ':'); p++, pd++)
171 {
172 *pd = *p;
173 }
174 *pd = 0;
175 v = atof(d);
176 free(d);
177 return v;
178 }
179 }
180 free(d);
181 return 0.5;
182}
183
184static char *
185_shot_file_get(Elm_Win *win)
186{
187 char *p;
188 char *tmp = strdup(win->shot.info);
189 char *repname = NULL;
190
191 if (!tmp) return NULL;
192
193 for (p = (char *)win->shot.info; *p; p++)
194 {
195 if (!strncmp(p, "file=", 5))
196 {
197 strcpy(tmp, p + 5);
198 if (!win->shot.repeat_count) return tmp;
199 else
200 {
201 char *dotptr = strrchr(tmp, '.');
202 if (dotptr)
203 {
204 size_t size = sizeof(char)*(strlen(tmp) + 16);
205 repname = malloc(size);
206 strncpy(repname, tmp, dotptr - tmp);
207 snprintf(repname + (dotptr - tmp), size - (dotptr - tmp), "%03i",
208 win->shot.shot_counter + 1);
209 strcat(repname, dotptr);
210 free(tmp);
211 return repname;
212 }
213 }
214 }
215 }
216 free(tmp);
217 if (!win->shot.repeat_count) return strdup("out.png");
218
219 repname = malloc(sizeof(char) * 24);
220 snprintf(repname, sizeof(char) * 24, "out%03i.png", win->shot.shot_counter + 1);
221 return repname;
222}
223
224static int
225_shot_repeat_count_get(Elm_Win *win)
226{
227 char *p, *pd;
228 char *d = strdup(win->shot.info);
229
230 if (!d) return 0;
231 for (p = (char *)win->shot.info; *p; p++)
232 {
233 if (!strncmp(p, "repeat=", 7))
234 {
235 int v;
236
237 for (pd = d, p += 7; (*p) && (*p != ':'); p++, pd++)
238 {
239 *pd = *p;
240 }
241 *pd = 0;
242 v = atoi(d);
243 if (v < 0) v = 0;
244 if (v > 1000) v = 999;
245 free(d);
246 return v;
247 }
248 }
249 free(d);
250 return 0;
251}
252
253static char *
254_shot_key_get(Elm_Win *win __UNUSED__)
255{
256 return NULL;
257}
258
259static char *
260_shot_flags_get(Elm_Win *win __UNUSED__)
261{
262 return NULL;
263}
264
265static void
266_shot_do(Elm_Win *win)
267{
268 Ecore_Evas *ee;
269 Evas_Object *o;
270 unsigned int *pixels;
271 int w, h;
272 char *file, *key, *flags;
273
274 ecore_evas_manual_render(win->ee);
275 pixels = (void *)ecore_evas_buffer_pixels_get(win->ee);
276 if (!pixels) return;
277 ecore_evas_geometry_get(win->ee, NULL, NULL, &w, &h);
278 if ((w < 1) || (h < 1)) return;
279 file = _shot_file_get(win);
280 if (!file) return;
281 key = _shot_key_get(win);
282 flags = _shot_flags_get(win);
283 ee = ecore_evas_buffer_new(1, 1);
284 o = evas_object_image_add(ecore_evas_get(ee));
285 evas_object_image_alpha_set(o, ecore_evas_alpha_get(win->ee));
286 evas_object_image_size_set(o, w, h);
287 evas_object_image_data_set(o, pixels);
288 if (!evas_object_image_save(o, file, key, flags))
289 {
290 ERR("Cannot save window to '%s' (key '%s', flags '%s')",
291 file, key, flags);
292 }
293 free(file);
294 if (key) free(key);
295 if (flags) free(flags);
296 ecore_evas_free(ee);
297 if (win->shot.repeat_count) win->shot.shot_counter++;
298}
299
300static Eina_Bool
301_shot_delay(void *data)
302{
303 Elm_Win *win = data;
304 _shot_do(win);
305 if (win->shot.repeat_count)
306 {
307 int remainshot = (win->shot.repeat_count - win->shot.shot_counter);
308 if (remainshot > 0) return EINA_TRUE;
309 }
310 win->shot.timer = NULL;
311 elm_exit();
312 return EINA_FALSE;
313}
314
315static void
316_shot_init(Elm_Win *win)
317{
318 if (!win->shot.info) return;
319 win->shot.repeat_count = _shot_repeat_count_get(win);
320 win->shot.shot_counter = 0;
321}
322
323static void
324_shot_handle(Elm_Win *win)
325{
326 if (!win->shot.info) return;
327 win->shot.timer = ecore_timer_add(_shot_delay_get(win), _shot_delay, win);
328}
329
330static void
331_elm_win_move(Ecore_Evas *ee)
332{
333 Evas_Object *obj = ecore_evas_object_associate_get(ee);
334 Elm_Win *win;
335 int x, y;
336
337 if (!obj) return;
338 win = elm_widget_data_get(obj);
339 if (!win) return;
340 ecore_evas_geometry_get(ee, &x, &y, NULL, NULL);
341 win->screen.x = x;
342 win->screen.y = y;
343 evas_object_smart_callback_call(win->win_obj, SIG_MOVED, NULL);
344}
345
346static void
347_elm_win_resize(Ecore_Evas *ee)
348{
349 Evas_Object *obj = ecore_evas_object_associate_get(ee);
350 Elm_Win *win;
351
352 if (!obj) return;
353 win = elm_widget_data_get(obj);
354 if (!win) return;
355 if (win->deferred_resize_job) ecore_job_del(win->deferred_resize_job);
356 win->deferred_resize_job = ecore_job_add(_elm_win_resize_job, win);
357}
358
359static void
360_elm_win_mouse_in(Ecore_Evas *ee)
361{
362 Evas_Object *obj;
363 Elm_Win *win;
364
365 if (!(obj = ecore_evas_object_associate_get(ee))) return;
366 if (!(win = elm_widget_data_get(obj))) return;
367 if (win->resizing) win->resizing = EINA_FALSE;
368}
369
370static void
371_elm_win_focus_in(Ecore_Evas *ee)
372{
373 Evas_Object *obj = ecore_evas_object_associate_get(ee);
374 Elm_Win *win;
375
376 if (!obj) return;
377 win = elm_widget_data_get(obj);
378 if (!win) return;
379 _elm_widget_top_win_focused_set(win->win_obj, EINA_TRUE);
380 if (!elm_widget_focus_order_get(obj))
381 {
382 elm_widget_focus_steal(win->win_obj);
383 win->show_count++;
384 }
385 else
386 elm_widget_focus_restore(win->win_obj);
387 evas_object_smart_callback_call(win->win_obj, SIG_FOCUS_IN, NULL);
388 win->focus_highlight.cur.visible = EINA_TRUE;
389 _elm_win_focus_highlight_reconfigure_job_start(win);
390 if (win->frame_obj)
391 {
392 edje_object_signal_emit(win->frame_obj, "elm,action,focus", "elm");
393 }
394 else if (win->img_obj)
395 {
396 /* do nothing */
397 }
398}
399
400static void
401_elm_win_focus_out(Ecore_Evas *ee)
402{
403 Evas_Object *obj = ecore_evas_object_associate_get(ee);
404 Elm_Win *win;
405
406 if (!obj) return;
407 win = elm_widget_data_get(obj);
408 if (!win) return;
409 elm_object_focus_set(win->win_obj, EINA_FALSE);
410 _elm_widget_top_win_focused_set(win->win_obj, EINA_FALSE);
411 evas_object_smart_callback_call(win->win_obj, SIG_FOCUS_OUT, NULL);
412 win->focus_highlight.cur.visible = EINA_FALSE;
413 _elm_win_focus_highlight_reconfigure_job_start(win);
414 if (win->frame_obj)
415 {
416 edje_object_signal_emit(win->frame_obj, "elm,action,unfocus", "elm");
417 }
418 else if (win->img_obj)
419 {
420 /* do nothing */
421 }
422}
423
424static void
425_elm_win_state_change(Ecore_Evas *ee)
426{
427 Evas_Object *obj;
428 Elm_Win *win;
429 Eina_Bool ch_withdrawn = EINA_FALSE;
430 Eina_Bool ch_sticky = EINA_FALSE;
431 Eina_Bool ch_iconified = EINA_FALSE;
432 Eina_Bool ch_fullscreen = EINA_FALSE;
433 Eina_Bool ch_maximized = EINA_FALSE;
434
435 if (!(obj = ecore_evas_object_associate_get(ee))) return;
436
437 if (!(win = elm_widget_data_get(obj))) return;
438
439 if (win->withdrawn != ecore_evas_withdrawn_get(win->ee))
440 {
441 win->withdrawn = ecore_evas_withdrawn_get(win->ee);
442 ch_withdrawn = EINA_TRUE;
443 }
444 if (win->sticky != ecore_evas_sticky_get(win->ee))
445 {
446 win->sticky = ecore_evas_sticky_get(win->ee);
447 ch_sticky = EINA_TRUE;
448 }
449 if (win->iconified != ecore_evas_iconified_get(win->ee))
450 {
451 win->iconified = ecore_evas_iconified_get(win->ee);
452 ch_iconified = EINA_TRUE;
453 }
454 if (win->fullscreen != ecore_evas_fullscreen_get(win->ee))
455 {
456 win->fullscreen = ecore_evas_fullscreen_get(win->ee);
457 ch_fullscreen = EINA_TRUE;
458 }
459 if (win->maximized != ecore_evas_maximized_get(win->ee))
460 {
461 win->maximized = ecore_evas_maximized_get(win->ee);
462 ch_maximized = EINA_TRUE;
463 }
464 if ((ch_withdrawn) || (ch_iconified))
465 {
466 if (win->withdrawn)
467 evas_object_smart_callback_call(win->win_obj, SIG_WITHDRAWN, NULL);
468 else if (win->iconified)
469 evas_object_smart_callback_call(win->win_obj, SIG_ICONIFIED, NULL);
470 else
471 evas_object_smart_callback_call(win->win_obj, SIG_NORMAL, NULL);
472 }
473 if (ch_sticky)
474 {
475 if (win->sticky)
476 evas_object_smart_callback_call(win->win_obj, SIG_STICK, NULL);
477 else
478 evas_object_smart_callback_call(win->win_obj, SIG_UNSTICK, NULL);
479 }
480 if (ch_fullscreen)
481 {
482 if (win->fullscreen)
483 evas_object_smart_callback_call(win->win_obj, SIG_FULLSCREEN, NULL);
484 else
485 evas_object_smart_callback_call(win->win_obj, SIG_UNFULLSCREEN, NULL);
486 }
487 if (ch_maximized)
488 {
489 if (win->maximized)
490 evas_object_smart_callback_call(win->win_obj, SIG_MAXIMIZED, NULL);
491 else
492 evas_object_smart_callback_call(win->win_obj, SIG_UNMAXIMIZED, NULL);
493 }
494}
495
496static Eina_Bool
497_elm_win_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
498{
499 Elm_Win *wd = elm_widget_data_get(obj);
500 const Eina_List *items;
501 const Eina_List *list;
502 void *(*list_data_get) (const Eina_List *list);
503
504 if (!wd)
505 return EINA_FALSE;
506 list = elm_widget_sub_object_list_get(obj);
507
508 /* Focus chain */
509 if (list)
510 {
511 if (!(items = elm_widget_focus_custom_chain_get(obj)))
512 items = list;
513
514 list_data_get = eina_list_data_get;
515
516 elm_widget_focus_list_next_get(obj, items, list_data_get, dir, next);
517
518 if (*next)
519 return EINA_TRUE;
520 }
521 *next = (Evas_Object *)obj;
522 return EINA_FALSE;
523}
524
525static void
526_elm_win_on_focus_hook(void *data __UNUSED__, Evas_Object *obj)
527{
528 Elm_Win *win = elm_widget_data_get(obj);
529 if (!win) return;
530
531 if (win->img_obj)
532 evas_object_focus_set(win->img_obj, elm_widget_focus_get(obj));
533 else
534 evas_object_focus_set(obj, elm_widget_focus_get(obj));
535}
536
537static Eina_Bool
538_elm_win_event_cb(Evas_Object *obj, Evas_Object *src __UNUSED__, Evas_Callback_Type type, void *event_info)
539{
540 if (type == EVAS_CALLBACK_KEY_DOWN)
541 {
542 Evas_Event_Key_Down *ev = event_info;
543 if (!strcmp(ev->keyname, "Tab"))
544 {
545 if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
546 elm_widget_focus_cycle(obj, ELM_FOCUS_PREVIOUS);
547 else
548 elm_widget_focus_cycle(obj, ELM_FOCUS_NEXT);
549 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
550 return EINA_TRUE;
551 }
552 else if ((!strcmp(ev->keyname, "Left")) ||
553 ((!strcmp(ev->keyname, "KP_Left")) && (!ev->string)))
554 {
555 //TODO : woohyun jung
556 }
557 else if ((!strcmp(ev->keyname, "Right")) ||
558 ((!strcmp(ev->keyname, "KP_Right")) && (!ev->string)))
559 {
560 //TODO : woohyun jung
561 }
562 else if ((!strcmp(ev->keyname, "Up")) ||
563 ((!strcmp(ev->keyname, "KP_Up")) && (!ev->string)))
564 {
565 //TODO : woohyun jung
566 }
567 else if ((!strcmp(ev->keyname, "Down")) ||
568 ((!strcmp(ev->keyname, "KP_Down")) && (!ev->string)))
569 {
570 //TODO : woohyun jung
571 }
572 }
573
574 return EINA_FALSE;
575}
576
577static void
578_deferred_ecore_evas_free(void *data)
579{
580 ecore_evas_free(data);
581 _elm_win_deferred_free--;
582}
583
584static void
585_elm_win_obj_callback_show(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
586{
587 Elm_Win *win = data;
588
589 if (!win->show_count) win->show_count++;
590 if (win->shot.info) _shot_handle(win);
591}
592
593static void
594_elm_win_obj_callback_hide(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
595{
596 Elm_Win *win = data;
597
598 if (win->frame_obj)
599 {
600 evas_object_hide(win->frame_obj);
601 }
602 else if (win->img_obj)
603 {
604 evas_object_hide(win->img_obj);
605 }
606 if (win->pointer.obj)
607 {
608 evas_object_hide(win->pointer.obj);
609 ecore_evas_hide(win->pointer.ee);
610 }
611}
612
613static void
614_elm_win_obj_callback_del(void *data, Evas *e, Evas_Object *obj, void *event_info __UNUSED__)
615{
616 Elm_Win *win = data;
617 Evas_Object *child, *child2 = NULL;
618
619 if (win->parent)
620 {
621 evas_object_event_callback_del_full(win->parent, EVAS_CALLBACK_DEL,
622 _elm_win_obj_callback_parent_del, win);
623 win->parent = NULL;
624 }
625 if (win->autodel_clear) *(win->autodel_clear) = -1;
626 _elm_win_list = eina_list_remove(_elm_win_list, win->win_obj);
627 while (win->subobjs) elm_win_resize_object_del(obj, win->subobjs->data);
628 if (win->ee)
629 {
630 ecore_evas_callback_delete_request_set(win->ee, NULL);
631 ecore_evas_callback_resize_set(win->ee, NULL);
632 }
633 if (win->deferred_resize_job) ecore_job_del(win->deferred_resize_job);
634 if (win->deferred_child_eval_job) ecore_job_del(win->deferred_child_eval_job);
635 if (win->shot.info) eina_stringshare_del(win->shot.info);
636 if (win->shot.timer) ecore_timer_del(win->shot.timer);
637 evas_object_event_callback_del_full(win->win_obj, EVAS_CALLBACK_DEL,
638 _elm_win_obj_callback_del, win);
639 child = evas_object_bottom_get(win->evas);
640 while (child)
641 {
642 /* if the object we see *IS* the window object (because we are
643 * faking a parent object inside the canvas), then skip it and
644 * go to the next one */
645 if (child == obj)
646 {
647 child = evas_object_above_get(child);
648 if (!child) break;
649 }
650 /* if we are using the next object above from the previous loop */
651 if (child == child2)
652 {
653 /* this object has refcounts from the previous loop */
654 child2 = evas_object_above_get(child);
655 if (child2) evas_object_ref(child2);
656 evas_object_del(child);
657 /* so unref from previous loop */
658 evas_object_unref(child);
659 child = child2;
660 }
661 else
662 {
663 /* just delete as normal (probably only first object */
664 child2 = evas_object_above_get(child);
665 if (child2) evas_object_ref(child2);
666 evas_object_del(child);
667 child = child2;
668 }
669 }
670#ifdef HAVE_ELEMENTARY_X
671 if (win->client_message_handler)
672 ecore_event_handler_del(win->client_message_handler);
673#endif
674 // FIXME: Why are we flushing edje on every window destroy ??
675 // edje_file_cache_flush();
676 // edje_collection_cache_flush();
677 // evas_image_cache_flush(win->evas);
678 // evas_font_cache_flush(win->evas);
679 // FIXME: we are in the del handler for the object and delete the canvas
680 // that lives under it from the handler... nasty. deferring doesn't help either
681
682 if (win->img_obj)
683 {
684 win->img_obj = NULL;
685 }
686 else
687 {
688 if (win->ee)
689 {
690 ecore_job_add(_deferred_ecore_evas_free, win->ee);
691 _elm_win_deferred_free++;
692 }
693 }
694
695 _elm_win_focus_highlight_shutdown(win);
696 eina_stringshare_del(win->focus_highlight.style);
697
698 if (win->title) eina_stringshare_del(win->title);
699 if (win->icon_name) eina_stringshare_del(win->icon_name);
700 if (win->role) eina_stringshare_del(win->role);
701 if (win->icon) evas_object_del(win->icon);
702
703 free(win);
704
705 if ((!_elm_win_list) &&
706 (elm_policy_get(ELM_POLICY_QUIT) == ELM_POLICY_QUIT_LAST_WINDOW_CLOSED))
707 {
708 edje_file_cache_flush();
709 edje_collection_cache_flush();
710 evas_image_cache_flush(e);
711 evas_font_cache_flush(e);
712 elm_exit();
713 }
714}
715
716static void
717_elm_win_obj_callback_img_obj_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
718{
719 Elm_Win *win = data;
720 if (!win->img_obj) return;
721 evas_object_event_callback_del_full
722 (win->img_obj, EVAS_CALLBACK_DEL, _elm_win_obj_callback_img_obj_del, win);
723 evas_object_del(win->img_obj);
724}
725
726static void
727_elm_win_obj_callback_parent_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
728{
729 Elm_Win *win = data;
730 if (obj == win->parent) win->parent = NULL;
731}
732
733static void
734_elm_win_obj_intercept_move(void *data, Evas_Object *obj, Evas_Coord x, Evas_Coord y)
735{
736 Elm_Win *win = data;
737
738 if (win->img_obj)
739 {
740 if ((x != win->screen.x) || (y != win->screen.y))
741 {
742 win->screen.x = x;
743 win->screen.y = y;
744 evas_object_smart_callback_call(win->win_obj, SIG_MOVED, NULL);
745 }
746 }
747 else
748 {
749 evas_object_move(obj, x, y);
750 }
751}
752
753static void
754_elm_win_obj_intercept_show(void *data, Evas_Object *obj)
755{
756 Elm_Win *win = data;
757 // this is called to make sure all smart containers have calculated their
758 // sizes BEFORE we show the window to make sure it initially appears at
759 // our desired size (ie min size is known first)
760 evas_smart_objects_calculate(evas_object_evas_get(obj));
761 if (win->frame_obj)
762 {
763 evas_object_show(win->frame_obj);
764 }
765 else if (win->img_obj)
766 {
767 evas_object_show(win->img_obj);
768 }
769 if (win->pointer.obj)
770 {
771 ecore_evas_show(win->pointer.ee);
772 evas_object_show(win->pointer.obj);
773 /* ecore_evas_wayland_pointer_set(win->pointer.ee, 10, 10); */
774 }
775 evas_object_show(obj);
776}
777
778static void
779_elm_win_obj_callback_move(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
780{
781 Elm_Win *win = data;
782
783 if (ecore_evas_override_get(win->ee))
784 {
785 Evas_Coord x, y;
786
787 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
788 win->screen.x = x;
789 win->screen.y = y;
790 evas_object_smart_callback_call(win->win_obj, SIG_MOVED, NULL);
791 }
792 if (win->frame_obj)
793 {
794 Evas_Coord x, y;
795
796 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
797 win->screen.x = x;
798 win->screen.y = y;
799 }
800 else if (win->img_obj)
801 {
802 Evas_Coord x, y;
803
804 evas_object_geometry_get(obj, &x, &y, NULL, NULL);
805 win->screen.x = x;
806 win->screen.y = y;
807// evas_object_move(win->img_obj, x, y);
808 }
809}
810
811static void
812_elm_win_obj_callback_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
813{
814 Elm_Win *win = data;
815
816 if (win->frame_obj)
817 {
818 }
819 else if (win->img_obj)
820 {
821 Evas_Coord w = 1, h = 1;
822
823 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
824 if (win->constrain)
825 {
826 int sw, sh;
827 ecore_evas_screen_geometry_get(win->ee, NULL, NULL, &sw, &sh);
828 w = MIN(w, sw);
829 h = MIN(h, sh);
830 }
831 if (w < 1) w = 1;
832 if (h < 1) h = 1;
833 evas_object_image_size_set(win->img_obj, w, h);
834 }
835}
836
837static void
838_elm_win_delete_request(Ecore_Evas *ee)
839{
840 Evas_Object *obj = ecore_evas_object_associate_get(ee);
841 Elm_Win *win;
842 if (strcmp(elm_widget_type_get(obj), "win")) return;
843
844 win = elm_widget_data_get(obj);
845 if (!win) return;
846 int autodel = win->autodel;
847 win->autodel_clear = &autodel;
848 evas_object_ref(win->win_obj);
849 evas_object_smart_callback_call(win->win_obj, SIG_DELETE_REQUEST, NULL);
850 // FIXME: if above callback deletes - then the below will be invalid
851 if (autodel) evas_object_del(win->win_obj);
852 else win->autodel_clear = NULL;
853 evas_object_unref(win->win_obj);
854}
855
856static void
857_elm_win_resize_job(void *data)
858{
859 Elm_Win *win = data;
860 const Eina_List *l;
861 Evas_Object *obj;
862 int w, h;
863
864 win->deferred_resize_job = NULL;
865 ecore_evas_request_geometry_get(win->ee, NULL, NULL, &w, &h);
866 if (win->constrain)
867 {
868 int sw, sh;
869 ecore_evas_screen_geometry_get(win->ee, NULL, NULL, &sw, &sh);
870 w = MIN(w, sw);
871 h = MIN(h, sh);
872 }
873 if (win->frame_obj)
874 {
875 evas_object_resize(win->frame_obj, w, h);
876 }
877 else if (win->img_obj)
878 {
879 }
880 evas_object_resize(win->win_obj, w, h);
881 EINA_LIST_FOREACH(win->subobjs, l, obj)
882 {
883 evas_object_move(obj, 0, 0);
884 evas_object_resize(obj, w, h);
885 }
886}
887
888#ifdef HAVE_ELEMENTARY_X
889static void
890_elm_win_xwindow_get(Elm_Win *win)
891{
892 win->xwin = 0;
893
894#define ENGINE_COMPARE(name) (!strcmp(_elm_preferred_engine, name))
895 if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
896 {
897 if (win->ee) win->xwin = ecore_evas_software_x11_window_get(win->ee);
898 }
899 else if (ENGINE_COMPARE(ELM_SOFTWARE_X11) ||
900 ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
901 ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE) ||
902 ENGINE_COMPARE(ELM_SOFTWARE_SDL) ||
903 ENGINE_COMPARE(ELM_SOFTWARE_16_SDL) ||
904 ENGINE_COMPARE(ELM_OPENGL_SDL) ||
905 ENGINE_COMPARE(ELM_OPENGL_COCOA))
906 {
907 }
908 else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
909 {
910 if (win->ee) win->xwin = ecore_evas_software_x11_16_window_get(win->ee);
911 }
912 else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
913 {
914 if (win->ee) win->xwin = ecore_evas_software_x11_8_window_get(win->ee);
915 }
916/* killed
917 else if (ENGINE_COMPARE(ELM_XRENDER_X11))
918 {
919 if (win->ee) win->xwin = ecore_evas_xrender_x11_window_get(win->ee);
920 }
921 */
922 else if (ENGINE_COMPARE(ELM_OPENGL_X11))
923 {
924 if (win->ee) win->xwin = ecore_evas_gl_x11_window_get(win->ee);
925 }
926 else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
927 {
928 if (win->ee) win->xwin = (long)ecore_evas_win32_window_get(win->ee);
929 }
930#undef ENGINE_COMPARE
931}
932#endif
933
934#ifdef HAVE_ELEMENTARY_X
935static void
936_elm_win_xwin_update(Elm_Win *win)
937{
938 const char *s;
939
940 _elm_win_xwindow_get(win);
941 if (win->parent)
942 {
943 Elm_Win *win2;
944
945 win2 = elm_widget_data_get(win->parent);
946 if (win2)
947 {
948 if (win->xwin)
949 ecore_x_icccm_transient_for_set(win->xwin, win2->xwin);
950 }
951 }
952
953 if (!win->xwin) return; /* nothing more to do */
954
955 s = win->title;
956 if (!s) s = _elm_appname;
957 if (!s) s = "";
958 if (win->icon_name) s = win->icon_name;
959 ecore_x_icccm_icon_name_set(win->xwin, s);
960 ecore_x_netwm_icon_name_set(win->xwin, s);
961
962 s = win->role;
963 if (s) ecore_x_icccm_window_role_set(win->xwin, s);
964
965 // set window icon
966 if (win->icon)
967 {
968 void *data;
969
970 data = evas_object_image_data_get(win->icon, EINA_FALSE);
971 if (data)
972 {
973 Ecore_X_Icon ic;
974 int w = 0, h = 0, stride, x, y;
975 unsigned char *p;
976 unsigned int *p2;
977
978 evas_object_image_size_get(win->icon, &w, &h);
979 stride = evas_object_image_stride_get(win->icon);
980 if ((w > 0) && (h > 0) &&
981 (stride >= (int)(w * sizeof(unsigned int))))
982 {
983 ic.width = w;
984 ic.height = h;
985 ic.data = malloc(w * h * sizeof(unsigned int));
986
987 if (ic.data)
988 {
989 p = (unsigned char *)data;
990 p2 = (unsigned int *)ic.data;
991 for (y = 0; y < h; y++)
992 {
993 for (x = 0; x < w; x++)
994 {
995 *p2 = *((unsigned int *)p);
996 p += sizeof(unsigned int);
997 p2++;
998 }
999 p += (stride - (w * sizeof(unsigned int)));
1000 }
1001 ecore_x_netwm_icons_set(win->xwin, &ic, 1);
1002 free(ic.data);
1003 }
1004 }
1005 evas_object_image_data_set(win->icon, data);
1006 }
1007 }
1008
1009 switch (win->type)
1010 {
1011 case ELM_WIN_BASIC:
1012 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_NORMAL);
1013 break;
1014 case ELM_WIN_DIALOG_BASIC:
1015 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DIALOG);
1016 break;
1017 case ELM_WIN_DESKTOP:
1018 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DESKTOP);
1019 break;
1020 case ELM_WIN_DOCK:
1021 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DOCK);
1022 break;
1023 case ELM_WIN_TOOLBAR:
1024 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_TOOLBAR);
1025 break;
1026 case ELM_WIN_MENU:
1027 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_MENU);
1028 break;
1029 case ELM_WIN_UTILITY:
1030 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_UTILITY);
1031 break;
1032 case ELM_WIN_SPLASH:
1033 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_SPLASH);
1034 break;
1035 case ELM_WIN_DROPDOWN_MENU:
1036 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DROPDOWN_MENU);
1037 break;
1038 case ELM_WIN_POPUP_MENU:
1039 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_POPUP_MENU);
1040 break;
1041 case ELM_WIN_TOOLTIP:
1042 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_TOOLTIP);
1043 break;
1044 case ELM_WIN_NOTIFICATION:
1045 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_NOTIFICATION);
1046 break;
1047 case ELM_WIN_COMBO:
1048 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_COMBO);
1049 break;
1050 case ELM_WIN_DND:
1051 ecore_x_netwm_window_type_set(win->xwin, ECORE_X_WINDOW_TYPE_DND);
1052 break;
1053 default:
1054 break;
1055 }
1056 ecore_x_e_virtual_keyboard_state_set
1057 (win->xwin, (Ecore_X_Virtual_Keyboard_State)win->kbdmode);
1058 if (win->indmode == ELM_WIN_INDICATOR_SHOW)
1059 ecore_x_e_illume_indicator_state_set
1060 (win->xwin, ECORE_X_ILLUME_INDICATOR_STATE_ON);
1061 else if (win->indmode == ELM_WIN_INDICATOR_HIDE)
1062 ecore_x_e_illume_indicator_state_set
1063 (win->xwin, ECORE_X_ILLUME_INDICATOR_STATE_OFF);
1064}
1065#endif
1066
1067static void
1068_elm_win_eval_subobjs(Evas_Object *obj)
1069{
1070 const Eina_List *l;
1071 const Evas_Object *child;
1072
1073 Elm_Win *win = elm_widget_data_get(obj);
1074 Evas_Coord w, h, minw = -1, minh = -1, maxw = -1, maxh = -1;
1075 int xx = 1, xy = 1;
1076 double wx, wy;
1077
1078 EINA_LIST_FOREACH(win->subobjs, l, child)
1079 {
1080 evas_object_size_hint_weight_get(child, &wx, &wy);
1081 if (wx == 0.0) xx = 0;
1082 if (wy == 0.0) xy = 0;
1083
1084 evas_object_size_hint_min_get(child, &w, &h);
1085 if (w < 1) w = 1;
1086 if (h < 1) h = 1;
1087 if (w > minw) minw = w;
1088 if (h > minh) minh = h;
1089
1090 evas_object_size_hint_max_get(child, &w, &h);
1091 if (w < 1) w = -1;
1092 if (h < 1) h = -1;
1093 if (maxw == -1) maxw = w;
1094 else if ((w > 0) && (w < maxw)) maxw = w;
1095 if (maxh == -1) maxh = h;
1096 else if ((h > 0) && (h < maxh)) maxh = h;
1097 }
1098 if (!xx) maxw = minw;
1099 else maxw = 32767;
1100 if (!xy) maxh = minh;
1101 else maxh = 32767;
1102 evas_object_size_hint_min_set(obj, minw, minh);
1103 evas_object_size_hint_max_set(obj, maxw, maxh);
1104 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
1105 if (w < minw) w = minw;
1106 if (h < minh) h = minh;
1107 if ((maxw >= 0) && (w > maxw)) w = maxw;
1108 if ((maxh >= 0) && (h > maxh)) h = maxh;
1109 evas_object_resize(obj, w, h);
1110}
1111
1112static void
1113_elm_win_subobj_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1114{
1115 Elm_Win *win = elm_widget_data_get(data);
1116 win->subobjs = eina_list_remove(win->subobjs, obj);
1117 _elm_win_eval_subobjs(win->win_obj);
1118}
1119
1120static void
1121_elm_win_subobj_callback_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1122{
1123 _elm_win_eval_subobjs(data);
1124}
1125
1126void
1127_elm_win_shutdown(void)
1128{
1129 while (_elm_win_list)
1130 evas_object_del(_elm_win_list->data);
1131}
1132
1133void
1134_elm_win_rescale(Elm_Theme *th, Eina_Bool use_theme)
1135{
1136 const Eina_List *l;
1137 Evas_Object *obj;
1138
1139 if (!use_theme)
1140 {
1141 EINA_LIST_FOREACH(_elm_win_list, l, obj)
1142 elm_widget_theme(obj);
1143 }
1144 else
1145 {
1146 EINA_LIST_FOREACH(_elm_win_list, l, obj)
1147 elm_widget_theme_specific(obj, th, EINA_FALSE);
1148 }
1149}
1150
1151void
1152_elm_win_translate(void)
1153{
1154 const Eina_List *l;
1155 Evas_Object *obj;
1156
1157 EINA_LIST_FOREACH(_elm_win_list, l, obj)
1158 elm_widget_translate(obj);
1159}
1160
1161#ifdef HAVE_ELEMENTARY_X
1162static Eina_Bool
1163_elm_win_client_message(void *data, int type __UNUSED__, void *event)
1164{
1165 Elm_Win *win = data;
1166 Ecore_X_Event_Client_Message *e = event;
1167
1168 if (e->format != 32) return ECORE_CALLBACK_PASS_ON;
1169 if (e->message_type == ECORE_X_ATOM_E_COMP_FLUSH)
1170 {
1171 if ((unsigned)e->data.l[0] == win->xwin)
1172 {
1173 Evas *evas = evas_object_evas_get(win->win_obj);
1174 if (evas)
1175 {
1176 edje_file_cache_flush();
1177 edje_collection_cache_flush();
1178 evas_image_cache_flush(evas);
1179 evas_font_cache_flush(evas);
1180 }
1181 }
1182 }
1183 else if (e->message_type == ECORE_X_ATOM_E_COMP_DUMP)
1184 {
1185 if ((unsigned)e->data.l[0] == win->xwin)
1186 {
1187 Evas *evas = evas_object_evas_get(win->win_obj);
1188 if (evas)
1189 {
1190 edje_file_cache_flush();
1191 edje_collection_cache_flush();
1192 evas_image_cache_flush(evas);
1193 evas_font_cache_flush(evas);
1194 evas_render_dump(evas);
1195 }
1196 }
1197 }
1198 return ECORE_CALLBACK_PASS_ON;
1199}
1200#endif
1201
1202static void
1203_elm_win_focus_target_move(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1204{
1205 Elm_Win *win = data;
1206
1207 win->focus_highlight.geometry_changed = EINA_TRUE;
1208 _elm_win_focus_highlight_reconfigure_job_start(win);
1209}
1210
1211static void
1212_elm_win_focus_target_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1213{
1214 Elm_Win *win = data;
1215
1216 win->focus_highlight.geometry_changed = EINA_TRUE;
1217 _elm_win_focus_highlight_reconfigure_job_start(win);
1218}
1219
1220static void
1221_elm_win_focus_target_del(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1222{
1223 Elm_Win *win = data;
1224
1225 win->focus_highlight.cur.target = NULL;
1226
1227 _elm_win_focus_highlight_reconfigure_job_start(win);
1228}
1229
1230static void
1231_elm_win_focus_target_callbacks_add(Elm_Win *win)
1232{
1233 Evas_Object *obj = win->focus_highlight.cur.target;
1234
1235 evas_object_event_callback_add(obj, EVAS_CALLBACK_MOVE,
1236 _elm_win_focus_target_move, win);
1237 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE,
1238 _elm_win_focus_target_resize, win);
1239 evas_object_event_callback_add(obj, EVAS_CALLBACK_DEL,
1240 _elm_win_focus_target_del, win);
1241}
1242
1243static void
1244_elm_win_focus_target_callbacks_del(Elm_Win *win)
1245{
1246 Evas_Object *obj = win->focus_highlight.cur.target;
1247
1248 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_MOVE,
1249 _elm_win_focus_target_move, win);
1250 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_RESIZE,
1251 _elm_win_focus_target_resize, win);
1252 evas_object_event_callback_del_full(obj, EVAS_CALLBACK_DEL,
1253 _elm_win_focus_target_del, win);
1254}
1255
1256static Evas_Object *
1257_elm_win_focus_target_get(Evas_Object *obj)
1258{
1259 Evas_Object *o = obj;
1260
1261 do
1262 {
1263 if (elm_widget_is(o))
1264 {
1265 if (!elm_widget_highlight_ignore_get(o))
1266 break;
1267 o = elm_widget_parent_get(o);
1268 if (!o)
1269 o = evas_object_smart_parent_get(o);
1270 }
1271 else
1272 {
1273 o = elm_widget_parent_widget_get(o);
1274 if (!o)
1275 o = evas_object_smart_parent_get(o);
1276 }
1277 }
1278 while (o);
1279
1280 return o;
1281}
1282
1283static void
1284_elm_win_object_focus_in(void *data, Evas *e __UNUSED__, void *event_info)
1285{
1286 Evas_Object *obj = event_info, *target;
1287 Elm_Win *win = data;
1288
1289 if (win->focus_highlight.cur.target == obj)
1290 return;
1291
1292 target = _elm_win_focus_target_get(obj);
1293 win->focus_highlight.cur.target = target;
1294 if (elm_widget_highlight_in_theme_get(target))
1295 win->focus_highlight.cur.handled = EINA_TRUE;
1296 else
1297 _elm_win_focus_target_callbacks_add(win);
1298
1299 _elm_win_focus_highlight_reconfigure_job_start(win);
1300}
1301
1302static void
1303_elm_win_object_focus_out(void *data, Evas *e __UNUSED__, void *event_info __UNUSED__)
1304{
1305 Elm_Win *win = data;
1306
1307 if (!win->focus_highlight.cur.target)
1308 return;
1309
1310 if (!win->focus_highlight.cur.handled)
1311 _elm_win_focus_target_callbacks_del(win);
1312 win->focus_highlight.cur.target = NULL;
1313 win->focus_highlight.cur.handled = EINA_FALSE;
1314
1315 _elm_win_focus_highlight_reconfigure_job_start(win);
1316}
1317
1318static void
1319_elm_win_focus_highlight_hide(void *data __UNUSED__, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
1320{
1321 evas_object_hide(obj);
1322}
1323
1324static void
1325_elm_win_focus_highlight_init(Elm_Win *win)
1326{
1327 evas_event_callback_add(win->evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
1328 _elm_win_object_focus_in, win);
1329 evas_event_callback_add(win->evas,
1330 EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
1331 _elm_win_object_focus_out, win);
1332
1333 win->focus_highlight.cur.target = evas_focus_get(win->evas);
1334
1335 win->focus_highlight.top = edje_object_add(win->evas);
1336 win->focus_highlight.changed_theme = EINA_TRUE;
1337 edje_object_signal_callback_add(win->focus_highlight.top,
1338 "elm,action,focus,hide,end", "",
1339 _elm_win_focus_highlight_hide, NULL);
1340 edje_object_signal_callback_add(win->focus_highlight.top,
1341 "elm,action,focus,anim,end", "",
1342 _elm_win_focus_highlight_anim_end, win);
1343 _elm_win_focus_highlight_reconfigure_job_start(win);
1344}
1345
1346static void
1347_elm_win_focus_highlight_shutdown(Elm_Win *win)
1348{
1349 _elm_win_focus_highlight_reconfigure_job_stop(win);
1350 if (win->focus_highlight.cur.target)
1351 {
1352 _elm_win_focus_target_callbacks_del(win);
1353 win->focus_highlight.cur.target = NULL;
1354 }
1355 if (win->focus_highlight.top)
1356 {
1357 evas_object_del(win->focus_highlight.top);
1358 win->focus_highlight.top = NULL;
1359 }
1360
1361 evas_event_callback_del_full(win->evas,
1362 EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
1363 _elm_win_object_focus_in, win);
1364 evas_event_callback_del_full(win->evas,
1365 EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT,
1366 _elm_win_object_focus_out, win);
1367}
1368
1369static void
1370_elm_win_focus_highlight_visible_set(Elm_Win *win, Eina_Bool visible)
1371{
1372 Evas_Object *top;
1373
1374 top = win->focus_highlight.top;
1375 if (visible)
1376 {
1377 if (top)
1378 {
1379 evas_object_show(top);
1380 edje_object_signal_emit(top, "elm,action,focus,show", "elm");
1381 }
1382 }
1383 else
1384 {
1385 if (top)
1386 edje_object_signal_emit(top, "elm,action,focus,hide", "elm");
1387 }
1388}
1389
1390static void
1391_elm_win_focus_highlight_reconfigure_job(void *data)
1392{
1393 _elm_win_focus_highlight_reconfigure((Elm_Win *)data);
1394}
1395
1396static void
1397_elm_win_focus_highlight_reconfigure_job_start(Elm_Win *win)
1398{
1399 if (win->focus_highlight.reconf_job)
1400 ecore_job_del(win->focus_highlight.reconf_job);
1401 win->focus_highlight.reconf_job = ecore_job_add(
1402 _elm_win_focus_highlight_reconfigure_job, win);
1403}
1404
1405static void
1406_elm_win_focus_highlight_reconfigure_job_stop(Elm_Win *win)
1407{
1408 if (win->focus_highlight.reconf_job)
1409 ecore_job_del(win->focus_highlight.reconf_job);
1410 win->focus_highlight.reconf_job = NULL;
1411}
1412
1413static void
1414_elm_win_focus_highlight_simple_setup(Elm_Win *win, Evas_Object *obj)
1415{
1416 Evas_Object *clip, *target = win->focus_highlight.cur.target;
1417 Evas_Coord x, y, w, h;
1418
1419 clip = evas_object_clip_get(target);
1420 evas_object_geometry_get(target, &x, &y, &w, &h);
1421
1422 evas_object_move(obj, x, y);
1423 evas_object_resize(obj, w, h);
1424 evas_object_clip_set(obj, clip);
1425}
1426
1427static void
1428_elm_win_focus_highlight_anim_setup(Elm_Win *win, Evas_Object *obj)
1429{
1430 Evas_Coord tx, ty, tw, th;
1431 Evas_Coord w, h, px, py, pw, ph;
1432 Edje_Message_Int_Set *m;
1433 Evas_Object *previous = win->focus_highlight.prev.target;
1434 Evas_Object *target = win->focus_highlight.cur.target;
1435
1436 evas_object_geometry_get(win->win_obj, NULL, NULL, &w, &h);
1437 evas_object_geometry_get(target, &tx, &ty, &tw, &th);
1438 evas_object_geometry_get(previous, &px, &py, &pw, &ph);
1439 evas_object_move(obj, 0, 0);
1440 evas_object_resize(obj, tw, th);
1441 evas_object_clip_unset(obj);
1442
1443 m = alloca(sizeof(*m) + (sizeof(int) * 8));
1444 m->count = 8;
1445 m->val[0] = px;
1446 m->val[1] = py;
1447 m->val[2] = pw;
1448 m->val[3] = ph;
1449 m->val[4] = tx;
1450 m->val[5] = ty;
1451 m->val[6] = tw;
1452 m->val[7] = th;
1453 edje_object_message_send(obj, EDJE_MESSAGE_INT_SET, 1, m);
1454}
1455
1456static void
1457_elm_win_focus_highlight_anim_end(void *data, Evas_Object *obj, const char *emission __UNUSED__, const char *source __UNUSED__)
1458{
1459 Elm_Win *win = data;
1460 _elm_win_focus_highlight_simple_setup(win, obj);
1461}
1462
1463static void
1464_elm_win_focus_highlight_reconfigure(Elm_Win *win)
1465{
1466 Evas_Object *target = win->focus_highlight.cur.target;
1467 Evas_Object *previous = win->focus_highlight.prev.target;
1468 Evas_Object *top = win->focus_highlight.top;
1469 Eina_Bool visible_changed;
1470 Eina_Bool common_visible;
1471 const char *sig = NULL;
1472
1473 _elm_win_focus_highlight_reconfigure_job_stop(win);
1474
1475 visible_changed = (win->focus_highlight.cur.visible !=
1476 win->focus_highlight.prev.visible);
1477
1478 if ((target == previous) && (!visible_changed) &&
1479 (!win->focus_highlight.geometry_changed))
1480 return;
1481
1482 if ((previous) && (win->focus_highlight.prev.handled))
1483 elm_widget_signal_emit(previous, "elm,action,focus_highlight,hide", "elm");
1484
1485 if (!target)
1486 common_visible = EINA_FALSE;
1487 else if (win->focus_highlight.cur.handled)
1488 {
1489 common_visible = EINA_FALSE;
1490 if (win->focus_highlight.cur.visible)
1491 sig = "elm,action,focus_highlight,show";
1492 else
1493 sig = "elm,action,focus_highlight,hide";
1494 }
1495 else
1496 common_visible = win->focus_highlight.cur.visible;
1497
1498 _elm_win_focus_highlight_visible_set(win, common_visible);
1499 if (sig)
1500 elm_widget_signal_emit(target, sig, "elm");
1501
1502 if ((!target) || (!common_visible) || (win->focus_highlight.cur.handled))
1503 goto the_end;
1504
1505 if (win->focus_highlight.changed_theme)
1506 {
1507 const char *str;
1508 if (win->focus_highlight.style)
1509 str = win->focus_highlight.style;
1510 else
1511 str = "default";
1512 _elm_theme_object_set(win->win_obj, top, "focus_highlight", "top",
1513 str);
1514 win->focus_highlight.changed_theme = EINA_FALSE;
1515
1516 if (_elm_config->focus_highlight_animate)
1517 {
1518 str = edje_object_data_get(win->focus_highlight.top, "animate");
1519 win->focus_highlight.top_animate = ((str) && (!strcmp(str, "on")));
1520 }
1521 }
1522
1523 if ((win->focus_highlight.top_animate) && (previous) &&
1524 (!win->focus_highlight.prev.handled))
1525 _elm_win_focus_highlight_anim_setup(win, top);
1526 else
1527 _elm_win_focus_highlight_simple_setup(win, top);
1528 evas_object_raise(top);
1529
1530the_end:
1531 win->focus_highlight.geometry_changed = EINA_FALSE;
1532 win->focus_highlight.prev = win->focus_highlight.cur;
1533}
1534
1535static void
1536_elm_win_frame_add(Elm_Win *win, const char *style)
1537{
1538 evas_output_framespace_set(win->evas, 0, 22, 0, 26);
1539
1540 win->frame_obj = edje_object_add(win->evas);
1541 _elm_theme_set(NULL, win->frame_obj, "border", "base", style);
1542 evas_object_is_frame_object_set(win->frame_obj, EINA_TRUE);
1543 evas_object_move(win->frame_obj, 0, 0);
1544 evas_object_resize(win->frame_obj, 1, 1);
1545
1546 edje_object_signal_callback_add(win->frame_obj, "elm,action,move,start",
1547 "elm", _elm_win_frame_cb_move_start, win);
1548 edje_object_signal_callback_add(win->frame_obj, "elm,action,resize,start",
1549 "*", _elm_win_frame_cb_resize_start, win);
1550 edje_object_signal_callback_add(win->frame_obj, "elm,action,minimize",
1551 "elm", _elm_win_frame_cb_minimize, win);
1552 edje_object_signal_callback_add(win->frame_obj, "elm,action,maximize",
1553 "elm", _elm_win_frame_cb_maximize, win);
1554 edje_object_signal_callback_add(win->frame_obj, "elm,action,close",
1555 "elm", _elm_win_frame_cb_close, win);
1556}
1557
1558static void
1559_elm_win_frame_cb_move_start(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
1560{
1561 Elm_Win *win;
1562
1563 if (!(win = data)) return;
1564 /* FIXME: Change mouse pointer */
1565
1566 /* NB: 0,0 are dummy values. Wayland handles the move by itself */
1567 ecore_evas_move(win->ee, 0, 0);
1568}
1569
1570static void
1571_elm_win_frame_cb_resize_start(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source)
1572{
1573 Elm_Win *win;
1574
1575 if (!(win = data)) return;
1576 if (win->resizing) return;
1577 win->resizing = EINA_TRUE;
1578
1579 /* FIXME: Change mouse pointer */
1580
1581 if (!strcmp(source, "elm.event.resize.t"))
1582 win->resize_location = 1;
1583 else if (!strcmp(source, "elm.event.resize.b"))
1584 win->resize_location = 2;
1585 else if (!strcmp(source, "elm.event.resize.l"))
1586 win->resize_location = 4;
1587 else if (!strcmp(source, "elm.event.resize.r"))
1588 win->resize_location = 8;
1589 else if (!strcmp(source, "elm.event.resize.tl"))
1590 win->resize_location = 5;
1591 else if (!strcmp(source, "elm.event.resize.tr"))
1592 win->resize_location = 9;
1593 else if (!strcmp(source, "elm.event.resize.bl"))
1594 win->resize_location = 6;
1595 else if (!strcmp(source, "elm.event.resize.br"))
1596 win->resize_location = 10;
1597 else
1598 win->resize_location = 0;
1599
1600 if (win->resize_location > 0)
1601 ecore_evas_wayland_resize(win->ee, win->resize_location);
1602}
1603
1604static void
1605_elm_win_frame_cb_minimize(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
1606{
1607 Elm_Win *win;
1608
1609 if (!(win = data)) return;
1610 win->iconified = EINA_TRUE;
1611 ecore_evas_iconified_set(win->ee, EINA_TRUE);
1612}
1613
1614static void
1615_elm_win_frame_cb_maximize(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
1616{
1617 Elm_Win *win;
1618
1619 if (!(win = data)) return;
1620 if (win->maximized) win->maximized = EINA_FALSE;
1621 else win->maximized = EINA_TRUE;
1622 ecore_evas_maximized_set(win->ee, win->maximized);
1623}
1624
1625static void
1626_elm_win_frame_cb_close(void *data, Evas_Object *obj __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
1627{
1628 Elm_Win *win;
1629
1630 if (!(win = data)) return;
1631 evas_object_del(win->win_obj);
1632}
1633
1634/*
1635static void
1636_elm_win_pointer_add(Elm_Win *win, const char *style)
1637{
1638 int mw, mh;
1639
1640 return;
1641
1642 win->pointer.ee = ecore_evas_wayland_shm_new(NULL, 0, 0, 0, 32, 32, 0);
1643 ecore_evas_resize(win->pointer.ee, 32, 32);
1644
1645 win->pointer.evas = ecore_evas_get(win->ee);
1646
1647 win->pointer.obj = edje_object_add(win->pointer.evas);
1648 _elm_theme_set(NULL, win->pointer.obj, "pointer", "base", style);
1649 edje_object_size_min_calc(win->pointer.obj, &mw, &mh);
1650 evas_object_move(win->pointer.obj, 0, 0);
1651 evas_object_resize(win->pointer.obj, 32, 32);
1652 evas_object_show(win->pointer.obj);
1653}
1654*/
1655
1656#ifdef ELM_DEBUG
1657static void
1658_debug_key_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info)
1659{
1660 Evas_Event_Key_Down *ev = event_info;
1661
1662 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
1663 return;
1664
1665 if ((strcmp(ev->keyname, "F12")) ||
1666 (!evas_key_modifier_is_set(ev->modifiers, "Control")))
1667 return;
1668
1669 printf("Tree graph generated.\n");
1670 elm_object_tree_dot_dump(obj, "./dump.dot");
1671}
1672#endif
1673
1674static void
1675_win_img_hide(void *data,
1676 Evas *e __UNUSED__,
1677 Evas_Object *obj __UNUSED__,
1678 void *event_info __UNUSED__)
1679{
1680 Elm_Win *win = data;
1681
1682 elm_widget_focus_hide_handle(win->win_obj);
1683}
1684
1685static void
1686_win_img_mouse_up(void *data,
1687 Evas *e __UNUSED__,
1688 Evas_Object *obj __UNUSED__,
1689 void *event_info)
1690{
1691 Elm_Win *win = data;
1692 Evas_Event_Mouse_Up *ev = event_info;
1693 if (!(ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD))
1694 elm_widget_focus_mouse_up_handle(win->win_obj);
1695}
1696
1697static void
1698_win_img_focus_in(void *data,
1699 Evas *e __UNUSED__,
1700 Evas_Object *obj __UNUSED__,
1701 void *event_info __UNUSED__)
1702{
1703 Elm_Win *win = data;
1704 elm_widget_focus_steal(win->win_obj);
1705}
1706
1707static void
1708_win_img_focus_out(void *data,
1709 Evas *e __UNUSED__,
1710 Evas_Object *obj __UNUSED__,
1711 void *event_info __UNUSED__)
1712{
1713 Elm_Win *win = data;
1714 elm_widget_focused_object_clear(win->win_obj);
1715}
1716
1717static void
1718_win_inlined_image_set(Elm_Win *win)
1719{
1720 evas_object_image_alpha_set(win->img_obj, EINA_FALSE);
1721 evas_object_image_filled_set(win->img_obj, EINA_TRUE);
1722 evas_object_event_callback_add(win->img_obj, EVAS_CALLBACK_DEL,
1723 _elm_win_obj_callback_img_obj_del, win);
1724
1725 evas_object_event_callback_add(win->img_obj, EVAS_CALLBACK_HIDE,
1726 _win_img_hide, win);
1727 evas_object_event_callback_add(win->img_obj, EVAS_CALLBACK_MOUSE_UP,
1728 _win_img_mouse_up, win);
1729 evas_object_event_callback_add(win->img_obj, EVAS_CALLBACK_FOCUS_IN,
1730 _win_img_focus_in, win);
1731 evas_object_event_callback_add(win->img_obj, EVAS_CALLBACK_FOCUS_OUT,
1732 _win_img_focus_out, win);
1733}
1734
1735static void
1736_subobj_del(Elm_Win *win, Evas_Object *obj, Evas_Object *subobj)
1737{
1738 evas_object_event_callback_del_full(subobj,
1739 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
1740 _elm_win_subobj_callback_changed_size_hints,
1741 obj);
1742 evas_object_event_callback_del_full(subobj, EVAS_CALLBACK_DEL,
1743 _elm_win_subobj_callback_del, obj);
1744 win->subobjs = eina_list_remove(win->subobjs, subobj);
1745 _elm_win_eval_subobjs(obj);
1746}
1747
1748static void
1749_elm_win_obj_icon_callback_del(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
1750{
1751 Elm_Win *win = data;
1752 if (win->icon == obj) win->icon = NULL;
1753}
1754
1755EAPI Evas_Object *
1756elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type)
1757{
1758 Elm_Win *win;
1759 const Eina_List *l;
1760 const char *fontpath;
1761
1762 win = ELM_NEW(Elm_Win);
1763
1764#define FALLBACK_TRY(engine) \
1765 if (!win->ee) \
1766 do { \
1767 CRITICAL(engine " engine creation failed. Trying default."); \
1768 win->ee = ecore_evas_new(NULL, 0, 0, 1, 1, NULL); \
1769 if (win->ee) \
1770 elm_config_preferred_engine_set(ecore_evas_engine_name_get(win->ee)); \
1771 } while (0)
1772#define ENGINE_COMPARE(name) (_elm_preferred_engine && !strcmp(_elm_preferred_engine, name))
1773
1774 win->kbdmode = ELM_WIN_KEYBOARD_UNKNOWN;
1775 win->indmode = ELM_WIN_INDICATOR_UNKNOWN;
1776
1777 switch (type)
1778 {
1779 case ELM_WIN_INLINED_IMAGE:
1780 if (!parent) break;
1781 {
1782 Evas *e = evas_object_evas_get(parent);
1783 Ecore_Evas *ee;
1784 if (!e) break;
1785 ee = ecore_evas_ecore_evas_get(e);
1786 if (!ee) break;
1787 win->img_obj = ecore_evas_object_image_new(ee);
1788 if (!win->img_obj) break;
1789 win->ee = ecore_evas_object_ecore_evas_get(win->img_obj);
1790 if (win->ee)
1791 {
1792 _win_inlined_image_set(win);
1793 break;
1794 }
1795 evas_object_del(win->img_obj);
1796 win->img_obj = NULL;
1797 }
1798 break;
1799
1800 case ELM_WIN_SOCKET_IMAGE:
1801 win->ee = ecore_evas_extn_socket_new(1, 1);
1802 break;
1803
1804 default:
1805 if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
1806 {
1807 win->ee = ecore_evas_software_x11_new(NULL, 0, 0, 0, 1, 1);
1808#ifdef HAVE_ELEMENTARY_X
1809 win->client_message_handler = ecore_event_handler_add
1810 (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
1811#endif
1812 FALLBACK_TRY("Sofware X11");
1813 }
1814 else if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
1815 {
1816 win->ee = ecore_evas_fb_new(NULL, 0, 1, 1);
1817 FALLBACK_TRY("Sofware FB");
1818 }
1819 else if (ENGINE_COMPARE(ELM_SOFTWARE_DIRECTFB))
1820 {
1821 win->ee = ecore_evas_directfb_new(NULL, 1, 0, 0, 1, 1);
1822 FALLBACK_TRY("Sofware DirectFB");
1823 }
1824 else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
1825 {
1826 win->ee = ecore_evas_software_x11_16_new(NULL, 0, 0, 0, 1, 1);
1827 FALLBACK_TRY("Sofware-16");
1828#ifdef HAVE_ELEMENTARY_X
1829 win->client_message_handler = ecore_event_handler_add
1830 (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
1831#endif
1832 }
1833 else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
1834 {
1835 win->ee = ecore_evas_software_x11_8_new(NULL, 0, 0, 0, 1, 1);
1836 FALLBACK_TRY("Sofware-8");
1837#ifdef HAVE_ELEMENTARY_X
1838 win->client_message_handler = ecore_event_handler_add
1839 (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
1840#endif
1841 }
1842/* killed
1843 else if (ENGINE_COMPARE(ELM_XRENDER_X11))
1844 {
1845 win->ee = ecore_evas_xrender_x11_new(NULL, 0, 0, 0, 1, 1);
1846 FALLBACK_TRY("XRender");
1847#ifdef HAVE_ELEMENTARY_X
1848 win->client_message_handler = ecore_event_handler_add
1849 (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
1850#endif
1851 }
1852 */
1853 else if (ENGINE_COMPARE(ELM_OPENGL_X11))
1854 {
1855 int opt[10];
1856 int opt_i = 0;
1857
1858 if (_elm_config->vsync)
1859 {
1860 opt[opt_i] = ECORE_EVAS_GL_X11_OPT_VSYNC;
1861 opt_i++;
1862 opt[opt_i] = 1;
1863 opt_i++;
1864 }
1865 if (opt_i > 0)
1866 win->ee = ecore_evas_gl_x11_options_new(NULL, 0, 0, 0, 1, 1, opt);
1867 else
1868 win->ee = ecore_evas_gl_x11_new(NULL, 0, 0, 0, 1, 1);
1869 FALLBACK_TRY("OpenGL");
1870#ifdef HAVE_ELEMENTARY_X
1871 win->client_message_handler = ecore_event_handler_add
1872 (ECORE_X_EVENT_CLIENT_MESSAGE, _elm_win_client_message, win);
1873#endif
1874 }
1875 else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
1876 {
1877 win->ee = ecore_evas_software_gdi_new(NULL, 0, 0, 1, 1);
1878 FALLBACK_TRY("Sofware Win32");
1879 }
1880 else if (ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
1881 {
1882 win->ee = ecore_evas_software_wince_gdi_new(NULL, 0, 0, 1, 1);
1883 FALLBACK_TRY("Sofware-16-WinCE");
1884 }
1885 else if (ENGINE_COMPARE(ELM_SOFTWARE_PSL1GHT))
1886 {
1887 win->ee = ecore_evas_psl1ght_new(NULL, 1, 1);
1888 FALLBACK_TRY("PSL1GHT");
1889 }
1890 else if (ENGINE_COMPARE(ELM_SOFTWARE_SDL))
1891 {
1892 win->ee = ecore_evas_sdl_new(NULL, 0, 0, 0, 0, 0, 1);
1893 FALLBACK_TRY("Sofware SDL");
1894 }
1895 else if (ENGINE_COMPARE(ELM_SOFTWARE_16_SDL))
1896 {
1897 win->ee = ecore_evas_sdl16_new(NULL, 0, 0, 0, 0, 0, 1);
1898 FALLBACK_TRY("Sofware-16-SDL");
1899 }
1900 else if (ENGINE_COMPARE(ELM_OPENGL_SDL))
1901 {
1902 win->ee = ecore_evas_gl_sdl_new(NULL, 1, 1, 0, 0);
1903 FALLBACK_TRY("OpenGL SDL");
1904 }
1905 else if (ENGINE_COMPARE(ELM_OPENGL_COCOA))
1906 {
1907 win->ee = ecore_evas_cocoa_new(NULL, 1, 1, 0, 0);
1908 FALLBACK_TRY("OpenGL Cocoa");
1909 }
1910 else if (ENGINE_COMPARE(ELM_BUFFER))
1911 {
1912 win->ee = ecore_evas_buffer_new(1, 1);
1913 }
1914 else if (ENGINE_COMPARE(ELM_EWS))
1915 {
1916 win->ee = ecore_evas_ews_new(0, 0, 1, 1);
1917 }
1918 else if (ENGINE_COMPARE(ELM_WAYLAND_SHM))
1919 {
1920 win->ee = ecore_evas_wayland_shm_new(NULL, 0, 0, 0, 1, 1, 0);
1921 win->evas = ecore_evas_get(win->ee);
1922
1923 _elm_win_frame_add(win, "default");
1924// _elm_win_pointer_add(win, "default");
1925 }
1926 else if (ENGINE_COMPARE(ELM_WAYLAND_EGL))
1927 {
1928 win->ee = ecore_evas_wayland_egl_new(NULL, 0, 0, 0, 1, 1, 0);
1929 win->evas = ecore_evas_get(win->ee);
1930
1931 _elm_win_frame_add(win, "default");
1932// _elm_win_pointer_add(win, "default");
1933 }
1934 else if (!strncmp(_elm_preferred_engine, "shot:", 5))
1935 {
1936 win->ee = ecore_evas_buffer_new(1, 1);
1937 ecore_evas_manual_render_set(win->ee, EINA_TRUE);
1938 win->shot.info = eina_stringshare_add(_elm_preferred_engine + 5);
1939 _shot_init(win);
1940 }
1941#undef FALLBACK_TRY
1942 break;
1943 }
1944
1945 if (!win->ee)
1946 {
1947 ERR("Cannot create window.");
1948 free(win);
1949 return NULL;
1950 }
1951#ifdef HAVE_ELEMENTARY_X
1952 _elm_win_xwindow_get(win);
1953#endif
1954 if ((_elm_config->bgpixmap) && (!_elm_config->compositing))
1955 ecore_evas_avoid_damage_set(win->ee, ECORE_EVAS_AVOID_DAMAGE_EXPOSE);
1956 // bg pixmap done by x - has other issues like can be redrawn by x before it
1957 // is filled/ready by app
1958 // ecore_evas_avoid_damage_set(win->ee, ECORE_EVAS_AVOID_DAMAGE_BUILT_IN);
1959
1960 win->type = type;
1961 win->parent = parent;
1962 if (win->parent)
1963 evas_object_event_callback_add(win->parent, EVAS_CALLBACK_DEL,
1964 _elm_win_obj_callback_parent_del, win);
1965
1966 win->evas = ecore_evas_get(win->ee);
1967 win->win_obj = elm_widget_add(win->evas);
1968 elm_widget_type_set(win->win_obj, "win");
1969 ELM_SET_WIDTYPE(widtype, "win");
1970 elm_widget_data_set(win->win_obj, win);
1971 elm_widget_event_hook_set(win->win_obj, _elm_win_event_cb);
1972 elm_widget_on_focus_hook_set(win->win_obj, _elm_win_on_focus_hook, NULL);
1973 elm_widget_can_focus_set(win->win_obj, EINA_TRUE);
1974 elm_widget_highlight_ignore_set(win->win_obj, EINA_TRUE);
1975 elm_widget_focus_next_hook_set(win->win_obj, _elm_win_focus_next_hook);
1976 evas_object_color_set(win->win_obj, 0, 0, 0, 0);
1977 evas_object_move(win->win_obj, 0, 0);
1978 evas_object_resize(win->win_obj, 1, 1);
1979 evas_object_layer_set(win->win_obj, 50);
1980 evas_object_pass_events_set(win->win_obj, EINA_TRUE);
1981
1982 if (win->frame_obj)
1983 {
1984 evas_object_clip_set(win->win_obj, win->frame_obj);
1985 evas_object_stack_below(win->frame_obj, win->win_obj);
1986 }
1987
1988 if (type == ELM_WIN_INLINED_IMAGE)
1989 elm_widget_parent2_set(win->win_obj, parent);
1990 ecore_evas_object_associate(win->ee, win->win_obj,
1991 ECORE_EVAS_OBJECT_ASSOCIATE_BASE |
1992 ECORE_EVAS_OBJECT_ASSOCIATE_STACK |
1993 ECORE_EVAS_OBJECT_ASSOCIATE_LAYER);
1994 evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_SHOW,
1995 _elm_win_obj_callback_show, win);
1996 evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_HIDE,
1997 _elm_win_obj_callback_hide, win);
1998 evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_DEL,
1999 _elm_win_obj_callback_del, win);
2000 evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_MOVE,
2001 _elm_win_obj_callback_move, win);
2002 evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_RESIZE,
2003 _elm_win_obj_callback_resize, win);
2004 if (win->img_obj)
2005 evas_object_intercept_move_callback_add(win->win_obj,
2006 _elm_win_obj_intercept_move, win);
2007 evas_object_intercept_show_callback_add(win->win_obj,
2008 _elm_win_obj_intercept_show, win);
2009
2010 evas_object_smart_callback_add(win->win_obj, "sub-object-del", (Evas_Smart_Cb)_subobj_del, win);
2011 ecore_evas_name_class_set(win->ee, name, _elm_appname);
2012 ecore_evas_callback_delete_request_set(win->ee, _elm_win_delete_request);
2013 ecore_evas_callback_resize_set(win->ee, _elm_win_resize);
2014 ecore_evas_callback_mouse_in_set(win->ee, _elm_win_mouse_in);
2015 ecore_evas_callback_focus_in_set(win->ee, _elm_win_focus_in);
2016 ecore_evas_callback_focus_out_set(win->ee, _elm_win_focus_out);
2017 ecore_evas_callback_move_set(win->ee, _elm_win_move);
2018 ecore_evas_callback_state_change_set(win->ee, _elm_win_state_change);
2019 evas_image_cache_set(win->evas, (_elm_config->image_cache * 1024));
2020 evas_font_cache_set(win->evas, (_elm_config->font_cache * 1024));
2021 EINA_LIST_FOREACH(_elm_config->font_dirs, l, fontpath)
2022 evas_font_path_append(win->evas, fontpath);
2023 if (!_elm_config->font_hinting)
2024 evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_NONE);
2025 else if (_elm_config->font_hinting == 1)
2026 evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_AUTO);
2027 else if (_elm_config->font_hinting == 2)
2028 evas_font_hinting_set(win->evas, EVAS_FONT_HINTING_BYTECODE);
2029
2030#ifdef HAVE_ELEMENTARY_X
2031 _elm_win_xwin_update(win);
2032#endif
2033
2034 _elm_win_list = eina_list_append(_elm_win_list, win->win_obj);
2035
2036 if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
2037 {
2038 ecore_evas_fullscreen_set(win->ee, 1);
2039 }
2040#undef ENGINE_COMPARE
2041
2042 if (_elm_config->focus_highlight_enable)
2043 elm_win_focus_highlight_enabled_set(win->win_obj, EINA_TRUE);
2044
2045#ifdef ELM_DEBUG
2046 Evas_Modifier_Mask mask = evas_key_modifier_mask_get(win->evas, "Control");
2047 evas_object_event_callback_add(win->win_obj, EVAS_CALLBACK_KEY_DOWN,
2048 _debug_key_down, win);
2049
2050 Eina_Bool ret = evas_object_key_grab(win->win_obj, "F12", mask, 0,
2051 EINA_TRUE);
2052 printf("Ctrl+F12 key combination exclusive for dot tree generation\n");
2053#endif
2054
2055 evas_object_smart_callbacks_descriptions_set(win->win_obj, _signals);
2056
2057 return win->win_obj;
2058}
2059
2060EAPI Evas_Object *
2061elm_win_util_standard_add(const char *name, const char *title)
2062{
2063 Evas_Object *win, *bg;
2064
2065 win = elm_win_add(NULL, name, ELM_WIN_BASIC);
2066 if (!win) return NULL;
2067 elm_win_title_set(win, title);
2068 bg = elm_bg_add(win);
2069 if (!bg)
2070 {
2071 evas_object_del(win);
2072 return NULL;
2073 }
2074 evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
2075 elm_win_resize_object_add(win, bg);
2076 evas_object_show(bg);
2077 return win;
2078}
2079
2080EAPI void
2081elm_win_resize_object_add(Evas_Object *obj, Evas_Object *subobj)
2082{
2083 Evas_Coord w, h;
2084 Elm_Win *win;
2085 ELM_CHECK_WIDTYPE(obj, widtype);
2086 win = elm_widget_data_get(obj);
2087 if (!win) return;
2088 if (eina_list_data_find(win->subobjs, subobj)) return;
2089 win->subobjs = eina_list_append(win->subobjs, subobj);
2090 elm_widget_sub_object_add(obj, subobj);
2091 evas_object_event_callback_add(subobj, EVAS_CALLBACK_DEL,
2092 _elm_win_subobj_callback_del, obj);
2093 evas_object_event_callback_add(subobj, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2094 _elm_win_subobj_callback_changed_size_hints,
2095 obj);
2096 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
2097 evas_object_move(subobj, 0, 0);
2098 evas_object_resize(subobj, w, h);
2099 _elm_win_eval_subobjs(obj);
2100}
2101
2102EAPI void
2103elm_win_resize_object_del(Evas_Object *obj, Evas_Object *subobj)
2104{
2105 Elm_Win *win;
2106 ELM_CHECK_WIDTYPE(obj, widtype);
2107 win = elm_widget_data_get(obj);
2108 if (!win) return;
2109 evas_object_event_callback_del_full(subobj,
2110 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
2111 _elm_win_subobj_callback_changed_size_hints,
2112 obj);
2113 evas_object_event_callback_del_full(subobj, EVAS_CALLBACK_DEL,
2114 _elm_win_subobj_callback_del, obj);
2115 win->subobjs = eina_list_remove(win->subobjs, subobj);
2116 elm_widget_sub_object_del(obj, subobj);
2117 _elm_win_eval_subobjs(obj);
2118}
2119
2120EAPI void
2121elm_win_title_set(Evas_Object *obj, const char *title)
2122{
2123 Elm_Win *win;
2124 ELM_CHECK_WIDTYPE(obj, widtype);
2125 win = elm_widget_data_get(obj);
2126 if (!win || !title) return;
2127 eina_stringshare_replace(&(win->title), title);
2128 ecore_evas_title_set(win->ee, win->title);
2129 if (win->frame_obj)
2130 edje_object_part_text_escaped_set(win->frame_obj, "elm.text.title", win->title);
2131}
2132
2133EAPI const char *
2134elm_win_title_get(const Evas_Object *obj)
2135{
2136 Elm_Win *win;
2137 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2138 win = elm_widget_data_get(obj);
2139 if (!win) return NULL;
2140 return win->title;
2141}
2142
2143EAPI void
2144elm_win_icon_name_set(Evas_Object *obj, const char *icon_name)
2145{
2146 Elm_Win *win;
2147 ELM_CHECK_WIDTYPE(obj, widtype);
2148 win = elm_widget_data_get(obj);
2149 if (!win || !icon_name) return;
2150 eina_stringshare_replace(&(win->icon_name), icon_name);
2151#ifdef HAVE_ELEMENTARY_X
2152 _elm_win_xwin_update(win);
2153#endif
2154}
2155
2156EAPI const char *
2157elm_win_icon_name_get(const Evas_Object *obj)
2158{
2159 Elm_Win *win;
2160 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2161 win = elm_widget_data_get(obj);
2162 if (!win) return NULL;
2163 return win->icon_name;
2164}
2165
2166EAPI void
2167elm_win_role_set(Evas_Object *obj, const char *role)
2168{
2169 Elm_Win *win;
2170 ELM_CHECK_WIDTYPE(obj, widtype);
2171 win = elm_widget_data_get(obj);
2172 if (!win || !role) return;
2173 eina_stringshare_replace(&(win->role), role);
2174#ifdef HAVE_ELEMENTARY_X
2175 _elm_win_xwin_update(win);
2176#endif
2177}
2178
2179EAPI const char *
2180elm_win_role_get(const Evas_Object *obj)
2181{
2182 Elm_Win *win;
2183 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2184 win = elm_widget_data_get(obj);
2185 if (!win) return NULL;
2186 return win->role;
2187}
2188
2189EAPI void
2190elm_win_icon_object_set(Evas_Object *obj, Evas_Object *icon)
2191{
2192 Elm_Win *win;
2193 ELM_CHECK_WIDTYPE(obj, widtype);
2194 win = elm_widget_data_get(obj);
2195 if (!win) return;
2196 if (win->icon)
2197 evas_object_event_callback_del_full(win->icon, EVAS_CALLBACK_DEL,
2198 _elm_win_obj_icon_callback_del, win);
2199 win->icon = icon;
2200 if (win->icon)
2201 evas_object_event_callback_add(win->icon, EVAS_CALLBACK_DEL,
2202 _elm_win_obj_icon_callback_del, win);
2203#ifdef HAVE_ELEMENTARY_X
2204 _elm_win_xwin_update(win);
2205#endif
2206}
2207
2208EAPI const Evas_Object *
2209elm_win_icon_object_get(const Evas_Object *obj)
2210{
2211 Elm_Win *win;
2212 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
2213 win = elm_widget_data_get(obj);
2214 if (!win) return NULL;
2215 return win->icon;
2216}
2217
2218EAPI void
2219elm_win_autodel_set(Evas_Object *obj, Eina_Bool autodel)
2220{
2221 Elm_Win *win;
2222 ELM_CHECK_WIDTYPE(obj, widtype);
2223 win = elm_widget_data_get(obj);
2224 if (!win) return;
2225 win->autodel = autodel;
2226}
2227
2228EAPI Eina_Bool
2229elm_win_autodel_get(const Evas_Object *obj)
2230{
2231 Elm_Win *win;
2232 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2233 win = elm_widget_data_get(obj);
2234 if (!win) return EINA_FALSE;
2235 return win->autodel;
2236}
2237
2238EAPI void
2239elm_win_activate(Evas_Object *obj)
2240{
2241 Elm_Win *win;
2242 ELM_CHECK_WIDTYPE(obj, widtype);
2243 win = elm_widget_data_get(obj);
2244 if (!win) return;
2245 ecore_evas_activate(win->ee);
2246}
2247
2248EAPI void
2249elm_win_lower(Evas_Object *obj)
2250{
2251 Elm_Win *win;
2252 ELM_CHECK_WIDTYPE(obj, widtype);
2253 win = elm_widget_data_get(obj);
2254 if (!win) return;
2255 ecore_evas_lower(win->ee);
2256}
2257
2258EAPI void
2259elm_win_raise(Evas_Object *obj)
2260{
2261 Elm_Win *win;
2262 ELM_CHECK_WIDTYPE(obj, widtype);
2263 win = elm_widget_data_get(obj);
2264 if (!win) return;
2265 ecore_evas_raise(win->ee);
2266}
2267
2268EAPI void
2269elm_win_center(Evas_Object *obj, Eina_Bool h, Eina_Bool v)
2270{
2271 Elm_Win *win;
2272 int win_w, win_h, screen_w, screen_h, nx, ny;
2273 ELM_CHECK_WIDTYPE(obj, widtype);
2274 win = elm_widget_data_get(obj);
2275 if (!win) return;
2276 ecore_evas_screen_geometry_get(win->ee, NULL, NULL, &screen_w, &screen_h);
2277 if ((!screen_w) || (!screen_h)) return;
2278 evas_object_geometry_get(obj, NULL, NULL, &win_w, &win_h);
2279 if ((!win_w) || (!win_h)) return;
2280 if (h) nx = win_w >= screen_w ? 0 : (screen_w / 2) - (win_w / 2);
2281 else nx = win->screen.x;
2282 if (v) ny = win_h >= screen_h ? 0 : (screen_h / 2) - (win_h / 2);
2283 else ny = win->screen.y;
2284 if (nx < 0) nx = 0;
2285 if (ny < 0) ny = 0;
2286 evas_object_move(obj, nx, ny);
2287}
2288
2289EAPI void
2290elm_win_borderless_set(Evas_Object *obj, Eina_Bool borderless)
2291{
2292 Elm_Win *win;
2293 ELM_CHECK_WIDTYPE(obj, widtype);
2294 win = elm_widget_data_get(obj);
2295 if (!win) return;
2296 ecore_evas_borderless_set(win->ee, borderless);
2297#ifdef HAVE_ELEMENTARY_X
2298 _elm_win_xwin_update(win);
2299#endif
2300}
2301
2302EAPI Eina_Bool
2303elm_win_borderless_get(const Evas_Object *obj)
2304{
2305 Elm_Win *win;
2306 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2307 win = elm_widget_data_get(obj);
2308 if (!win) return EINA_FALSE;
2309 return ecore_evas_borderless_get(win->ee);
2310}
2311
2312EAPI void
2313elm_win_shaped_set(Evas_Object *obj, Eina_Bool shaped)
2314{
2315 Elm_Win *win;
2316 ELM_CHECK_WIDTYPE(obj, widtype);
2317 win = elm_widget_data_get(obj);
2318 if (!win) return;
2319 ecore_evas_shaped_set(win->ee, shaped);
2320#ifdef HAVE_ELEMENTARY_X
2321 _elm_win_xwin_update(win);
2322#endif
2323}
2324
2325EAPI Eina_Bool
2326elm_win_shaped_get(const Evas_Object *obj)
2327{
2328 Elm_Win *win;
2329 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2330 win = elm_widget_data_get(obj);
2331 if (!win) return EINA_FALSE;
2332 return ecore_evas_shaped_get(win->ee);
2333}
2334
2335EAPI void
2336elm_win_alpha_set(Evas_Object *obj, Eina_Bool alpha)
2337{
2338 Elm_Win *win;
2339 ELM_CHECK_WIDTYPE(obj, widtype);
2340 win = elm_widget_data_get(obj);
2341 if (!win) return;
2342 if (win->frame_obj)
2343 {
2344 }
2345 else if (win->img_obj)
2346 {
2347 evas_object_image_alpha_set(win->img_obj, alpha);
2348 ecore_evas_alpha_set(win->ee, alpha);
2349 }
2350 else
2351 {
2352#ifdef HAVE_ELEMENTARY_X
2353 if (win->xwin)
2354 {
2355 if (alpha)
2356 {
2357 if (!_elm_config->compositing)
2358 elm_win_shaped_set(obj, alpha);
2359 else
2360 ecore_evas_alpha_set(win->ee, alpha);
2361 }
2362 else
2363 ecore_evas_alpha_set(win->ee, alpha);
2364 _elm_win_xwin_update(win);
2365 }
2366 else
2367#endif
2368 ecore_evas_alpha_set(win->ee, alpha);
2369 }
2370}
2371
2372EAPI Eina_Bool
2373elm_win_alpha_get(const Evas_Object *obj)
2374{
2375 Elm_Win *win;
2376 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2377 win = elm_widget_data_get(obj);
2378 if (!win) return EINA_FALSE;
2379 if (win->frame_obj)
2380 {
2381 }
2382 else if (win->img_obj)
2383 {
2384 return evas_object_image_alpha_get(win->img_obj);
2385 }
2386 return ecore_evas_alpha_get(win->ee);
2387}
2388
2389EAPI void
2390elm_win_override_set(Evas_Object *obj, Eina_Bool override)
2391{
2392 Elm_Win *win;
2393 ELM_CHECK_WIDTYPE(obj, widtype);
2394 win = elm_widget_data_get(obj);
2395 if (!win) return;
2396 ecore_evas_override_set(win->ee, override);
2397#ifdef HAVE_ELEMENTARY_X
2398 _elm_win_xwin_update(win);
2399#endif
2400}
2401
2402EAPI Eina_Bool
2403elm_win_override_get(const Evas_Object *obj)
2404{
2405 Elm_Win *win;
2406 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2407 win = elm_widget_data_get(obj);
2408 if (!win) return EINA_FALSE;
2409 return ecore_evas_override_get(win->ee);
2410}
2411
2412EAPI void
2413elm_win_fullscreen_set(Evas_Object *obj, Eina_Bool fullscreen)
2414{
2415 Elm_Win *win;
2416 ELM_CHECK_WIDTYPE(obj, widtype);
2417 win = elm_widget_data_get(obj);
2418 if (!win) return;
2419 // YYY: handle if win->img_obj
2420#define ENGINE_COMPARE(name) (!strcmp(_elm_preferred_engine, name))
2421 if (ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
2422 ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
2423 {
2424 // these engines... can ONLY be fullscreen
2425 return;
2426 }
2427 else
2428 {
2429 win->fullscreen = fullscreen;
2430 ecore_evas_fullscreen_set(win->ee, fullscreen);
2431#ifdef HAVE_ELEMENTARY_X
2432 _elm_win_xwin_update(win);
2433#endif
2434 }
2435#undef ENGINE_COMPARE
2436}
2437
2438EAPI Eina_Bool
2439elm_win_fullscreen_get(const Evas_Object *obj)
2440{
2441 Elm_Win *win;
2442 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2443 win = elm_widget_data_get(obj);
2444 if (!win) return EINA_FALSE;
2445#define ENGINE_COMPARE(name) (!strcmp(_elm_preferred_engine, name))
2446 if (ENGINE_COMPARE(ELM_SOFTWARE_FB) ||
2447 ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
2448 {
2449 // these engines... can ONLY be fullscreen
2450 return EINA_TRUE;
2451 }
2452 else
2453 {
2454 return win->fullscreen;
2455 }
2456#undef ENGINE_COMPARE
2457}
2458
2459EAPI void
2460elm_win_maximized_set(Evas_Object *obj, Eina_Bool maximized)
2461{
2462 Elm_Win *win;
2463 ELM_CHECK_WIDTYPE(obj, widtype);
2464 win = elm_widget_data_get(obj);
2465 if (!win) return;
2466 win->maximized = maximized;
2467 // YYY: handle if win->img_obj
2468 ecore_evas_maximized_set(win->ee, maximized);
2469#ifdef HAVE_ELEMENTARY_X
2470 _elm_win_xwin_update(win);
2471#endif
2472}
2473
2474EAPI Eina_Bool
2475elm_win_maximized_get(const Evas_Object *obj)
2476{
2477 Elm_Win *win;
2478 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2479 win = elm_widget_data_get(obj);
2480 if (!win) return EINA_FALSE;
2481 return win->maximized;
2482}
2483
2484EAPI void
2485elm_win_iconified_set(Evas_Object *obj, Eina_Bool iconified)
2486{
2487 Elm_Win *win;
2488 ELM_CHECK_WIDTYPE(obj, widtype);
2489 win = elm_widget_data_get(obj);
2490 if (!win) return;
2491 win->iconified = iconified;
2492 ecore_evas_iconified_set(win->ee, iconified);
2493#ifdef HAVE_ELEMENTARY_X
2494 _elm_win_xwin_update(win);
2495#endif
2496}
2497
2498EAPI Eina_Bool
2499elm_win_iconified_get(const Evas_Object *obj)
2500{
2501 Elm_Win *win;
2502 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2503 win = elm_widget_data_get(obj);
2504 if (!win) return EINA_FALSE;
2505 return win->iconified;
2506}
2507
2508EAPI void
2509elm_win_withdrawn_set(Evas_Object *obj, Eina_Bool withdrawn)
2510{
2511 Elm_Win *win;
2512 ELM_CHECK_WIDTYPE(obj, widtype);
2513 win = elm_widget_data_get(obj);
2514 if (!win) return;
2515 win->withdrawn = withdrawn;
2516 ecore_evas_withdrawn_set(win->ee, withdrawn);
2517#ifdef HAVE_ELEMENTARY_X
2518 _elm_win_xwin_update(win);
2519#endif
2520}
2521
2522EAPI Eina_Bool
2523elm_win_withdrawn_get(const Evas_Object *obj)
2524{
2525 Elm_Win *win;
2526 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2527 win = elm_widget_data_get(obj);
2528 if (!win) return EINA_FALSE;
2529 return win->withdrawn;
2530}
2531
2532EAPI void
2533elm_win_urgent_set(Evas_Object *obj, Eina_Bool urgent)
2534{
2535 Elm_Win *win;
2536 ELM_CHECK_WIDTYPE(obj, widtype);
2537 win = elm_widget_data_get(obj);
2538 if (!win) return;
2539 win->urgent = urgent;
2540 ecore_evas_urgent_set(win->ee, urgent);
2541#ifdef HAVE_ELEMENTARY_X
2542 _elm_win_xwin_update(win);
2543#endif
2544}
2545
2546EAPI Eina_Bool
2547elm_win_urgent_get(const Evas_Object *obj)
2548{
2549 Elm_Win *win;
2550 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2551 win = elm_widget_data_get(obj);
2552 if (!win) return EINA_FALSE;
2553 return win->urgent;
2554}
2555
2556EAPI void
2557elm_win_demand_attention_set(Evas_Object *obj, Eina_Bool demand_attention)
2558{
2559 Elm_Win *win;
2560 ELM_CHECK_WIDTYPE(obj, widtype);
2561 win = elm_widget_data_get(obj);
2562 if (!win) return;
2563 win->demand_attention = demand_attention;
2564 ecore_evas_demand_attention_set(win->ee, demand_attention);
2565#ifdef HAVE_ELEMENTARY_X
2566 _elm_win_xwin_update(win);
2567#endif
2568}
2569
2570EAPI Eina_Bool
2571elm_win_demand_attention_get(const Evas_Object *obj)
2572{
2573 Elm_Win *win;
2574 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2575 win = elm_widget_data_get(obj);
2576 if (!win) return EINA_FALSE;
2577 return win->demand_attention;
2578}
2579
2580EAPI void
2581elm_win_modal_set(Evas_Object *obj, Eina_Bool modal)
2582{
2583 Elm_Win *win;
2584 ELM_CHECK_WIDTYPE(obj, widtype);
2585 win = elm_widget_data_get(obj);
2586 if (!win) return;
2587 win->modal = modal;
2588 ecore_evas_modal_set(win->ee, modal);
2589#ifdef HAVE_ELEMENTARY_X
2590 _elm_win_xwin_update(win);
2591#endif
2592}
2593
2594EAPI Eina_Bool
2595elm_win_modal_get(const Evas_Object *obj)
2596{
2597 Elm_Win *win;
2598 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2599 win = elm_widget_data_get(obj);
2600 if (!win) return EINA_FALSE;
2601 return win->modal;
2602}
2603
2604EAPI void
2605elm_win_aspect_set(Evas_Object *obj, double aspect)
2606{
2607 Elm_Win *win;
2608 ELM_CHECK_WIDTYPE(obj, widtype);
2609 win = elm_widget_data_get(obj);
2610 if (!win) return;
2611 win->aspect = aspect;
2612 ecore_evas_aspect_set(win->ee, aspect);
2613#ifdef HAVE_ELEMENTARY_X
2614 _elm_win_xwin_update(win);
2615#endif
2616}
2617
2618EAPI double
2619elm_win_aspect_get(const Evas_Object *obj)
2620{
2621 Elm_Win *win;
2622 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2623 win = elm_widget_data_get(obj);
2624 if (!win) return EINA_FALSE;
2625 return win->aspect;
2626}
2627
2628EAPI void
2629elm_win_layer_set(Evas_Object *obj, int layer)
2630{
2631 Elm_Win *win;
2632 ELM_CHECK_WIDTYPE(obj, widtype);
2633 win = elm_widget_data_get(obj);
2634 if (!win) return;
2635 ecore_evas_layer_set(win->ee, layer);
2636#ifdef HAVE_ELEMENTARY_X
2637 _elm_win_xwin_update(win);
2638#endif
2639}
2640
2641EAPI int
2642elm_win_layer_get(const Evas_Object *obj)
2643{
2644 Elm_Win *win;
2645 ELM_CHECK_WIDTYPE(obj, widtype) -1;
2646 win = elm_widget_data_get(obj);
2647 if (!win) return -1;
2648 return ecore_evas_layer_get(win->ee);
2649}
2650
2651EAPI void
2652elm_win_rotation_set(Evas_Object *obj, int rotation)
2653{
2654 Elm_Win *win;
2655 ELM_CHECK_WIDTYPE(obj, widtype);
2656 win = elm_widget_data_get(obj);
2657 if (!win) return;
2658 if (win->rot == rotation) return;
2659 win->rot = rotation;
2660 ecore_evas_rotation_set(win->ee, rotation);
2661 evas_object_size_hint_min_set(obj, -1, -1);
2662 evas_object_size_hint_max_set(obj, -1, -1);
2663 _elm_win_eval_subobjs(obj);
2664#ifdef HAVE_ELEMENTARY_X
2665 _elm_win_xwin_update(win);
2666#endif
2667}
2668
2669EAPI void
2670elm_win_rotation_with_resize_set(Evas_Object *obj, int rotation)
2671{
2672 Elm_Win *win;
2673 ELM_CHECK_WIDTYPE(obj, widtype);
2674 win = elm_widget_data_get(obj);
2675 if (!win) return;
2676 if (win->rot == rotation) return;
2677 win->rot = rotation;
2678 ecore_evas_rotation_with_resize_set(win->ee, rotation);
2679 evas_object_size_hint_min_set(obj, -1, -1);
2680 evas_object_size_hint_max_set(obj, -1, -1);
2681 _elm_win_eval_subobjs(obj);
2682#ifdef HAVE_ELEMENTARY_X
2683 _elm_win_xwin_update(win);
2684#endif
2685}
2686
2687EAPI int
2688elm_win_rotation_get(const Evas_Object *obj)
2689{
2690 Elm_Win *win;
2691 ELM_CHECK_WIDTYPE(obj, widtype) -1;
2692 win = elm_widget_data_get(obj);
2693 if (!win) return -1;
2694 return win->rot;
2695}
2696
2697EAPI void
2698elm_win_sticky_set(Evas_Object *obj, Eina_Bool sticky)
2699{
2700 Elm_Win *win;
2701 ELM_CHECK_WIDTYPE(obj, widtype);
2702 win = elm_widget_data_get(obj);
2703 if (!win) return;
2704 win->sticky = sticky;
2705 ecore_evas_sticky_set(win->ee, sticky);
2706#ifdef HAVE_ELEMENTARY_X
2707 _elm_win_xwin_update(win);
2708#endif
2709}
2710
2711EAPI Eina_Bool
2712elm_win_sticky_get(const Evas_Object *obj)
2713{
2714 Elm_Win *win;
2715 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2716 win = elm_widget_data_get(obj);
2717 if (!win) return EINA_FALSE;
2718 return win->sticky;
2719}
2720
2721EAPI void
2722elm_win_keyboard_mode_set(Evas_Object *obj, Elm_Win_Keyboard_Mode mode)
2723{
2724 Elm_Win *win;
2725 ELM_CHECK_WIDTYPE(obj, widtype);
2726 win = elm_widget_data_get(obj);
2727 if (!win) return;
2728 if (mode == win->kbdmode) return;
2729#ifdef HAVE_ELEMENTARY_X
2730 _elm_win_xwindow_get(win);
2731#endif
2732 win->kbdmode = mode;
2733#ifdef HAVE_ELEMENTARY_X
2734 if (win->xwin)
2735 ecore_x_e_virtual_keyboard_state_set
2736 (win->xwin, (Ecore_X_Virtual_Keyboard_State)win->kbdmode);
2737#endif
2738}
2739
2740EAPI Elm_Win_Keyboard_Mode
2741elm_win_keyboard_mode_get(const Evas_Object *obj)
2742{
2743 Elm_Win *win;
2744 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WIN_KEYBOARD_UNKNOWN;
2745 win = elm_widget_data_get(obj);
2746 if (!win) return ELM_WIN_KEYBOARD_UNKNOWN;
2747 return win->kbdmode;
2748}
2749
2750EAPI void
2751elm_win_keyboard_win_set(Evas_Object *obj, Eina_Bool is_keyboard)
2752{
2753 Elm_Win *win;
2754 ELM_CHECK_WIDTYPE(obj, widtype);
2755 win = elm_widget_data_get(obj);
2756 if (!win) return;
2757#ifdef HAVE_ELEMENTARY_X
2758 _elm_win_xwindow_get(win);
2759 if (win->xwin)
2760 ecore_x_e_virtual_keyboard_set(win->xwin, is_keyboard);
2761#else
2762 (void) is_keyboard;
2763#endif
2764}
2765
2766EAPI Eina_Bool
2767elm_win_keyboard_win_get(const Evas_Object *obj)
2768{
2769 Elm_Win *win;
2770 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2771 win = elm_widget_data_get(obj);
2772 if (!win) return EINA_FALSE;
2773#ifdef HAVE_ELEMENTARY_X
2774 _elm_win_xwindow_get(win);
2775 if (win->xwin)
2776 return ecore_x_e_virtual_keyboard_get(win->xwin);
2777#endif
2778 return EINA_FALSE;
2779}
2780
2781EAPI void
2782elm_win_indicator_mode_set(Evas_Object *obj, Elm_Win_Indicator_Mode mode)
2783{
2784 Elm_Win *win;
2785 ELM_CHECK_WIDTYPE(obj, widtype);
2786 win = elm_widget_data_get(obj);
2787 if (!win) return;
2788 if (mode == win->indmode) return;
2789#ifdef HAVE_ELEMENTARY_X
2790 _elm_win_xwindow_get(win);
2791#endif
2792 win->indmode = mode;
2793#ifdef HAVE_ELEMENTARY_X
2794 if (win->xwin)
2795 {
2796 if (win->indmode == ELM_WIN_INDICATOR_SHOW)
2797 ecore_x_e_illume_indicator_state_set
2798 (win->xwin, ECORE_X_ILLUME_INDICATOR_STATE_ON);
2799 else if (win->indmode == ELM_WIN_INDICATOR_HIDE)
2800 ecore_x_e_illume_indicator_state_set
2801 (win->xwin, ECORE_X_ILLUME_INDICATOR_STATE_OFF);
2802 }
2803#endif
2804}
2805
2806EAPI Elm_Win_Indicator_Mode
2807elm_win_indicator_mode_get(const Evas_Object *obj)
2808{
2809 Elm_Win *win;
2810 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WIN_INDICATOR_UNKNOWN;
2811 win = elm_widget_data_get(obj);
2812 if (!win) return ELM_WIN_INDICATOR_UNKNOWN;
2813 return win->indmode;
2814}
2815
2816EAPI void
2817elm_win_indicator_opacity_set(Evas_Object *obj, Elm_Win_Indicator_Opacity_Mode mode)
2818{
2819 Elm_Win *win;
2820 ELM_CHECK_WIDTYPE(obj, widtype);
2821 win = elm_widget_data_get(obj);
2822 if (!win) return;
2823 if (mode == win->ind_o_mode) return;
2824 win->ind_o_mode = mode;
2825#ifdef HAVE_ELEMENTARY_X
2826 _elm_win_xwindow_get(win);
2827 if (win->xwin)
2828 {
2829 if (win->ind_o_mode == ELM_WIN_INDICATOR_OPAQUE)
2830 ecore_x_e_illume_indicator_opacity_set
2831 (win->xwin, ECORE_X_ILLUME_INDICATOR_OPAQUE);
2832 else if (win->ind_o_mode == ELM_WIN_INDICATOR_TRANSLUCENT)
2833 ecore_x_e_illume_indicator_opacity_set
2834 (win->xwin, ECORE_X_ILLUME_INDICATOR_TRANSLUCENT);
2835 else if (win->ind_o_mode == ELM_WIN_INDICATOR_TRANSPARENT)
2836 ecore_x_e_illume_indicator_opacity_set
2837 (win->xwin, ECORE_X_ILLUME_INDICATOR_TRANSPARENT);
2838
2839 }
2840#endif
2841}
2842
2843EAPI Elm_Win_Indicator_Opacity_Mode
2844elm_win_indicator_opacity_get(const Evas_Object *obj)
2845{
2846 Elm_Win *win;
2847 ELM_CHECK_WIDTYPE(obj, widtype) ELM_WIN_INDICATOR_OPACITY_UNKNOWN;
2848 win = elm_widget_data_get(obj);
2849 if (!win) return ELM_WIN_INDICATOR_OPACITY_UNKNOWN;
2850 return win->ind_o_mode;
2851}
2852
2853EAPI void
2854elm_win_screen_position_get(const Evas_Object *obj, int *x, int *y)
2855{
2856 Elm_Win *win;
2857 ELM_CHECK_WIDTYPE(obj, widtype);
2858 win = elm_widget_data_get(obj);
2859 if (!win) return;
2860 if (x) *x = win->screen.x;
2861 if (y) *y = win->screen.y;
2862}
2863
2864EAPI Eina_Bool
2865elm_win_focus_get(const Evas_Object *obj)
2866{
2867 Elm_Win *win;
2868 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2869 win = elm_widget_data_get(obj);
2870 if (!win) return EINA_FALSE;
2871 return ecore_evas_focus_get(win->ee);
2872}
2873
2874EAPI void
2875elm_win_screen_constrain_set(Evas_Object *obj, Eina_Bool constrain)
2876{
2877 Elm_Win *win;
2878 ELM_CHECK_WIDTYPE(obj, widtype);
2879 win = elm_widget_data_get(obj);
2880 if (!win) return;
2881 win->constrain = !!constrain;
2882}
2883
2884EAPI Eina_Bool
2885elm_win_screen_constrain_get(Evas_Object *obj)
2886{
2887 Elm_Win *win;
2888 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2889 win = elm_widget_data_get(obj);
2890 if (!win) return EINA_FALSE;
2891 return win->constrain;
2892}
2893
2894EAPI void
2895elm_win_screen_size_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
2896{
2897 Elm_Win *win;
2898 ELM_CHECK_WIDTYPE(obj, widtype);
2899 win = elm_widget_data_get(obj);
2900 if (!win) return;
2901 ecore_evas_screen_geometry_get(win->ee, x, y, w, h);
2902}
2903
2904EAPI void
2905elm_win_conformant_set(Evas_Object *obj, Eina_Bool conformant)
2906{
2907 Elm_Win *win;
2908 ELM_CHECK_WIDTYPE(obj, widtype);
2909 win = elm_widget_data_get(obj);
2910 if (!win) return;
2911#ifdef HAVE_ELEMENTARY_X
2912 _elm_win_xwindow_get(win);
2913 if (win->xwin)
2914 ecore_x_e_illume_conformant_set(win->xwin, conformant);
2915#else
2916 (void) conformant;
2917#endif
2918}
2919
2920EAPI Eina_Bool
2921elm_win_conformant_get(const Evas_Object *obj)
2922{
2923 Elm_Win *win;
2924 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2925 win = elm_widget_data_get(obj);
2926 if (!win) return EINA_FALSE;
2927#ifdef HAVE_ELEMENTARY_X
2928 _elm_win_xwindow_get(win);
2929 if (win->xwin)
2930 return ecore_x_e_illume_conformant_get(win->xwin);
2931#endif
2932 return EINA_FALSE;
2933}
2934
2935EAPI void
2936elm_win_quickpanel_set(Evas_Object *obj, Eina_Bool quickpanel)
2937{
2938 Elm_Win *win;
2939 ELM_CHECK_WIDTYPE(obj, widtype);
2940 win = elm_widget_data_get(obj);
2941 if (!win) return;
2942#ifdef HAVE_ELEMENTARY_X
2943 _elm_win_xwindow_get(win);
2944 if (win->xwin)
2945 {
2946 ecore_x_e_illume_quickpanel_set(win->xwin, quickpanel);
2947 if (quickpanel)
2948 {
2949 Ecore_X_Window_State states[2];
2950
2951 states[0] = ECORE_X_WINDOW_STATE_SKIP_TASKBAR;
2952 states[1] = ECORE_X_WINDOW_STATE_SKIP_PAGER;
2953 ecore_x_netwm_window_state_set(win->xwin, states, 2);
2954 ecore_x_icccm_hints_set(win->xwin, 0, 0, 0, 0, 0, 0, 0);
2955 }
2956 }
2957#else
2958 (void) quickpanel;
2959#endif
2960}
2961
2962EAPI Eina_Bool
2963elm_win_quickpanel_get(const Evas_Object *obj)
2964{
2965 Elm_Win *win;
2966 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
2967 win = elm_widget_data_get(obj);
2968 if (!win) return EINA_FALSE;
2969#ifdef HAVE_ELEMENTARY_X
2970 _elm_win_xwindow_get(win);
2971 if (win->xwin)
2972 return ecore_x_e_illume_quickpanel_get(win->xwin);
2973#endif
2974 return EINA_FALSE;
2975}
2976
2977EAPI void
2978elm_win_quickpanel_priority_major_set(Evas_Object *obj, int priority)
2979{
2980 Elm_Win *win;
2981 ELM_CHECK_WIDTYPE(obj, widtype);
2982 win = elm_widget_data_get(obj);
2983 if (!win) return;
2984#ifdef HAVE_ELEMENTARY_X
2985 _elm_win_xwindow_get(win);
2986 if (win->xwin)
2987 ecore_x_e_illume_quickpanel_priority_major_set(win->xwin, priority);
2988#else
2989 (void) priority;
2990#endif
2991}
2992
2993EAPI int
2994elm_win_quickpanel_priority_major_get(const Evas_Object *obj)
2995{
2996 Elm_Win *win;
2997 ELM_CHECK_WIDTYPE(obj, widtype) -1;
2998 win = elm_widget_data_get(obj);
2999 if (!win) return -1;
3000#ifdef HAVE_ELEMENTARY_X
3001 _elm_win_xwindow_get(win);
3002 if (win->xwin)
3003 return ecore_x_e_illume_quickpanel_priority_major_get(win->xwin);
3004#endif
3005 return -1;
3006}
3007
3008EAPI void
3009elm_win_quickpanel_priority_minor_set(Evas_Object *obj, int priority)
3010{
3011 Elm_Win *win;
3012 ELM_CHECK_WIDTYPE(obj, widtype);
3013 win = elm_widget_data_get(obj);
3014 if (!win) return;
3015#ifdef HAVE_ELEMENTARY_X
3016 _elm_win_xwindow_get(win);
3017 if (win->xwin)
3018 ecore_x_e_illume_quickpanel_priority_minor_set(win->xwin, priority);
3019#else
3020 (void) priority;
3021#endif
3022}
3023
3024EAPI int
3025elm_win_quickpanel_priority_minor_get(const Evas_Object *obj)
3026{
3027 Elm_Win *win;
3028 ELM_CHECK_WIDTYPE(obj, widtype) -1;
3029 win = elm_widget_data_get(obj);
3030 if (!win) return -1;
3031#ifdef HAVE_ELEMENTARY_X
3032 _elm_win_xwindow_get(win);
3033 if (win->xwin)
3034 return ecore_x_e_illume_quickpanel_priority_minor_get(win->xwin);
3035#endif
3036 return -1;
3037}
3038
3039EAPI void
3040elm_win_quickpanel_zone_set(Evas_Object *obj, int zone)
3041{
3042 Elm_Win *win;
3043 ELM_CHECK_WIDTYPE(obj, widtype);
3044 win = elm_widget_data_get(obj);
3045 if (!win) return;
3046#ifdef HAVE_ELEMENTARY_X
3047 _elm_win_xwindow_get(win);
3048 if (win->xwin)
3049 ecore_x_e_illume_quickpanel_zone_set(win->xwin, zone);
3050#else
3051 (void) zone;
3052#endif
3053}
3054
3055EAPI int
3056elm_win_quickpanel_zone_get(const Evas_Object *obj)
3057{
3058 Elm_Win *win;
3059 ELM_CHECK_WIDTYPE(obj, widtype) 0;
3060 win = elm_widget_data_get(obj);
3061 if (!win) return 0;
3062#ifdef HAVE_ELEMENTARY_X
3063 _elm_win_xwindow_get(win);
3064 if (win->xwin)
3065 return ecore_x_e_illume_quickpanel_zone_get(win->xwin);
3066#endif
3067 return 0;
3068}
3069
3070EAPI void
3071elm_win_prop_focus_skip_set(Evas_Object *obj, Eina_Bool skip)
3072{
3073 Elm_Win *win;
3074 ELM_CHECK_WIDTYPE(obj, widtype);
3075 win = elm_widget_data_get(obj);
3076 if (!win) return;
3077 win->skip_focus = skip;
3078 ecore_evas_focus_skip_set(win->ee, skip);
3079}
3080
3081EAPI void
3082elm_win_illume_command_send(Evas_Object *obj, Elm_Illume_Command command, void *params __UNUSED__)
3083{
3084 Elm_Win *win;
3085 ELM_CHECK_WIDTYPE(obj, widtype);
3086 win = elm_widget_data_get(obj);
3087 if (!win) return;
3088#ifdef HAVE_ELEMENTARY_X
3089 _elm_win_xwindow_get(win);
3090 if (win->xwin)
3091 {
3092 switch (command)
3093 {
3094 case ELM_ILLUME_COMMAND_FOCUS_BACK:
3095 ecore_x_e_illume_focus_back_send(win->xwin);
3096 break;
3097 case ELM_ILLUME_COMMAND_FOCUS_FORWARD:
3098 ecore_x_e_illume_focus_forward_send(win->xwin);
3099 break;
3100 case ELM_ILLUME_COMMAND_FOCUS_HOME:
3101 ecore_x_e_illume_focus_home_send(win->xwin);
3102 break;
3103 case ELM_ILLUME_COMMAND_CLOSE:
3104 ecore_x_e_illume_close_send(win->xwin);
3105 break;
3106 default:
3107 break;
3108 }
3109 }
3110#else
3111 (void) command;
3112#endif
3113}
3114
3115EAPI Evas_Object *
3116elm_win_inlined_image_object_get(Evas_Object *obj)
3117{
3118 Elm_Win *win;
3119 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3120 win = elm_widget_data_get(obj);
3121 if (!win) return NULL;
3122 return win->img_obj;
3123}
3124
3125EAPI void
3126elm_win_focus_highlight_enabled_set(Evas_Object *obj, Eina_Bool enabled)
3127{
3128 Elm_Win *win;
3129
3130 ELM_CHECK_WIDTYPE(obj, widtype);
3131
3132 win = elm_widget_data_get(obj);
3133 enabled = !!enabled;
3134 if (win->focus_highlight.enabled == enabled)
3135 return;
3136
3137 win->focus_highlight.enabled = enabled;
3138
3139 if (win->focus_highlight.enabled)
3140 _elm_win_focus_highlight_init(win);
3141 else
3142 _elm_win_focus_highlight_shutdown(win);
3143}
3144
3145EAPI Eina_Bool
3146elm_win_focus_highlight_enabled_get(const Evas_Object *obj)
3147{
3148 Elm_Win *win;
3149
3150 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3151
3152 win = elm_widget_data_get(obj);
3153 return win->focus_highlight.enabled;
3154}
3155
3156EAPI void
3157elm_win_focus_highlight_style_set(Evas_Object *obj, const char *style)
3158{
3159 Elm_Win *win;
3160
3161 ELM_CHECK_WIDTYPE(obj, widtype);
3162
3163 win = elm_widget_data_get(obj);
3164 eina_stringshare_replace(&win->focus_highlight.style, style);
3165 win->focus_highlight.changed_theme = EINA_TRUE;
3166 _elm_win_focus_highlight_reconfigure_job_start(win);
3167}
3168
3169EAPI const char *
3170elm_win_focus_highlight_style_get(const Evas_Object *obj)
3171{
3172 Elm_Win *win;
3173
3174 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3175
3176 win = elm_widget_data_get(obj);
3177 return win->focus_highlight.style;
3178}
3179
3180typedef struct _Widget_Data Widget_Data;
3181
3182struct _Widget_Data
3183{
3184 Evas_Object *frm;
3185 Evas_Object *content;
3186};
3187
3188static void _del_hook(Evas_Object *obj);
3189static void _theme_hook(Evas_Object *obj);
3190static void _sizing_eval(Evas_Object *obj);
3191static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
3192static void _sub_del(void *data, Evas_Object *obj, void *event_info);
3193
3194static const char *widtype2 = NULL;
3195
3196static void
3197_del_hook(Evas_Object *obj)
3198{
3199 Widget_Data *wd = elm_widget_data_get(obj);
3200 if (!wd) return;
3201 free(wd);
3202}
3203
3204static void
3205_theme_hook(Evas_Object *obj)
3206{
3207 Widget_Data *wd = elm_widget_data_get(obj);
3208 _elm_theme_object_set(obj, wd->frm, "win", "inwin", elm_widget_style_get(obj));
3209 if (wd->content)
3210 edje_object_part_swallow(wd->frm, "elm.swallow.content", wd->content);
3211 _sizing_eval(obj);
3212
3213 evas_object_smart_callback_call(obj, SIG_THEME_CHANGED, NULL);
3214}
3215
3216static Eina_Bool
3217_elm_inwin_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
3218{
3219 Widget_Data *wd = elm_widget_data_get(obj);
3220
3221 if (!wd)
3222 return EINA_FALSE;
3223
3224 /* Try Focus cycle in subitem */
3225 if (wd->content)
3226 {
3227 elm_widget_focus_next_get(wd->content, dir, next);
3228 if (*next)
3229 return EINA_TRUE;
3230 }
3231
3232 *next = (Evas_Object *)obj;
3233 return EINA_FALSE;
3234}
3235
3236static void
3237_elm_inwin_text_set_hook(Evas_Object *obj, const char *item, const char *text)
3238{
3239 Widget_Data *wd = elm_widget_data_get(obj);
3240
3241 if (!wd || !item) return;
3242 edje_object_part_text_escaped_set(wd->frm, item, text);
3243 _sizing_eval(obj);
3244}
3245
3246static const char *
3247_elm_inwin_text_get_hook(const Evas_Object *obj, const char *item)
3248{
3249 Widget_Data *wd = elm_widget_data_get(obj);
3250
3251 if (!item || !wd || !wd->frm) return NULL;
3252 return edje_object_part_text_get(wd->frm, item);
3253}
3254
3255static void
3256_sizing_eval(Evas_Object *obj)
3257{
3258 Widget_Data *wd = elm_widget_data_get(obj);
3259 Evas_Coord minw = -1, minh = -1;
3260
3261 evas_object_size_hint_min_get(wd->content, &minw, &minh);
3262 edje_object_size_min_calc(wd->frm, &minw, &minh);
3263 evas_object_size_hint_min_set(obj, minw, minh);
3264 evas_object_size_hint_max_set(obj, -1, -1);
3265}
3266
3267static void
3268_changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
3269{
3270 _sizing_eval(data);
3271}
3272
3273static void
3274_sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info)
3275{
3276 Widget_Data *wd = elm_widget_data_get(obj);
3277 Evas_Object *sub = event_info;
3278 if (sub == wd->content)
3279 {
3280 evas_object_event_callback_del_full
3281 (sub, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
3282 wd->content = NULL;
3283 _sizing_eval(obj);
3284 }
3285}
3286
3287EAPI Evas_Object *
3288elm_win_inwin_add(Evas_Object *obj)
3289{
3290 Evas_Object *obj2;
3291 Widget_Data *wd;
3292 Elm_Win *win;
3293
3294 ELM_CHECK_WIDTYPE(obj, widtype) NULL;
3295 win = elm_widget_data_get(obj);
3296 if (!win) return NULL;
3297 wd = ELM_NEW(Widget_Data);
3298 obj2 = elm_widget_add(win->evas);
3299 elm_widget_type_set(obj2, "inwin");
3300 ELM_SET_WIDTYPE(widtype2, "inwin");
3301 elm_widget_sub_object_add(obj, obj2);
3302 evas_object_size_hint_weight_set(obj2, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3303 evas_object_size_hint_align_set(obj2, EVAS_HINT_FILL, EVAS_HINT_FILL);
3304 elm_win_resize_object_add(obj, obj2);
3305
3306 elm_widget_data_set(obj2, wd);
3307 elm_widget_del_hook_set(obj2, _del_hook);
3308 elm_widget_theme_hook_set(obj2, _theme_hook);
3309 elm_widget_focus_next_hook_set(obj2, _elm_inwin_focus_next_hook);
3310 elm_widget_text_set_hook_set(obj2, _elm_inwin_text_set_hook);
3311 elm_widget_text_get_hook_set(obj2, _elm_inwin_text_get_hook);
3312 elm_widget_can_focus_set(obj2, EINA_TRUE);
3313 elm_widget_highlight_ignore_set(obj2, EINA_TRUE);
3314
3315 wd->frm = edje_object_add(win->evas);
3316 _elm_theme_object_set(obj, wd->frm, "win", "inwin", "default");
3317 elm_widget_resize_object_set(obj2, wd->frm);
3318
3319 evas_object_smart_callback_add(obj2, "sub-object-del", _sub_del, obj2);
3320
3321 _sizing_eval(obj2);
3322 return obj2;
3323}
3324
3325EAPI void
3326elm_win_inwin_activate(Evas_Object *obj)
3327{
3328 ELM_CHECK_WIDTYPE(obj, widtype2);
3329 Widget_Data *wd = elm_widget_data_get(obj);
3330 if (!wd) return;
3331 evas_object_raise(obj);
3332 evas_object_show(obj);
3333 edje_object_signal_emit(wd->frm, "elm,action,show", "elm");
3334 elm_object_focus_set(obj, EINA_TRUE);
3335}
3336
3337EAPI void
3338elm_win_inwin_content_set(Evas_Object *obj, Evas_Object *content)
3339{
3340 ELM_CHECK_WIDTYPE(obj, widtype2);
3341 Widget_Data *wd = elm_widget_data_get(obj);
3342 if (!wd) return;
3343 if (wd->content == content) return;
3344 if (wd->content) evas_object_del(wd->content);
3345 wd->content = content;
3346 if (content)
3347 {
3348 elm_widget_sub_object_add(obj, content);
3349 evas_object_event_callback_add(content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
3350 _changed_size_hints, obj);
3351 edje_object_part_swallow(wd->frm, "elm.swallow.content", content);
3352 }
3353 _sizing_eval(obj);
3354}
3355
3356EAPI Evas_Object *
3357elm_win_inwin_content_get(const Evas_Object *obj)
3358{
3359 ELM_CHECK_WIDTYPE(obj, widtype2) NULL;
3360 Widget_Data *wd = elm_widget_data_get(obj);
3361 if (!wd) return NULL;
3362 return wd->content;
3363}
3364
3365EAPI Evas_Object *
3366elm_win_inwin_content_unset(Evas_Object *obj)
3367{
3368 ELM_CHECK_WIDTYPE(obj, widtype2) NULL;
3369 Widget_Data *wd = elm_widget_data_get(obj);
3370 if (!wd) return NULL;
3371 if (!wd->content) return NULL;
3372 Evas_Object *content = wd->content;
3373 elm_widget_sub_object_del(obj, wd->content);
3374 evas_object_event_callback_del_full(wd->content,
3375 EVAS_CALLBACK_CHANGED_SIZE_HINTS,
3376 _changed_size_hints, obj);
3377 edje_object_part_unswallow(wd->frm, wd->content);
3378 wd->content = NULL;
3379 return content;
3380}
3381
3382EAPI Eina_Bool
3383elm_win_socket_listen(Evas_Object *obj, const char *svcname, int svcnum, Eina_Bool svcsys)
3384{
3385
3386 Elm_Win *win;
3387
3388 ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
3389 win = elm_widget_data_get(obj);
3390 if (!win) return EINA_FALSE;
3391 if (!win->ee) return EINA_FALSE;
3392
3393 if (!ecore_evas_extn_socket_listen(win->ee, svcname, svcnum, svcsys))
3394 return EINA_FALSE;
3395
3396 return EINA_TRUE;
3397}
3398
3399/* windowing specific calls - shall we do this differently? */
3400
3401static Ecore_X_Window
3402_elm_ee_win_get(const Evas_Object *obj)
3403{
3404 if (!obj) return 0;
3405#ifdef HAVE_ELEMENTARY_X
3406 Ecore_Evas *ee = ecore_evas_ecore_evas_get(evas_object_evas_get(obj));
3407 if (ee) return (Ecore_X_Window)ecore_evas_window_get(ee);
3408#endif
3409 return 0;
3410}
3411
3412EAPI Ecore_X_Window
3413elm_win_xwindow_get(const Evas_Object *obj)
3414{
3415 Elm_Win *win;
3416 const char *type;
3417
3418 if (!obj) return 0;
3419 type = elm_widget_type_get(obj);
3420 if ((!type) || (type != widtype)) return _elm_ee_win_get(obj);
3421 win = elm_widget_data_get(obj);
3422 if (!win) return 0;
3423#ifdef HAVE_ELEMENTARY_X
3424 if (win->xwin) return win->xwin;
3425 if (win->parent) return elm_win_xwindow_get(win->parent);
3426#endif
3427 return 0;
3428}
diff --git a/libraries/elementary/src/lib/elm_win.h b/libraries/elementary/src/lib/elm_win.h
new file mode 100644
index 0000000..0cf2810
--- /dev/null
+++ b/libraries/elementary/src/lib/elm_win.h
@@ -0,0 +1,1371 @@
1/**
2 * @defgroup Win Win
3 * @ingroup Elementary
4 *
5 * @image html img/widget/win/preview-00.png
6 * @image latex img/widget/win/preview-00.eps
7 *
8 * The window class of Elementary. Contains functions to manipulate
9 * windows. The Evas engine used to render the window contents is specified
10 * in the system or user elementary config files (whichever is found last),
11 * and can be overridden with the ELM_ENGINE environment variable for
12 * testing. Engines that may be supported (depending on Evas and Ecore-Evas
13 * compilation setup and modules actually installed at runtime) are (listed
14 * in order of best supported and most likely to be complete and work to
15 * lowest quality).
16 *
17 * @li "x11", "x", "software-x11", "software_x11" (Software rendering in X11)
18 * @li "gl", "opengl", "opengl-x11", "opengl_x11" (OpenGL or OpenGL-ES2
19 * rendering in X11)
20 * @li "shot:..." (Virtual screenshot renderer - renders to output file and
21 * exits)
22 * @li "fb", "software-fb", "software_fb" (Linux framebuffer direct software
23 * rendering)
24 * @li "sdl", "software-sdl", "software_sdl" (SDL software rendering to SDL
25 * buffer)
26 * @li "gl-sdl", "gl_sdl", "opengl-sdl", "opengl_sdl" (OpenGL or OpenGL-ES2
27 * rendering using SDL as the buffer)
28 * @li "gdi", "software-gdi", "software_gdi" (Windows WIN32 rendering via
29 * GDI with software)
30 * @li "dfb", "directfb" (Rendering to a DirectFB window)
31 * @li "x11-8", "x8", "software-8-x11", "software_8_x11" (Rendering in
32 * grayscale using dedicated 8bit software engine in X11)
33 * @li "x11-16", "x16", "software-16-x11", "software_16_x11" (Rendering in
34 * X11 using 16bit software engine)
35 * @li "wince-gdi", "software-16-wince-gdi", "software_16_wince_gdi"
36 * (Windows CE rendering via GDI with 16bit software renderer)
37 * @li "sdl-16", "software-16-sdl", "software_16_sdl" (Rendering to SDL
38 * buffer with 16bit software renderer)
39 * @li "ews" (rendering to EWS - Ecore + Evas Single Process Windowing System)
40 * @li "gl-cocoa", "gl_cocoa", "opengl-cocoa", "opengl_cocoa" (OpenGL rendering in Cocoa)
41 * @li "psl1ght" (PS3 rendering using PSL1GHT)
42 *
43 * All engines use a simple string to select the engine to render, EXCEPT
44 * the "shot" engine. This actually encodes the output of the virtual
45 * screenshot and how long to delay in the engine string. The engine string
46 * is encoded in the following way:
47 *
48 * "shot:[delay=XX][:][repeat=DDD][:][file=XX]"
49 *
50 * Where options are separated by a ":" char if more than one option is
51 * given, with delay, if provided being the first option and file the last
52 * (order is important). The delay specifies how long to wait after the
53 * window is shown before doing the virtual "in memory" rendering and then
54 * save the output to the file specified by the file option (and then exit).
55 * If no delay is given, the default is 0.5 seconds. If no file is given the
56 * default output file is "out.png". Repeat option is for continuous
57 * capturing screenshots. Repeat range is from 1 to 999 and filename is
58 * fixed to "out001.png" Some examples of using the shot engine:
59 *
60 * ELM_ENGINE="shot:delay=1.0:repeat=5:file=elm_test.png" elementary_test
61 * ELM_ENGINE="shot:delay=1.0:file=elm_test.png" elementary_test
62 * ELM_ENGINE="shot:file=elm_test2.png" elementary_test
63 * ELM_ENGINE="shot:delay=2.0" elementary_test
64 * ELM_ENGINE="shot:" elementary_test
65 *
66 * Signals that you can add callbacks for are:
67 *
68 * @li "delete,request": the user requested to close the window. See
69 * elm_win_autodel_set().
70 * @li "focus,in": window got focus
71 * @li "focus,out": window lost focus
72 * @li "moved": window that holds the canvas was moved
73 * @li "withdrawn": window is still managed normally but removed from view
74 * @li "iconified": window is minimized (perhaps into an icon or taskbar)
75 * @li "normal": window is in a normal state (not withdrawn or iconified)
76 * @li "stick": window has become sticky (shows on all desktops)
77 * @li "unstick": window has stopped being sticky
78 * @li "fullscreen": window has become fullscreen
79 * @li "unfullscreen": window has stopped being fullscreen
80 * @li "maximized": window has been maximized
81 * @li "unmaximized": window has stopped being maximized
82 *
83 * Examples:
84 * @li @ref win_example_01
85 *
86 * @{
87 */
88/**
89 * Defines the types of window that can be created
90 *
91 * These are hints set on the window so that a running Window Manager knows
92 * how the window should be handled and/or what kind of decorations it
93 * should have.
94 *
95 * Currently, only the X11 backed engines use them.
96 */
97typedef enum
98{
99 ELM_WIN_BASIC, /**< A normal window. Indicates a normal, top-level
100 window. Almost every window will be created with this
101 type. */
102 ELM_WIN_DIALOG_BASIC, /**< Used for simple dialog windows/ */
103 ELM_WIN_DESKTOP, /**< For special desktop windows, like a background
104 window holding desktop icons. */
105 ELM_WIN_DOCK, /**< The window is used as a dock or panel. Usually would
106 be kept on top of any other window by the Window
107 Manager. */
108 ELM_WIN_TOOLBAR, /**< The window is used to hold a floating toolbar, or
109 similar. */
110 ELM_WIN_MENU, /**< Similar to #ELM_WIN_TOOLBAR. */
111 ELM_WIN_UTILITY, /**< A persistent utility window, like a toolbox or
112 palette. */
113 ELM_WIN_SPLASH, /**< Splash window for a starting up application. */
114 ELM_WIN_DROPDOWN_MENU, /**< The window is a dropdown menu, as when an
115 entry in a menubar is clicked. Typically used
116 with elm_win_override_set(). This hint exists
117 for completion only, as the EFL way of
118 implementing a menu would not normally use a
119 separate window for its contents. */
120 ELM_WIN_POPUP_MENU, /**< Like #ELM_WIN_DROPDOWN_MENU, but for the menu
121 triggered by right-clicking an object. */
122 ELM_WIN_TOOLTIP, /**< The window is a tooltip. A short piece of
123 explanatory text that typically appear after the
124 mouse cursor hovers over an object for a while.
125 Typically used with elm_win_override_set() and also
126 not very commonly used in the EFL. */
127 ELM_WIN_NOTIFICATION, /**< A notification window, like a warning about
128 battery life or a new E-Mail received. */
129 ELM_WIN_COMBO, /**< A window holding the contents of a combo box. Not
130 usually used in the EFL. */
131 ELM_WIN_DND, /**< Used to indicate the window is a representation of an
132 object being dragged across different windows, or even
133 applications. Typically used with
134 elm_win_override_set(). */
135 ELM_WIN_INLINED_IMAGE, /**< The window is rendered onto an image
136 buffer. No actual window is created for this
137 type, instead the window and all of its
138 contents will be rendered to an image buffer.
139 This allows to have children window inside a
140 parent one just like any other object would
141 be, and do other things like applying @c
142 Evas_Map effects to it. This is the only type
143 of window that requires the @c parent
144 parameter of elm_win_add() to be a valid @c
145 Evas_Object. */
146 ELM_WIN_SOCKET_IMAGE,/**< The window is rendered onto an image buffer
147 and can be shown other process's plug image object.
148 No actual window is created for this type,
149 instead the window and all of its contents will be
150 rendered to an image buffer and can be shown
151 other process's plug image object*/
152} Elm_Win_Type;
153
154/**
155 * The different layouts that can be requested for the virtual keyboard.
156 *
157 * When the application window is being managed by Illume, it may request
158 * any of the following layouts for the virtual keyboard.
159 */
160typedef enum
161{
162 ELM_WIN_KEYBOARD_UNKNOWN, /**< Unknown keyboard state */
163 ELM_WIN_KEYBOARD_OFF, /**< Request to deactivate the keyboard */
164 ELM_WIN_KEYBOARD_ON, /**< Enable keyboard with default layout */
165 ELM_WIN_KEYBOARD_ALPHA, /**< Alpha (a-z) keyboard layout */
166 ELM_WIN_KEYBOARD_NUMERIC, /**< Numeric keyboard layout */
167 ELM_WIN_KEYBOARD_PIN, /**< PIN keyboard layout */
168 ELM_WIN_KEYBOARD_PHONE_NUMBER, /**< Phone keyboard layout */
169 ELM_WIN_KEYBOARD_HEX, /**< Hexadecimal numeric keyboard layout */
170 ELM_WIN_KEYBOARD_TERMINAL, /**< Full (QWERTY) keyboard layout */
171 ELM_WIN_KEYBOARD_PASSWORD, /**< Password keyboard layout */
172 ELM_WIN_KEYBOARD_IP, /**< IP keyboard layout */
173 ELM_WIN_KEYBOARD_HOST, /**< Host keyboard layout */
174 ELM_WIN_KEYBOARD_FILE, /**< File keyboard layout */
175 ELM_WIN_KEYBOARD_URL, /**< URL keyboard layout */
176 ELM_WIN_KEYBOARD_KEYPAD, /**< Keypad layout */
177 ELM_WIN_KEYBOARD_J2ME /**< J2ME keyboard layout */
178} Elm_Win_Keyboard_Mode;
179
180/**
181 * In some environments, like phones, you may have an indicator that
182 * shows battery status, reception, time etc. This is the indicator.
183 *
184 * Sometimes you don't want it because you provide the same functionality
185 * inside your app, so this will request that the indicator is hidden in
186 * this circumstance if you use ELM_ILLUME_INDICATOR_HIDE. The default
187 * is to have the indicator shown.
188 */
189typedef enum
190{
191 ELM_WIN_INDICATOR_UNKNOWN, /**< Unknown indicator state */
192 ELM_WIN_INDICATOR_HIDE, /**< Hides the indicator */
193 ELM_WIN_INDICATOR_SHOW /**< Shows the indicator */
194} Elm_Win_Indicator_Mode;
195
196/**
197 * Defines the opacity modes of indicator that can be shown
198 */
199
200typedef enum
201{
202 ELM_WIN_INDICATOR_OPACITY_UNKNOWN, /**< Unknown indicator opacity mode */
203 ELM_WIN_INDICATOR_OPAQUE, /**< Opacifies the indicator */
204 ELM_WIN_INDICATOR_TRANSLUCENT, /**< Be translucent the indicator */
205 ELM_WIN_INDICATOR_TRANSPARENT /**< Transparentizes the indicator */
206} Elm_Win_Indicator_Opacity_Mode;
207
208/**
209 * Available commands that can be sent to the Illume manager.
210 *
211 * When running under an Illume session, a window may send commands to the
212 * Illume manager to perform different actions.
213 */
214typedef enum
215{
216 ELM_ILLUME_COMMAND_FOCUS_BACK, /**< Reverts focus to the previous window */
217 ELM_ILLUME_COMMAND_FOCUS_FORWARD, /**< Sends focus to the next window in the list */
218 ELM_ILLUME_COMMAND_FOCUS_HOME, /**< Hides all windows to show the Home screen */
219 ELM_ILLUME_COMMAND_CLOSE, /**< Closes the currently active window */
220} Elm_Illume_Command;
221
222/**
223 * Adds a window object. If this is the first window created, pass NULL as
224 * @p parent.
225 *
226 * @param parent Parent object to add the window to, or NULL
227 * @param name The name of the window
228 * @param type The window type, one of #Elm_Win_Type.
229 *
230 * The @p parent parameter can be @c NULL for every window @p type except
231 * #ELM_WIN_INLINED_IMAGE, which needs a parent to retrieve the canvas on
232 * which the image object will be created.
233 *
234 * @return The created object, or NULL on failure
235 *
236 * @ingroup Win
237 */
238EAPI Evas_Object *elm_win_add(Evas_Object *parent, const char *name, Elm_Win_Type type);
239
240/**
241 * Adds a window object with standard setup
242 *
243 * @param name The name of the window
244 * @param title The title for the window
245 *
246 * This creates a window like elm_win_add() but also puts in a standard
247 * background with elm_bg_add(), as well as setting the window title to
248 * @p title. The window type created is of type ELM_WIN_BASIC, with NULL
249 * as the parent widget.
250 *
251 * @return The created object, or NULL on failure
252 *
253 * @see elm_win_add()
254 *
255 * @ingroup Win
256 */
257EAPI Evas_Object *elm_win_util_standard_add(const char *name, const char *title);
258
259/**
260 * Add @p subobj as a resize object of window @p obj.
261 *
262 *
263 * Setting an object as a resize object of the window means that the
264 * @p subobj child's size and position will be controlled by the window
265 * directly. That is, the object will be resized to match the window size
266 * and should never be moved or resized manually by the developer.
267 *
268 * In addition, resize objects of the window control what the minimum size
269 * of it will be, as well as whether it can or not be resized by the user.
270 *
271 * For the end user to be able to resize a window by dragging the handles
272 * or borders provided by the Window Manager, or using any other similar
273 * mechanism, all of the resize objects in the window should have their
274 * evas_object_size_hint_weight_set() set to EVAS_HINT_EXPAND.
275 *
276 * Also notice that the window can get resized to the current size of the
277 * object if the EVAS_HINT_EXPAND is set @b after the call to
278 * elm_win_resize_object_add(). So if the object should get resized to the
279 * size of the window, set this hint @b before adding it as a resize object
280 * (this happens because the size of the window and the object are evaluated
281 * as soon as the object is added to the window).
282 *
283 * @param obj The window object
284 * @param subobj The resize object to add
285 *
286 * @ingroup Win
287 */
288EAPI void elm_win_resize_object_add(Evas_Object *obj, Evas_Object *subobj);
289
290/**
291 * Delete @p subobj as a resize object of window @p obj.
292 *
293 * This function removes the object @p subobj from the resize objects of
294 * the window @p obj. It will not delete the object itself, which will be
295 * left unmanaged and should be deleted by the developer, manually handled
296 * or set as child of some other container.
297 *
298 * @param obj The window object
299 * @param subobj The resize object to add
300 *
301 * @ingroup Win
302 */
303EAPI void elm_win_resize_object_del(Evas_Object *obj, Evas_Object *subobj);
304
305/**
306 * Set the title of the window
307 *
308 * @param obj The window object
309 * @param title The title to set
310 *
311 * @ingroup Win
312 */
313EAPI void elm_win_title_set(Evas_Object *obj, const char *title);
314
315/**
316 * Get the title of the window
317 *
318 * The returned string is an internal one and should not be freed or
319 * modified. It will also be rendered invalid if a new title is set or if
320 * the window is destroyed.
321 *
322 * @param obj The window object
323 * @return The title
324 *
325 * @ingroup Win
326 */
327EAPI const char *elm_win_title_get(const Evas_Object *obj);
328
329/**
330 * Set the icon name of the window
331 *
332 * @param obj The window object
333 * @param icon_name The icon name to set
334 *
335 * @ingroup Win
336 */
337EAPI void elm_win_icon_name_set(Evas_Object *obj, const char *icon_name);
338
339/**
340 * Get the icon name of the window
341 *
342 * The returned string is an internal one and should not be freed or
343 * modified. It will also be rendered invalid if a new icon name is set or if
344 * the window is destroyed.
345 *
346 * @param obj The window object
347 * @return The icon name
348 *
349 * @ingroup Win
350 */
351EAPI const char *elm_win_icon_name_get(const Evas_Object *obj);
352
353/**
354 * Set the role of the window
355 *
356 * @param obj The window object
357 * @param role The role to set
358 *
359 * @ingroup Win
360 */
361EAPI void elm_win_role_set(Evas_Object *obj, const char *role);
362
363/**
364 * Get the role of the window
365 *
366 * The returned string is an internal one and should not be freed or
367 * modified. It will also be rendered invalid if a new role is set or if
368 * the window is destroyed.
369 *
370 * @param obj The window object
371 * @return The role
372 *
373 * @ingroup Win
374 */
375EAPI const char *elm_win_role_get(const Evas_Object *obj);
376
377/**
378 * Set the object to represent the window icon
379 *
380 * This sets an object that will be used as the icon for the window. The exact
381 * pixel dimensions of the object (not object size) will be used, and the
382 * image pixels will be used as-is when this function is called. If the
383 * image object has been updated, then call this function again to source
384 * the image pixels and put them on the window's icon. This has limitations
385 * as only image objects allowed at this stage. This may be lifted in future.
386 *
387 * @param obj The window object
388 * @param icon The object to use for an icon
389 *
390 * @ingroup Win
391 */
392EAPI void elm_win_icon_object_set(Evas_Object *obj, Evas_Object *icon);
393
394/**
395 * Get the icon object used for the window
396 *
397 * The object returns is the one marked by elm_win_icon_object_set() as the
398 * object to use for the window icon.
399 *
400 * @param obj The window object
401 * @return The icon object set
402 *
403 * @ingroup Win
404 */
405EAPI const Evas_Object *elm_win_icon_object_get(const Evas_Object *obj);
406
407/**
408 * Set the window's autodel state.
409 *
410 * When closing the window in any way outside of the program control, like
411 * pressing the X button in the titlebar or using a command from the
412 * Window Manager, a "delete,request" signal is emitted to indicate that
413 * this event occurred and the developer can take any action, which may
414 * include, or not, destroying the window object.
415 *
416 * When the @p autodel parameter is set, the window will be automatically
417 * destroyed when this event occurs, after the signal is emitted.
418 * If @p autodel is @c EINA_FALSE, then the window will not be destroyed
419 * and is up to the program to do so when it's required.
420 *
421 * @param obj The window object
422 * @param autodel If true, the window will automatically delete itself when
423 * closed
424 *
425 * @ingroup Win
426 */
427EAPI void elm_win_autodel_set(Evas_Object *obj, Eina_Bool autodel);
428
429/**
430 * Get the window's autodel state.
431 *
432 * @param obj The window object
433 * @return If the window will automatically delete itself when closed
434 *
435 * @see elm_win_autodel_set()
436 *
437 * @ingroup Win
438 */
439EAPI Eina_Bool elm_win_autodel_get(const Evas_Object *obj);
440
441/**
442 * Activate a window object.
443 *
444 * This function sends a request to the Window Manager to activate the
445 * window pointed by @p obj. If honored by the WM, the window will receive
446 * the keyboard focus.
447 *
448 * @note This is just a request that a Window Manager may ignore, so calling
449 * this function does not ensure in any way that the window will be the
450 * active one after it.
451 *
452 * @param obj The window object
453 *
454 * @ingroup Win
455 */
456EAPI void elm_win_activate(Evas_Object *obj);
457
458/**
459 * Lower a window object.
460 *
461 * Places the window pointed by @p obj at the bottom of the stack, so that
462 * no other window is covered by it.
463 *
464 * If elm_win_override_set() is not set, the Window Manager may ignore this
465 * request.
466 *
467 * @param obj The window object
468 *
469 * @ingroup Win
470 */
471EAPI void elm_win_lower(Evas_Object *obj);
472
473/**
474 * Raise a window object.
475 *
476 * Places the window pointed by @p obj at the top of the stack, so that it's
477 * not covered by any other window.
478 *
479 * If elm_win_override_set() is not set, the Window Manager may ignore this
480 * request.
481 *
482 * @param obj The window object
483 *
484 * @ingroup Win
485 */
486EAPI void elm_win_raise(Evas_Object *obj);
487
488/**
489 * Center a window on its screen
490 *
491 * This function centers window @p obj horizontally and/or vertically based on the values
492 * of @p h and @p v.
493 * @param obj The window object
494 * @param h If true, center horizontally. If false, do not change horizontal location.
495 * @param v If true, center vertically. If false, do not change vertical location.
496 *
497 * @ingroup Win
498 */
499EAPI void elm_win_center(Evas_Object *obj, Eina_Bool h, Eina_Bool v);
500
501/**
502 * Set the borderless state of a window.
503 *
504 * This function requests the Window Manager to not draw any decoration
505 * around the window.
506 *
507 * @param obj The window object
508 * @param borderless If true, the window is borderless
509 *
510 * @ingroup Win
511 */
512EAPI void elm_win_borderless_set(Evas_Object *obj, Eina_Bool borderless);
513
514/**
515 * Get the borderless state of a window.
516 *
517 * @param obj The window object
518 * @return If true, the window is borderless
519 *
520 * @ingroup Win
521 */
522EAPI Eina_Bool elm_win_borderless_get(const Evas_Object *obj);
523
524/**
525 * Set the shaped state of a window.
526 *
527 * Shaped windows, when supported, will render the parts of the window that
528 * has no content, transparent.
529 *
530 * If @p shaped is EINA_FALSE, then it is strongly advised to have some
531 * background object or cover the entire window in any other way, or the
532 * parts of the canvas that have no data will show framebuffer artifacts.
533 *
534 * @param obj The window object
535 * @param shaped If true, the window is shaped
536 *
537 * @see elm_win_alpha_set()
538 *
539 * @ingroup Win
540 */
541EAPI void elm_win_shaped_set(Evas_Object *obj, Eina_Bool shaped);
542
543/**
544 * Get the shaped state of a window.
545 *
546 * @param obj The window object
547 * @return If true, the window is shaped
548 *
549 * @see elm_win_shaped_set()
550 *
551 * @ingroup Win
552 */
553EAPI Eina_Bool elm_win_shaped_get(const Evas_Object *obj);
554
555/**
556 * Set the alpha channel state of a window.
557 *
558 * If @p alpha is EINA_TRUE, the alpha channel of the canvas will be enabled
559 * possibly making parts of the window completely or partially transparent.
560 * This is also subject to the underlying system supporting it, like for
561 * example, running under a compositing manager. If no compositing is
562 * available, enabling this option will instead fallback to using shaped
563 * windows, with elm_win_shaped_set().
564 *
565 * @param obj The window object
566 * @param alpha If true, the window has an alpha channel
567 *
568 * @see elm_win_alpha_set()
569 *
570 * @ingroup Win
571 */
572EAPI void elm_win_alpha_set(Evas_Object *obj, Eina_Bool alpha);
573
574/**
575 * Get the alpha channel state of a window.
576 *
577 * @param obj The window object
578 * @return If true, the window has an alpha channel
579 *
580 * @ingroup Win
581 */
582EAPI Eina_Bool elm_win_alpha_get(const Evas_Object *obj);
583
584/**
585 * Set the override state of a window.
586 *
587 * A window with @p override set to EINA_TRUE will not be managed by the
588 * Window Manager. This means that no decorations of any kind will be shown
589 * for it, moving and resizing must be handled by the application, as well
590 * as the window visibility.
591 *
592 * This should not be used for normal windows, and even for not so normal
593 * ones, it should only be used when there's a good reason and with a lot
594 * of care. Mishandling override windows may result situations that
595 * disrupt the normal workflow of the end user.
596 *
597 * @param obj The window object
598 * @param override If true, the window is overridden
599 *
600 * @ingroup Win
601 */
602EAPI void elm_win_override_set(Evas_Object *obj, Eina_Bool override);
603
604/**
605 * Get the override state of a window.
606 *
607 * @param obj The window object
608 * @return If true, the window is overridden
609 *
610 * @see elm_win_override_set()
611 *
612 * @ingroup Win
613 */
614EAPI Eina_Bool elm_win_override_get(const Evas_Object *obj);
615
616/**
617 * Set the fullscreen state of a window.
618 *
619 * @param obj The window object
620 * @param fullscreen If true, the window is fullscreen
621 *
622 * @ingroup Win
623 */
624EAPI void elm_win_fullscreen_set(Evas_Object *obj, Eina_Bool fullscreen);
625
626/**
627 * Get the fullscreen state of a window.
628 *
629 * @param obj The window object
630 * @return If true, the window is fullscreen
631 *
632 * @ingroup Win
633 */
634EAPI Eina_Bool elm_win_fullscreen_get(const Evas_Object *obj);
635
636/**
637 * Set the maximized state of a window.
638 *
639 * @param obj The window object
640 * @param maximized If true, the window is maximized
641 *
642 * @ingroup Win
643 */
644EAPI void elm_win_maximized_set(Evas_Object *obj, Eina_Bool maximized);
645
646/**
647 * Get the maximized state of a window.
648 *
649 * @param obj The window object
650 * @return If true, the window is maximized
651 *
652 * @ingroup Win
653 */
654EAPI Eina_Bool elm_win_maximized_get(const Evas_Object *obj);
655
656/**
657 * Set the iconified state of a window.
658 *
659 * @param obj The window object
660 * @param iconified If true, the window is iconified
661 *
662 * @ingroup Win
663 */
664EAPI void elm_win_iconified_set(Evas_Object *obj, Eina_Bool iconified);
665
666/**
667 * Get the iconified state of a window.
668 *
669 * @param obj The window object
670 * @return If true, the window is iconified
671 *
672 * @ingroup Win
673 */
674EAPI Eina_Bool elm_win_iconified_get(const Evas_Object *obj);
675
676/**
677 * Set the withdrawn state of a window.
678 *
679 * @param obj The window object
680 * @param withdrawn If true, the window is withdrawn
681 *
682 * @ingroup Win
683 */
684EAPI void elm_win_withdrawn_set(Evas_Object *obj, Eina_Bool withdrawn);
685
686/**
687 * Get the withdrawn state of a window.
688 *
689 * @param obj The window object
690 * @return If true, the window is withdrawn
691 *
692 * @ingroup Win
693 */
694EAPI Eina_Bool elm_win_withdrawn_get(const Evas_Object *obj);
695
696/**
697 * Set the urgent state of a window.
698 *
699 * @param obj The window object
700 * @param urgent If true, the window is urgent
701 *
702 * @ingroup Win
703 */
704EAPI void elm_win_urgent_set(Evas_Object *obj, Eina_Bool urgent);
705
706/**
707 * Get the urgent state of a window.
708 *
709 * @param obj The window object
710 * @return If true, the window is urgent
711 *
712 * @ingroup Win
713 */
714EAPI Eina_Bool elm_win_urgent_get(const Evas_Object *obj);
715
716/**
717 * Set the demand_attention state of a window.
718 *
719 * @param obj The window object
720 * @param demand_attention If true, the window is demand_attention
721 *
722 * @ingroup Win
723 */
724EAPI void elm_win_demand_attention_set(Evas_Object *obj, Eina_Bool demand_attention);
725
726/**
727 * Get the demand_attention state of a window.
728 *
729 * @param obj The window object
730 * @return If true, the window is demand_attention
731 *
732 * @ingroup Win
733 */
734EAPI Eina_Bool elm_win_demand_attention_get(const Evas_Object *obj);
735
736/**
737 * Set the modal state of a window.
738 *
739 * @param obj The window object
740 * @param modal If true, the window is modal
741 *
742 * @ingroup Win
743 */
744EAPI void elm_win_modal_set(Evas_Object *obj, Eina_Bool modal);
745
746/**
747 * Get the modal state of a window.
748 *
749 * @param obj The window object
750 * @return If true, the window is modal
751 *
752 * @ingroup Win
753 */
754EAPI Eina_Bool elm_win_modal_get(const Evas_Object *obj);
755
756/**
757 * Set the aspect ratio of a window.
758 *
759 * @param obj The window object
760 * @param aspect If 0, the window has no aspect limits, otherwise it is
761 * width divided by height
762 *
763 * @ingroup Win
764 */
765EAPI void elm_win_aspect_set(Evas_Object *obj, double aspect);
766
767/**
768 * Get the aspect ratio of a window.
769 *
770 * @param obj The window object
771 * @return The aspect ratio set (0 by default)
772 *
773 * @ingroup Win
774 */
775EAPI double elm_win_aspect_get(const Evas_Object *obj);
776
777/**
778 * Set the layer of the window.
779 *
780 * What this means exactly will depend on the underlying engine used.
781 *
782 * In the case of X11 backed engines, the value in @p layer has the
783 * following meanings:
784 * @li < 3: The window will be placed below all others.
785 * @li > 5: The window will be placed above all others.
786 * @li other: The window will be placed in the default layer.
787 *
788 * @param obj The window object
789 * @param layer The layer of the window
790 *
791 * @ingroup Win
792 */
793EAPI void elm_win_layer_set(Evas_Object *obj, int layer);
794
795/**
796 * Get the layer of the window.
797 *
798 * @param obj The window object
799 * @return The layer of the window
800 *
801 * @see elm_win_layer_set()
802 *
803 * @ingroup Win
804 */
805EAPI int elm_win_layer_get(const Evas_Object *obj);
806
807/**
808 * Set the rotation of the window.
809 *
810 * Most engines only work with multiples of 90.
811 *
812 * This function is used to set the orientation of the window @p obj to
813 * match that of the screen. The window itself will be resized to adjust
814 * to the new geometry of its contents. If you want to keep the window size,
815 * see elm_win_rotation_with_resize_set().
816 *
817 * @param obj The window object
818 * @param rotation The rotation of the window, in degrees (0-360),
819 * counter-clockwise.
820 *
821 * @ingroup Win
822 */
823EAPI void elm_win_rotation_set(Evas_Object *obj, int rotation);
824
825/**
826 * Rotates the window and resizes it.
827 *
828 * Like elm_win_rotation_set(), but it also resizes the window's contents so
829 * that they fit inside the current window geometry.
830 *
831 * @param obj The window object
832 * @param rotation The rotation of the window in degrees (0-360),
833 * counter-clockwise.
834 *
835 * @ingroup Win
836 */
837EAPI void elm_win_rotation_with_resize_set(Evas_Object *obj, int rotation);
838
839/**
840 * Get the rotation of the window.
841 *
842 * @param obj The window object
843 * @return The rotation of the window in degrees (0-360)
844 *
845 * @see elm_win_rotation_set()
846 * @see elm_win_rotation_with_resize_set()
847 *
848 * @ingroup Win
849 */
850EAPI int elm_win_rotation_get(const Evas_Object *obj);
851
852/**
853 * Set the sticky state of the window.
854 *
855 * Hints the Window Manager that the window in @p obj should be left fixed
856 * at its position even when the virtual desktop it's on moves or changes.
857 *
858 * @param obj The window object
859 * @param sticky If true, the window's sticky state is enabled
860 *
861 * @ingroup Win
862 */
863EAPI void elm_win_sticky_set(Evas_Object *obj, Eina_Bool sticky);
864
865/**
866 * Get the sticky state of the window.
867 *
868 * @param obj The window object
869 * @return If true, the window's sticky state is enabled
870 *
871 * @see elm_win_sticky_set()
872 *
873 * @ingroup Win
874 */
875EAPI Eina_Bool elm_win_sticky_get(const Evas_Object *obj);
876
877/**
878 * Set if this window is an illume conformant window
879 *
880 * @param obj The window object
881 * @param conformant The conformant flag (1 = conformant, 0 = non-conformant)
882 *
883 * @ingroup Win
884 */
885EAPI void elm_win_conformant_set(Evas_Object *obj, Eina_Bool conformant);
886
887/**
888 * Get if this window is an illume conformant window
889 *
890 * @param obj The window object
891 * @return A boolean if this window is illume conformant or not
892 *
893 * @ingroup Win
894 */
895EAPI Eina_Bool elm_win_conformant_get(const Evas_Object *obj);
896
897/**
898 * Set a window to be an illume quickpanel window
899 *
900 * By default window objects are not quickpanel windows.
901 *
902 * @param obj The window object
903 * @param quickpanel The quickpanel flag (1 = quickpanel, 0 = normal window)
904 *
905 * @ingroup Win
906 */
907EAPI void elm_win_quickpanel_set(Evas_Object *obj, Eina_Bool quickpanel);
908
909/**
910 * Get if this window is a quickpanel or not
911 *
912 * @param obj The window object
913 * @return A boolean if this window is a quickpanel or not
914 *
915 * @ingroup Win
916 */
917EAPI Eina_Bool elm_win_quickpanel_get(const Evas_Object *obj);
918
919/**
920 * Set the major priority of a quickpanel window
921 *
922 * @param obj The window object
923 * @param priority The major priority for this quickpanel
924 *
925 * @ingroup Win
926 */
927EAPI void elm_win_quickpanel_priority_major_set(Evas_Object *obj, int priority);
928
929/**
930 * Get the major priority of a quickpanel window
931 *
932 * @param obj The window object
933 * @return The major priority of this quickpanel
934 *
935 * @ingroup Win
936 */
937EAPI int elm_win_quickpanel_priority_major_get(const Evas_Object *obj);
938
939/**
940 * Set the minor priority of a quickpanel window
941 *
942 * @param obj The window object
943 * @param priority The minor priority for this quickpanel
944 *
945 * @ingroup Win
946 */
947EAPI void elm_win_quickpanel_priority_minor_set(Evas_Object *obj, int priority);
948
949/**
950 * Get the minor priority of a quickpanel window
951 *
952 * @param obj The window object
953 * @return The minor priority of this quickpanel
954 *
955 * @ingroup Win
956 */
957EAPI int elm_win_quickpanel_priority_minor_get(const Evas_Object *obj);
958
959/**
960 * Set which zone this quickpanel should appear in
961 *
962 * @param obj The window object
963 * @param zone The requested zone for this quickpanel
964 *
965 * @ingroup Win
966 */
967EAPI void elm_win_quickpanel_zone_set(Evas_Object *obj, int zone);
968
969/**
970 * Get which zone this quickpanel should appear in
971 *
972 * @param obj The window object
973 * @return The requested zone for this quickpanel
974 *
975 * @ingroup Win
976 */
977EAPI int elm_win_quickpanel_zone_get(const Evas_Object *obj);
978
979/**
980 * Set the window to be skipped by keyboard focus
981 *
982 * This sets the window to be skipped by normal keyboard input. This means
983 * a window manager will be asked to not focus this window as well as omit
984 * it from things like the taskbar, pager, "alt-tab" list etc. etc.
985 *
986 * Call this and enable it on a window BEFORE you show it for the first time,
987 * otherwise it may have no effect.
988 *
989 * Use this for windows that have only output information or might only be
990 * interacted with by the mouse or fingers, and never for typing input.
991 * Be careful that this may have side-effects like making the window
992 * non-accessible in some cases unless the window is specially handled. Use
993 * this with care.
994 *
995 * @param obj The window object
996 * @param skip The skip flag state (EINA_TRUE if it is to be skipped)
997 *
998 * @ingroup Win
999 */
1000EAPI void elm_win_prop_focus_skip_set(Evas_Object *obj, Eina_Bool skip);
1001
1002/**
1003 * Send a command to the windowing environment
1004 *
1005 * This is intended to work in touchscreen or small screen device
1006 * environments where there is a more simplistic window management policy in
1007 * place. This uses the window object indicated to select which part of the
1008 * environment to control (the part that this window lives in), and provides
1009 * a command and an optional parameter structure (use NULL for this if not
1010 * needed).
1011 *
1012 * @param obj The window object that lives in the environment to control
1013 * @param command The command to send
1014 * @param params Optional parameters for the command
1015 *
1016 * @ingroup Win
1017 */
1018EAPI void elm_win_illume_command_send(Evas_Object *obj, Elm_Illume_Command command, void *params);
1019
1020/**
1021 * Get the inlined image object handle
1022 *
1023 * When you create a window with elm_win_add() of type ELM_WIN_INLINED_IMAGE,
1024 * then the window is in fact an evas image object inlined in the parent
1025 * canvas. You can get this object (be careful to not manipulate it as it
1026 * is under control of elementary), and use it to do things like get pixel
1027 * data, save the image to a file, etc.
1028 *
1029 * @param obj The window object to get the inlined image from
1030 * @return The inlined image object, or NULL if none exists
1031 *
1032 * @ingroup Win
1033 */
1034EAPI Evas_Object *elm_win_inlined_image_object_get(Evas_Object *obj);
1035
1036/**
1037 * Determine whether a window has focus
1038 * @param obj The window to query
1039 * @return EINA_TRUE if the window exists and has focus, else EINA_FALSE
1040 *
1041 * @ingroup Win
1042 */
1043EAPI Eina_Bool elm_win_focus_get(const Evas_Object *obj);
1044
1045/**
1046 * Constrain the maximum width and height of a window to the width and height of its screen
1047 *
1048 * When @p constrain is true, @p obj will never resize larger than the screen.
1049 * @param obj The window object
1050 * @param constrain EINA_TRUE to restrict the window's maximum size, EINA_FALSE to disable restriction
1051 *
1052 * @ingroup Win
1053 */
1054EAPI void elm_win_screen_constrain_set(Evas_Object *obj, Eina_Bool constrain);
1055
1056/**
1057 * Retrieve the constraints on the maximum width and height of a window relative to the width and height of its screen
1058 *
1059 * When this function returns true, @p obj will never resize larger than the screen.
1060 * @param obj The window object
1061 * @return EINA_TRUE to restrict the window's maximum size, EINA_FALSE to disable restriction
1062 *
1063 * @ingroup Win
1064 */
1065EAPI Eina_Bool elm_win_screen_constrain_get(Evas_Object *obj);
1066
1067/**
1068 * Get screen geometry details for the screen that a window is on
1069 * @param obj The window to query
1070 * @param x where to return the horizontal offset value. May be NULL.
1071 * @param y where to return the vertical offset value. May be NULL.
1072 * @param w where to return the width value. May be NULL.
1073 * @param h where to return the height value. May be NULL.
1074 *
1075 * @ingroup Win
1076 */
1077EAPI void elm_win_screen_size_get(const Evas_Object *obj, int *x, int *y, int *w, int *h);
1078
1079/**
1080 * Set the enabled status for the focus highlight in a window
1081 *
1082 * This function will enable or disable the focus highlight only for the
1083 * given window, regardless of the global setting for it
1084 *
1085 * @param obj The window where to enable the highlight
1086 * @param enabled The enabled value for the highlight
1087 *
1088 * @ingroup Win
1089 */
1090EAPI void elm_win_focus_highlight_enabled_set(Evas_Object *obj, Eina_Bool enabled);
1091
1092/**
1093 * Get the enabled value of the focus highlight for this window
1094 *
1095 * @param obj The window in which to check if the focus highlight is enabled
1096 *
1097 * @return EINA_TRUE if enabled, EINA_FALSE otherwise
1098 *
1099 * @ingroup Win
1100 */
1101EAPI Eina_Bool elm_win_focus_highlight_enabled_get(const Evas_Object *obj);
1102
1103/**
1104 * Set the style for the focus highlight on this window
1105 *
1106 * Sets the style to use for theming the highlight of focused objects on
1107 * the given window. If @p style is NULL, the default will be used.
1108 *
1109 * @param obj The window where to set the style
1110 * @param style The style to set
1111 *
1112 * @ingroup Win
1113 */
1114EAPI void elm_win_focus_highlight_style_set(Evas_Object *obj, const char *style);
1115
1116/**
1117 * Get the style set for the focus highlight object
1118 *
1119 * Gets the style set for this windows highlight object, or NULL if none
1120 * is set.
1121 *
1122 * @param obj The window to retrieve the highlights style from
1123 *
1124 * @return The style set or NULL if none was. Default is used in that case.
1125 *
1126 * @ingroup Win
1127 */
1128EAPI const char *elm_win_focus_highlight_style_get(const Evas_Object *obj);
1129
1130/**
1131 * Sets the keyboard mode of the window.
1132 *
1133 * @param obj The window object
1134 * @param mode The mode to set, one of #Elm_Win_Keyboard_Mode
1135 *
1136 * @ingroup Win
1137 */
1138EAPI void elm_win_keyboard_mode_set(Evas_Object *obj, Elm_Win_Keyboard_Mode mode);
1139
1140/**
1141 * Gets the keyboard mode of the window.
1142 *
1143 * @param obj The window object
1144 * @return The mode, one of #Elm_Win_Keyboard_Mode
1145 *
1146 * @ingroup Win
1147 */
1148EAPI Elm_Win_Keyboard_Mode elm_win_keyboard_mode_get(const Evas_Object *obj);
1149
1150/**
1151 * Sets whether the window is a keyboard.
1152 *
1153 * @param obj The window object
1154 * @param is_keyboard If true, the window is a virtual keyboard
1155 *
1156 * @ingroup Win
1157 */
1158EAPI void elm_win_keyboard_win_set(Evas_Object *obj, Eina_Bool is_keyboard);
1159
1160/**
1161 * Gets whether the window is a keyboard.
1162 *
1163 * @param obj The window object
1164 * @return If the window is a virtual keyboard
1165 *
1166 * @ingroup Win
1167 */
1168EAPI Eina_Bool elm_win_keyboard_win_get(const Evas_Object *obj);
1169
1170/**
1171 * Sets the indicator mode of the window.
1172 *
1173 * @param obj The window object
1174 * @param mode The mode to set, one of #Elm_Win_Indicator_Mode
1175 *
1176 * @ingroup Win
1177 */
1178EAPI void elm_win_indicator_mode_set(Evas_Object *obj, Elm_Win_Indicator_Mode mode);
1179
1180/**
1181 * Gets the indicator mode of the window.
1182 *
1183 * @param obj The window object
1184 * @return The mode, one of #Elm_Win_Indicator_Mode
1185 *
1186 * @ingroup Win
1187 */
1188EAPI Elm_Win_Indicator_Mode elm_win_indicator_mode_get(const Evas_Object *obj);
1189
1190/**
1191 * Sets the indicator opacity mode of the window.
1192 *
1193 * @param obj The window object
1194 * @param mode The mode to set, one of #Elm_Win_Indicator_Opacity_Mode
1195 *
1196 * @ingroup Win
1197 */
1198EAPI void elm_win_indicator_opacity_set(Evas_Object *obj, Elm_Win_Indicator_Opacity_Mode mode);
1199
1200/**
1201 * Gets the indicator opacity mode of the window.
1202 *
1203 * @param obj The window object
1204 * @return The mode, one of #Elm_Win_Indicator_Opacity_Mode
1205 *
1206 * @ingroup Win
1207 */
1208EAPI Elm_Win_Indicator_Opacity_Mode elm_win_indicator_opacity_get(const Evas_Object *obj);
1209
1210/**
1211 * Get the screen position of a window.
1212 *
1213 * @param obj The window object
1214 * @param x The int to store the x coordinate to
1215 * @param y The int to store the y coordinate to
1216 *
1217 * @ingroup Win
1218 */
1219EAPI void elm_win_screen_position_get(const Evas_Object *obj, int *x, int *y);
1220
1221/**
1222 * Create a socket to provide the service for Plug widget
1223 *
1224 * @param obj The window object
1225 * @param svcname The name of the service to be advertised. ensure that it is unique (when combined with @p svcnum) otherwise creation may fail.
1226 * @param svcnum A number (any value, 0 being the common default) to differentiate multiple instances of services with the same name.
1227 * @param svcsys A boolean that if true, specifies to create a system-wide service all users can connect to, otherwise the service is private to the user id that created the service.
1228 * @return If socket creation is successful
1229 *
1230 * @ingroup Win
1231 */
1232EAPI Eina_Bool elm_win_socket_listen(Evas_Object *obj, const char *svcname, int svcnum, Eina_Bool svcsys);
1233
1234/* X specific calls - won't work on non-x engines (return 0) */
1235/**
1236 * Get the Ecore_X_Window of an Evas_Object
1237 *
1238 * @param obj The object
1239 *
1240 * @return The Ecore_X_Window of @p obj
1241 *
1242 * @ingroup Win
1243 */
1244EAPI Ecore_X_Window elm_win_xwindow_get(const Evas_Object *obj);
1245
1246/**
1247 * @}
1248 */
1249
1250/**
1251 * @defgroup Inwin Inwin
1252 * @ingroup Win
1253 *
1254 * @image html img/widget/inwin/preview-00.png
1255 * @image latex img/widget/inwin/preview-00.eps
1256 * @image html img/widget/inwin/preview-01.png
1257 * @image latex img/widget/inwin/preview-01.eps
1258 * @image html img/widget/inwin/preview-02.png
1259 * @image latex img/widget/inwin/preview-02.eps
1260 *
1261 * An inwin is a window inside a window that is useful for a quick popup.
1262 * It does not hover.
1263 *
1264 * It works by creating an object that will occupy the entire window, so it
1265 * must be created using an @ref Win "elm_win" as parent only. The inwin
1266 * object can be hidden or restacked below every other object if it's
1267 * needed to show what's behind it without destroying it. If this is done,
1268 * the elm_win_inwin_activate() function can be used to bring it back to
1269 * full visibility again.
1270 *
1271 * There are three styles available in the default theme. These are:
1272 * @li default: The inwin is sized to take over most of the window it's
1273 * placed in.
1274 * @li minimal: The size of the inwin will be the minimum necessary to show
1275 * its contents.
1276 * @li minimal_vertical: Horizontally, the inwin takes as much space as
1277 * possible, but it's sized vertically the most it needs to fit its\
1278 * contents.
1279 *
1280 * Some examples of Inwin can be found in the following:
1281 * @li @ref inwin_example_01
1282 *
1283 * @{
1284 */
1285
1286/**
1287 * Adds an inwin to the current window
1288 *
1289 * The @p obj used as parent @b MUST be an @ref Win "Elementary Window".
1290 * Never call this function with anything other than the top-most window
1291 * as its parameter, unless you are fond of undefined behavior.
1292 *
1293 * After creating the object, the widget will set itself as resize object
1294 * for the window with elm_win_resize_object_add(), so when shown it will
1295 * appear to cover almost the entire window (how much of it depends on its
1296 * content and the style used). It must not be added into other container
1297 * objects and it needs not be moved or resized manually.
1298 *
1299 * @param parent The parent object
1300 * @return The new object or NULL if it cannot be created
1301 *
1302 * @ingroup Inwin
1303 */
1304EAPI Evas_Object *elm_win_inwin_add(Evas_Object *parent);
1305
1306/**
1307 * Activates an inwin object, ensuring its visibility
1308 *
1309 * This function will make sure that the inwin @p obj is completely visible
1310 * by calling evas_object_show() and evas_object_raise() on it, to bring it
1311 * to the front. It also sets the keyboard focus to it, which will be passed
1312 * onto its content.
1313 *
1314 * The object's theme will also receive the signal "elm,action,show" with
1315 * source "elm".
1316 *
1317 * @param obj The inwin to activate
1318 *
1319 * @ingroup Inwin
1320 */
1321EAPI void elm_win_inwin_activate(Evas_Object *obj);
1322
1323/**
1324 * Set the content of an inwin object.
1325 *
1326 * Once the content object is set, a previously set one will be deleted.
1327 * If you want to keep that old content object, use the
1328 * elm_win_inwin_content_unset() function.
1329 *
1330 * @param obj The inwin object
1331 * @param content The object to set as content
1332 *
1333 * @ingroup Inwin
1334 */
1335EAPI void elm_win_inwin_content_set(Evas_Object *obj, Evas_Object *content);
1336
1337/**
1338 * Get the content of an inwin object.
1339 *
1340 * Return the content object for this widget.
1341 *
1342 * The returned object is valid as long as the inwin is still alive and no
1343 * other content is set on it. Deleting the object will notify the inwin
1344 * about it and this one will be left empty.
1345 *
1346 * If you need to remove an inwin's content to be reused somewhere else,
1347 * see elm_win_inwin_content_unset().
1348 *
1349 * @param obj The inwin object
1350 * @return The content that is being used
1351 *
1352 * @ingroup Inwin
1353 */
1354EAPI Evas_Object *elm_win_inwin_content_get(const Evas_Object *obj);
1355
1356/**
1357 * Unset the content of an inwin object.
1358 *
1359 * Unparent and return the content object which was set for this widget.
1360 *
1361 * @param obj The inwin object
1362 * @return The content that was being used
1363 *
1364 * @ingroup Inwin
1365 */
1366EAPI Evas_Object *elm_win_inwin_content_unset(Evas_Object *obj);
1367
1368/**
1369 * @}
1370 */
1371
diff --git a/libraries/elementary/src/lib/els_box.c b/libraries/elementary/src/lib/els_box.c
new file mode 100644
index 0000000..50810a6
--- /dev/null
+++ b/libraries/elementary/src/lib/els_box.c
@@ -0,0 +1,256 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_box.h"
4
5static void
6_smart_extents_calculate(Evas_Object *box, Evas_Object_Box_Data *priv, int horizontal, int homogeneous)
7{
8 Evas_Coord minw, minh, mnw, mnh, maxw, maxh;
9 const Eina_List *l;
10 Evas_Object_Box_Option *opt;
11 int c;
12
13 minw = 0;
14 minh = 0;
15 maxw = -1;
16 maxh = -1;
17 if (homogeneous)
18 {
19 EINA_LIST_FOREACH(priv->children, l, opt)
20 {
21 evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
22 if (minh < mnh) minh = mnh;
23 if (minw < mnw) minw = mnw;
24
25 evas_object_size_hint_max_get(opt->obj, &mnw, &mnh);
26 if (mnh >= 0)
27 {
28 if (maxw == -1) maxh = mnh;
29 else if (maxh > mnh) maxh = mnh;
30 }
31 if (mnw >= 0)
32 {
33 if (maxw == -1) maxw = mnw;
34 else if (maxw > mnw) maxw = mnw;
35 }
36 }
37 if (horizontal)
38 {
39 minw *= eina_list_count(priv->children);
40 if (maxw != -1)
41 maxw *= eina_list_count(priv->children);
42 else maxw = -1;
43 }
44 else
45 {
46 minh *= eina_list_count(priv->children);
47 if (maxh != -1)
48 maxh *= eina_list_count(priv->children);
49 else maxh = -1;
50 }
51 }
52 else
53 {
54 EINA_LIST_FOREACH(priv->children, l, opt)
55 {
56 evas_object_size_hint_min_get(opt->obj, &mnw, &mnh);
57 if (horizontal)
58 {
59 if (minh < mnh) minh = mnh;
60 minw += mnw;
61 }
62 else
63 {
64 if (minw < mnw) minw = mnw;
65 minh += mnh;
66 }
67 evas_object_size_hint_max_get(opt->obj, &mnw, &mnh);
68 if (horizontal)
69 {
70 if (mnw < 0) maxw = -1;
71 if (maxw != -1)
72 {
73 if (maxw > mnw) maxw = mnw;
74 maxw += mnw;
75 }
76 }
77 else
78 {
79 if (mnh < 0) maxh = -1;
80 if (maxh != -1)
81 {
82 if (maxh > mnh) maxh = mnh;
83 maxh += mnh;
84 }
85 }
86 }
87 }
88 c = eina_list_count(priv->children) - 1;
89 if (c > 0)
90 {
91 if (horizontal)
92 {
93 minw += priv->pad.h * c;
94 if (maxw != -1) maxw += priv->pad.h * c;
95 }
96 else
97 {
98 minh += priv->pad.v * c;
99 if (maxh != -1) maxh += priv->pad.v * c;
100 }
101 }
102 evas_object_size_hint_min_set(box, minw, minh);
103 evas_object_size_hint_max_set(box, maxw, maxh);
104}
105
106void
107_els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous, int rtl)
108{
109 Evas_Coord x, y, w, h, xx, yy;
110 const Eina_List *l;
111 Evas_Object *obj;
112 Evas_Coord minw, minh, wdif, hdif;
113 int count = 0;
114 double expand = 0.0;
115 double ax, ay;
116 Evas_Object_Box_Option *opt;
117
118 _smart_extents_calculate(o, priv, horizontal, homogeneous);
119
120 evas_object_geometry_get(o, &x, &y, &w, &h);
121
122 evas_object_size_hint_min_get(o, &minw, &minh);
123 evas_object_size_hint_align_get(o, &ax, &ay);
124 if ((w < minw) || (h < minh)) return;
125 count = eina_list_count(priv->children);
126 if (rtl) ax = 1.0 - ax;
127
128 if (w < minw)
129 {
130 x = x + ((w - minw) * (1.0 - ax));
131 w = minw;
132 }
133 if (h < minh)
134 {
135 y = y + ((h - minh) * (1.0 - ay));
136 h = minh;
137 }
138 EINA_LIST_FOREACH(priv->children, l, opt)
139 {
140 double wx, wy;
141
142 evas_object_size_hint_weight_get(opt->obj, &wx, &wy);
143 if (horizontal)
144 {
145 if (wx > 0.0) expand += wx;
146 }
147 else
148 {
149 if (wy > 0.0) expand += wy;
150 }
151 }
152 if (!expand)
153 {
154 evas_object_size_hint_align_get(o, &ax, &ay);
155 if (rtl) ax = 1.0 - ax;
156 if (horizontal)
157 {
158 x += (double)(w - minw) * ax;
159 w = minw;
160 }
161 else
162 {
163 y += (double)(h - minh) * ay;
164 h = minh;
165 }
166 }
167 wdif = w - minw;
168 hdif = h - minh;
169 xx = x;
170 yy = y;
171 EINA_LIST_FOREACH(priv->children, l, opt)
172 {
173 Evas_Coord mnw, mnh, mxw, mxh;
174 double wx, wy;
175 int fw, fh, xw, xh;
176
177 obj = opt->obj;
178 evas_object_size_hint_align_get(obj, &ax, &ay);
179 evas_object_size_hint_weight_get(obj, &wx, &wy);
180 evas_object_size_hint_min_get(obj, &mnw, &mnh);
181 evas_object_size_hint_max_get(obj, &mxw, &mxh);
182 fw = fh = 0;
183 xw = xh = 0;
184 if (ax == -1.0) {fw = 1; ax = 0.5;}
185 if (ay == -1.0) {fh = 1; ay = 0.5;}
186 if (rtl) ax = 1.0 - ax;
187 if (wx > 0.0) xw = 1;
188 if (wy > 0.0) xh = 1;
189 if (horizontal)
190 {
191 Evas_Coord ww, hh, ow, oh;
192
193 if (homogeneous)
194 {
195 ww = (w / (Evas_Coord)count);
196 }
197 else
198 {
199 ww = mnw;
200 if ((expand > 0) && (xw))
201 {
202 ow = ((w - minw) * wx) / expand;
203 wdif -= ow;
204 ww += ow;
205 }
206 }
207 hh = h;
208 ow = mnw;
209 if (fw) ow = ww;
210 if ((mxw >= 0) && (mxw < ow)) ow = mxw;
211 oh = mnh;
212 if (fh) oh = hh;
213 if ((mxh >= 0) && (mxh < oh)) oh = mxh;
214 evas_object_move(obj,
215 ((!rtl) ? (xx) : (x + (w - (xx - x) - ww)))
216 + (Evas_Coord)(((double)(ww - ow)) * ax),
217 yy + (Evas_Coord)(((double)(hh - oh)) * ay));
218 evas_object_resize(obj, ow, oh);
219 xx += ww;
220 xx += priv->pad.h;
221 }
222 else
223 {
224 Evas_Coord ww, hh, ow, oh;
225
226 if (homogeneous)
227 {
228 hh = (h / (Evas_Coord)count);
229 }
230 else
231 {
232 hh = mnh;
233 if ((expand > 0) && (xh))
234 {
235 oh = ((h - minh) * wy) / expand;
236 hdif -= oh;
237 hh += oh;
238 }
239 }
240 ww = w;
241 ow = mnw;
242 if (fw) ow = ww;
243 if ((mxw >= 0) && (mxw < ow)) ow = mxw;
244 oh = mnh;
245 if (fh) oh = hh;
246 if ((mxh >= 0) && (mxh < oh)) oh = mxh;
247 evas_object_move(obj,
248 xx + (Evas_Coord)(((double)(ww - ow)) * ax),
249 yy + (Evas_Coord)(((double)(hh - oh)) * ay));
250 evas_object_resize(obj, ow, oh);
251 yy += hh;
252 yy += priv->pad.v;
253 }
254 }
255}
256
diff --git a/libraries/elementary/src/lib/els_box.h b/libraries/elementary/src/lib/els_box.h
new file mode 100644
index 0000000..026f3af
--- /dev/null
+++ b/libraries/elementary/src/lib/els_box.h
@@ -0,0 +1 @@
void _els_box_layout(Evas_Object *o, Evas_Object_Box_Data *priv, int horizontal, int homogeneous, int rtl);
diff --git a/libraries/elementary/src/lib/els_cursor.c b/libraries/elementary/src/lib/els_cursor.c
new file mode 100644
index 0000000..7e8a625
--- /dev/null
+++ b/libraries/elementary/src/lib/els_cursor.c
@@ -0,0 +1,506 @@
1#include <Elementary.h>
2#include <Elementary_Cursor.h>
3#include "elm_priv.h"
4
5#ifdef HAVE_ELEMENTARY_X
6#include <Ecore_X.h>
7#include <Ecore_X_Cursor.h>
8#endif
9
10#define _cursor_key "_elm_cursor"
11
12struct _Cursor_Id
13{
14 const char *name;
15#ifdef HAVE_ELEMENTARY_X
16 int id;
17#endif
18};
19
20#ifdef HAVE_ELEMENTARY_X
21#define CURSOR(_name, _xid) \
22 {_name , _xid}
23# else
24#define CURSOR(_name, _xid) \
25 {_name}
26#endif
27
28/* Please keep order in sync with Ecore_X_Cursor.h values! */
29struct _Cursor_Id _cursors[] =
30{
31 CURSOR(ELM_CURSOR_X , ECORE_X_CURSOR_X ),
32 CURSOR(ELM_CURSOR_ARROW , ECORE_X_CURSOR_ARROW ),
33 CURSOR(ELM_CURSOR_BASED_ARROW_DOWN , ECORE_X_CURSOR_BASED_ARROW_DOWN ),
34 CURSOR(ELM_CURSOR_BASED_ARROW_UP , ECORE_X_CURSOR_UP ),
35 CURSOR(ELM_CURSOR_BOAT , ECORE_X_CURSOR_BOAT ),
36 CURSOR(ELM_CURSOR_BOGOSITY , ECORE_X_CURSOR_BOGOSITY ),
37 CURSOR(ELM_CURSOR_BOTTOM_LEFT_CORNER , ECORE_X_CURSOR_BOTTOM_LEFT_CORNER ),
38 CURSOR(ELM_CURSOR_BOTTOM_RIGHT_CORNER, ECORE_X_CURSOR_BOTTOM_RIGHT_CORNER),
39 CURSOR(ELM_CURSOR_BOTTOM_SIDE , ECORE_X_CURSOR_BOTTOM_SIDE ),
40 CURSOR(ELM_CURSOR_BOTTOM_TEE , ECORE_X_CURSOR_BOTTOM_TEE ),
41 CURSOR(ELM_CURSOR_BOX_SPIRAL , ECORE_X_CURSOR_BOX_SPIRAL ),
42 CURSOR(ELM_CURSOR_CENTER_PTR , ECORE_X_CURSOR_CENTER_PTR ),
43 CURSOR(ELM_CURSOR_CIRCLE , ECORE_X_CURSOR_CIRCLE ),
44 CURSOR(ELM_CURSOR_CLOCK , ECORE_X_CURSOR_CLOCK ),
45 CURSOR(ELM_CURSOR_COFFEE_MUG , ECORE_X_CURSOR_COFFEE_MUG ),
46 CURSOR(ELM_CURSOR_CROSS , ECORE_X_CURSOR_CROSS ),
47 CURSOR(ELM_CURSOR_CROSS_REVERSE , ECORE_X_CURSOR_CROSS_REVERSE ),
48 CURSOR(ELM_CURSOR_CROSSHAIR , ECORE_X_CURSOR_CROSSHAIR ),
49 CURSOR(ELM_CURSOR_DIAMOND_CROSS , ECORE_X_CURSOR_DIAMOND_CROSS ),
50 CURSOR(ELM_CURSOR_DOT , ECORE_X_CURSOR_DOT ),
51 CURSOR(ELM_CURSOR_DOT_BOX_MASK , ECORE_X_CURSOR_DOT_BOX_MASK ),
52 CURSOR(ELM_CURSOR_DOUBLE_ARROW , ECORE_X_CURSOR_DOUBLE_ARROW ),
53 CURSOR(ELM_CURSOR_DRAFT_LARGE , ECORE_X_CURSOR_DRAFT_LARGE ),
54 CURSOR(ELM_CURSOR_DRAFT_SMALL , ECORE_X_CURSOR_DRAFT_SMALL ),
55 CURSOR(ELM_CURSOR_DRAPED_BOX , ECORE_X_CURSOR_DRAPED_BOX ),
56 CURSOR(ELM_CURSOR_EXCHANGE , ECORE_X_CURSOR_EXCHANGE ),
57 CURSOR(ELM_CURSOR_FLEUR , ECORE_X_CURSOR_FLEUR ),
58 CURSOR(ELM_CURSOR_GOBBLER , ECORE_X_CURSOR_GOBBLER ),
59 CURSOR(ELM_CURSOR_GUMBY , ECORE_X_CURSOR_GUMBY ),
60 CURSOR(ELM_CURSOR_HAND1 , ECORE_X_CURSOR_HAND1 ),
61 CURSOR(ELM_CURSOR_HAND2 , ECORE_X_CURSOR_HAND2 ),
62 CURSOR(ELM_CURSOR_HEART , ECORE_X_CURSOR_HEART ),
63 CURSOR(ELM_CURSOR_ICON , ECORE_X_CURSOR_ICON ),
64 CURSOR(ELM_CURSOR_IRON_CROSS , ECORE_X_CURSOR_IRON_CROSS ),
65 CURSOR(ELM_CURSOR_LEFT_PTR , ECORE_X_CURSOR_LEFT_PTR ),
66 CURSOR(ELM_CURSOR_LEFT_SIDE , ECORE_X_CURSOR_LEFT_SIDE ),
67 CURSOR(ELM_CURSOR_LEFT_TEE , ECORE_X_CURSOR_LEFT_TEE ),
68 CURSOR(ELM_CURSOR_LEFTBUTTON , ECORE_X_CURSOR_LEFTBUTTON ),
69 CURSOR(ELM_CURSOR_LL_ANGLE , ECORE_X_CURSOR_LL_ANGLE ),
70 CURSOR(ELM_CURSOR_LR_ANGLE , ECORE_X_CURSOR_LR_ANGLE ),
71 CURSOR(ELM_CURSOR_MAN , ECORE_X_CURSOR_MAN ),
72 CURSOR(ELM_CURSOR_MIDDLEBUTTON , ECORE_X_CURSOR_MIDDLEBUTTON ),
73 CURSOR(ELM_CURSOR_MOUSE , ECORE_X_CURSOR_MOUSE ),
74 CURSOR(ELM_CURSOR_PENCIL , ECORE_X_CURSOR_PENCIL ),
75 CURSOR(ELM_CURSOR_PIRATE , ECORE_X_CURSOR_PIRATE ),
76 CURSOR(ELM_CURSOR_PLUS , ECORE_X_CURSOR_PLUS ),
77 CURSOR(ELM_CURSOR_QUESTION_ARROW , ECORE_X_CURSOR_QUESTION_ARROW ),
78 CURSOR(ELM_CURSOR_RIGHT_PTR , ECORE_X_CURSOR_RIGHT_PTR ),
79 CURSOR(ELM_CURSOR_RIGHT_SIDE , ECORE_X_CURSOR_RIGHT_SIDE ),
80 CURSOR(ELM_CURSOR_RIGHT_TEE , ECORE_X_CURSOR_RIGHT_TEE ),
81 CURSOR(ELM_CURSOR_RIGHTBUTTON , ECORE_X_CURSOR_RIGHTBUTTON ),
82 CURSOR(ELM_CURSOR_RTL_LOGO , ECORE_X_CURSOR_RTL_LOGO ),
83 CURSOR(ELM_CURSOR_SAILBOAT , ECORE_X_CURSOR_SAILBOAT ),
84 CURSOR(ELM_CURSOR_SB_DOWN_ARROW , ECORE_X_CURSOR_SB_DOWN_ARROW ),
85 CURSOR(ELM_CURSOR_SB_H_DOUBLE_ARROW , ECORE_X_CURSOR_SB_H_DOUBLE_ARROW ),
86 CURSOR(ELM_CURSOR_SB_LEFT_ARROW , ECORE_X_CURSOR_SB_LEFT_ARROW ),
87 CURSOR(ELM_CURSOR_SB_RIGHT_ARROW , ECORE_X_CURSOR_SB_RIGHT_ARROW ),
88 CURSOR(ELM_CURSOR_SB_UP_ARROW , ECORE_X_CURSOR_SB_UP_ARROW ),
89 CURSOR(ELM_CURSOR_SB_V_DOUBLE_ARROW , ECORE_X_CURSOR_SB_V_DOUBLE_ARROW ),
90 CURSOR(ELM_CURSOR_SHUTTLE , ECORE_X_CURSOR_SHUTTLE ),
91 CURSOR(ELM_CURSOR_SIZING , ECORE_X_CURSOR_SIZING ),
92 CURSOR(ELM_CURSOR_SPIDER , ECORE_X_CURSOR_SPIDER ),
93 CURSOR(ELM_CURSOR_SPRAYCAN , ECORE_X_CURSOR_SPRAYCAN ),
94 CURSOR(ELM_CURSOR_STAR , ECORE_X_CURSOR_STAR ),
95 CURSOR(ELM_CURSOR_TARGET , ECORE_X_CURSOR_TARGET ),
96 CURSOR(ELM_CURSOR_TCROSS , ECORE_X_CURSOR_TCROSS ),
97 CURSOR(ELM_CURSOR_TOP_LEFT_ARROW , ECORE_X_CURSOR_TOP_LEFT_ARROW ),
98 CURSOR(ELM_CURSOR_TOP_LEFT_CORNER , ECORE_X_CURSOR_TOP_LEFT_CORNER ),
99 CURSOR(ELM_CURSOR_TOP_RIGHT_CORNER , ECORE_X_CURSOR_TOP_RIGHT_CORNER ),
100 CURSOR(ELM_CURSOR_TOP_SIDE , ECORE_X_CURSOR_TOP_SIDE ),
101 CURSOR(ELM_CURSOR_TOP_TEE , ECORE_X_CURSOR_TOP_TEE ),
102 CURSOR(ELM_CURSOR_TREK , ECORE_X_CURSOR_TREK ),
103 CURSOR(ELM_CURSOR_UL_ANGLE , ECORE_X_CURSOR_UL_ANGLE ),
104 CURSOR(ELM_CURSOR_UMBRELLA , ECORE_X_CURSOR_UMBRELLA ),
105 CURSOR(ELM_CURSOR_UR_ANGLE , ECORE_X_CURSOR_UR_ANGLE ),
106 CURSOR(ELM_CURSOR_WATCH , ECORE_X_CURSOR_WATCH ),
107 CURSOR(ELM_CURSOR_XTERM , ECORE_X_CURSOR_XTERM )
108};
109static const int _cursors_count = sizeof(_cursors)/sizeof(struct _Cursor_Id);
110
111#define ELM_CURSOR_GET_OR_RETURN(cur, obj, ...) \
112 Elm_Cursor *cur; \
113 do \
114 { \
115 if (!(obj)) \
116 { \
117 CRITICAL("Null pointer: " #obj); \
118 return __VA_ARGS__; \
119 } \
120 cur = evas_object_data_get((obj), _cursor_key); \
121 if (!cur) \
122 { \
123 ERR("Object does not have cursor: " #obj); \
124 return __VA_ARGS__; \
125 } \
126 } \
127 while (0)
128
129struct _Elm_Cursor
130{
131 Evas_Object *obj;
132 Evas_Object *eventarea, *owner;
133 const char *style, *cursor_name;
134 int hot_x, hot_y;
135 Ecore_Evas *ee;
136 Evas *evas;
137#ifdef HAVE_ELEMENTARY_X
138 Ecore_X_Cursor cursor;
139 Ecore_X_Window win;
140#endif
141 Eina_Bool visible:1;
142 Eina_Bool use_engine:1;
143 Eina_Bool engine_only:1;
144};
145
146static void
147_elm_cursor_obj_del(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
148{
149 Elm_Cursor *cur = data;
150
151 if (cur) cur->obj = NULL;
152}
153
154static Eina_Bool
155_elm_cursor_obj_add(Evas_Object *obj, Elm_Cursor *cur)
156{
157 int x, y;
158
159 cur->obj = edje_object_add(cur->evas);
160
161 if (!cur->obj)
162 return EINA_FALSE;
163
164 if (!_elm_theme_object_set(obj, cur->obj, "cursor", cur->cursor_name,
165 cur->style ? cur->style : "default"))
166 {
167 evas_object_del(cur->obj);
168 cur->obj = NULL;
169 return EINA_FALSE;
170 }
171
172 evas_object_event_callback_add(cur->obj, EVAS_CALLBACK_DEL,
173 _elm_cursor_obj_del, cur);
174
175 edje_object_size_min_get(cur->obj, &x, &y);
176 evas_object_resize(cur->obj, x, y);
177 return EINA_TRUE;
178}
179
180static void
181_elm_cursor_set_hot_spots(Elm_Cursor *cur)
182{
183 const char *str;
184
185 str = edje_object_data_get(cur->obj, "hot_x");
186 if (str) cur->hot_x = atoi(str);
187 else cur->hot_x = 0;
188
189 str = edje_object_data_get(cur->obj, "hot_y");
190 if (str) cur->hot_y = atoi(str);
191 else cur->hot_y = 0;
192}
193
194static void
195_elm_cursor_mouse_in(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
196{
197 Elm_Cursor *cur = data;
198
199 if (cur->visible) return;
200 evas_event_freeze(cur->evas);
201 cur->visible = EINA_TRUE;
202 if ((!cur->engine_only) && (!cur->use_engine))
203 {
204 if (!cur->obj)
205 _elm_cursor_obj_add(cur->eventarea, cur);
206 ecore_evas_object_cursor_set(cur->ee, cur->obj,
207 ELM_OBJECT_LAYER_CURSOR, cur->hot_x,
208 cur->hot_y);
209 }
210 else
211 {
212#ifdef HAVE_ELEMENTARY_X
213 if (cur->win)
214 {
215 ecore_x_window_cursor_set(cur->win, cur->cursor);
216 }
217#endif
218 }
219 evas_event_thaw(cur->evas);
220}
221
222static void
223_elm_cursor_mouse_out(void *data, Evas *evas __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
224{
225 Evas_Object *sobj_parent;
226 Elm_Cursor *pcur = NULL;
227 Elm_Cursor *cur = data;
228
229 if (!cur->visible) return;
230 evas_event_freeze(cur->evas);
231 cur->visible = EINA_FALSE;
232
233 sobj_parent = evas_object_data_get(cur->eventarea, "elm-parent");
234 while (sobj_parent)
235 {
236 pcur = evas_object_data_get((sobj_parent), _cursor_key);
237 if ((pcur) && (pcur->visible)) break;
238 sobj_parent = evas_object_data_get(sobj_parent, "elm-parent");
239 }
240
241 if (pcur)
242 {
243 pcur->visible = EINA_FALSE;
244 evas_event_thaw(cur->evas);
245 _elm_cursor_mouse_in(pcur, NULL, NULL, NULL);
246 return;
247 }
248
249 if ((!cur->engine_only) || (!cur->use_engine))
250 {
251 ecore_evas_object_cursor_set(cur->ee, NULL, ELM_OBJECT_LAYER_CURSOR,
252 cur->hot_x, cur->hot_y);
253 }
254 else
255 {
256#ifdef HAVE_ELEMENTARY_X
257 if (cur->win)
258 {
259 ecore_x_window_cursor_set(cur->win, ECORE_X_CURSOR_X);
260 }
261#endif
262 }
263 evas_event_thaw(cur->evas);
264}
265
266static void
267_elm_cursor_del(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
268{
269 elm_object_cursor_unset(obj);
270}
271
272#ifdef HAVE_ELEMENTARY_X
273static int
274_elm_cursor_strcmp(const void *data1, const void *data2)
275{
276 const struct _Cursor_Id *c1 = data1;
277 const struct _Cursor_Id *c2 = data2;
278 return strcmp (c1->name, c2->name);
279}
280#endif
281
282static void
283_elm_cursor_cur_set(Elm_Cursor *cur)
284{
285 if (cur->engine_only)
286 {
287 INF("Using only engine cursors");
288 cur->use_engine = EINA_TRUE;
289 }
290 else if (_elm_cursor_obj_add(cur->eventarea, cur))
291 {
292 _elm_cursor_set_hot_spots(cur);
293 cur->use_engine = EINA_FALSE;
294 elm_widget_cursor_add(cur->owner, cur);
295 }
296 else
297 {
298 INF("Cursor couldn't be found on theme: %s", cur->cursor_name);
299 cur->use_engine = EINA_TRUE;
300 }
301
302 if (cur->use_engine)
303 {
304#ifdef HAVE_ELEMENTARY_X
305 struct _Cursor_Id *cur_id;
306
307 cur_id = bsearch(&(cur->cursor_name), _cursors, _cursors_count,
308 sizeof(struct _Cursor_Id), _elm_cursor_strcmp);
309
310 cur->win = elm_win_xwindow_get(cur->eventarea);
311 if (cur->win)
312 {
313 if (!cur_id)
314 {
315 INF("X cursor couldn't be found: %s. Using default.",
316 cur->cursor_name);
317 cur->cursor = ecore_x_cursor_shape_get(ECORE_X_CURSOR_X);
318 }
319 else
320 cur->cursor = ecore_x_cursor_shape_get(cur_id->id);
321 }
322#endif
323 }
324}
325
326/**
327 * Set the cursor to be shown when mouse is over the object
328 *
329 * Set the cursor that will be displayed when mouse is over the
330 * object. The object can have only one cursor set to it, so if
331 * this function is called twice for an object, the previous set
332 * will be unset.
333 * If using X cursors, a definition of all the valid cursor names
334 * is listed on Elementary_Cursors.h. If an invalid name is set
335 * the default cursor will be used.
336 *
337 * This is an internal function that is used by objects with sub-items
338 * that want to provide different cursors for each of them. The @a
339 * owner object should be an elm_widget and will be used to track
340 * theme changes and to feed @a func and @a del_cb. The @a eventarea
341 * may be any object and is the one that should be used later on with
342 * elm_object_cursor apis, such as elm_object_cursor_unset().
343 *
344 * @param eventarea the object being attached a cursor.
345 * @param owner the elm_widget that owns this object, will be used to
346 * track theme changes and to be used in @a func or @a del_cb.
347 * @param cursor the cursor name to be used.
348 *
349 * @internal
350 * @ingroup Cursors
351 */
352void
353elm_object_sub_cursor_set(Evas_Object *eventarea, Evas_Object *owner, const char *cursor)
354{
355 Elm_Cursor *cur = NULL;
356
357 cur = evas_object_data_get(eventarea, _cursor_key);
358 if (cur)
359 elm_object_cursor_unset(eventarea);
360
361 if (!cursor) return;
362
363 cur = ELM_NEW(Elm_Cursor);
364 if (!cur) return;
365
366 cur->owner = owner;
367 cur->eventarea = eventarea;
368 cur->engine_only = _elm_config->cursor_engine_only;
369 cur->visible = EINA_FALSE;
370
371 cur->cursor_name = eina_stringshare_add(cursor);
372 if (!cur->cursor_name)
373 ERR("Could not store cursor name %s", cursor);
374
375 cur->evas = evas_object_evas_get(eventarea);
376 cur->ee = ecore_evas_ecore_evas_get(cur->evas);
377
378 _elm_cursor_cur_set(cur);
379
380 evas_object_data_set(eventarea, _cursor_key, cur);
381
382 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_IN,
383 _elm_cursor_mouse_in, cur);
384 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_OUT,
385 _elm_cursor_mouse_out, cur);
386 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_DEL,
387 _elm_cursor_del, cur);
388}
389
390EAPI void
391elm_object_cursor_set(Evas_Object *obj, const char *cursor)
392{
393 EINA_SAFETY_ON_NULL_RETURN(obj);
394 elm_object_sub_cursor_set(obj, obj, cursor);
395}
396
397EAPI const char *
398elm_object_cursor_get(const Evas_Object *obj)
399{
400 ELM_CURSOR_GET_OR_RETURN(cur, obj, NULL);
401 return cur->cursor_name;
402}
403
404EAPI void
405elm_object_cursor_unset(Evas_Object *obj)
406{
407 ELM_CURSOR_GET_OR_RETURN(cur, obj);
408
409 eina_stringshare_del(cur->cursor_name);
410 eina_stringshare_del(cur->style);
411
412 if (cur->owner)
413 elm_widget_cursor_del(cur->owner, cur);
414
415 if (cur->obj)
416 evas_object_del(cur->obj);
417
418 if (cur->visible)
419 {
420 if (!cur->use_engine)
421 ecore_evas_object_cursor_set(cur->ee, NULL, ELM_OBJECT_LAYER_CURSOR,
422 cur->hot_x, cur->hot_y);
423#ifdef HAVE_ELEMENTARY_X
424 else if (cur->win)
425 ecore_x_window_cursor_set(cur->win, ECORE_X_CURSOR_X);
426#endif
427 }
428
429 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_IN,
430 _elm_cursor_mouse_in);
431 evas_object_event_callback_del(obj, EVAS_CALLBACK_MOUSE_OUT,
432 _elm_cursor_mouse_out);
433 evas_object_event_callback_del(obj, EVAS_CALLBACK_DEL, _elm_cursor_del);
434
435 evas_object_data_del(obj, _cursor_key);
436 free(cur);
437}
438
439EAPI void
440elm_object_cursor_style_set(Evas_Object *obj, const char *style)
441{
442 ELM_CURSOR_GET_OR_RETURN(cur, obj);
443
444 if (!eina_stringshare_replace(&cur->style, style))
445 ERR("Could not set current style=%s", style);
446
447 if (cur->use_engine) return;
448
449 if (!cur->obj)
450 {
451 if (!_elm_cursor_obj_add(obj, cur))
452 ERR("Could not create cursor object");
453 else
454 _elm_cursor_set_hot_spots(cur);
455 }
456 else
457 {
458 if (!_elm_theme_object_set(obj, cur->obj, "cursor", cur->cursor_name,
459 style))
460 ERR("Could not apply the theme to the cursor style=%s", style);
461 else
462 _elm_cursor_set_hot_spots(cur);
463 }
464}
465
466EAPI const char *
467elm_object_cursor_style_get(const Evas_Object *obj)
468{
469 ELM_CURSOR_GET_OR_RETURN(cur, obj, NULL);
470 return cur->style ? cur->style : "default";
471}
472
473/**
474 * Notify cursor should recalculate its theme.
475 * @internal
476 */
477void
478elm_cursor_theme(Elm_Cursor *cur)
479{
480 if ((!cur) || (!cur->obj)) return;
481 if (!_elm_theme_object_set(cur->eventarea, cur->obj, "cursor",
482 cur->cursor_name, cur->style))
483 ERR("Could not apply the theme to the cursor style=%s", cur->style);
484 else
485 _elm_cursor_set_hot_spots(cur);
486}
487
488EAPI void elm_object_cursor_theme_search_enabled_set(Evas_Object *obj, Eina_Bool theme_search)
489{
490 ELM_CURSOR_GET_OR_RETURN(cur, obj);
491 cur->engine_only = theme_search;
492 if (cur->obj)
493 {
494 evas_object_del(cur->obj);
495 cur->obj = NULL;
496 }
497 _elm_cursor_cur_set(cur);
498}
499
500
501EAPI Eina_Bool
502elm_object_cursor_theme_search_enabled_get(const Evas_Object *obj)
503{
504 ELM_CURSOR_GET_OR_RETURN(cur, obj, EINA_FALSE);
505 return cur->engine_only;
506}
diff --git a/libraries/elementary/src/lib/els_icon.c b/libraries/elementary/src/lib/els_icon.c
new file mode 100644
index 0000000..9cd74bb
--- /dev/null
+++ b/libraries/elementary/src/lib/els_icon.c
@@ -0,0 +1,842 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_icon.h"
4
5#ifdef _WIN32
6# define FMT_SIZE_T "%Iu"
7#else
8# define FMT_SIZE_T "%zu"
9#endif
10
11typedef struct _Smart_Data Smart_Data;
12
13struct _Smart_Data
14{
15 Evas_Coord x, y, w, h;
16 Evas_Object *obj;
17 Evas_Object *prev;
18 int size;
19 double scale;
20 Eina_Bool fill_inside : 1;
21 Eina_Bool scale_up : 1;
22 Eina_Bool scale_down : 1;
23 Eina_Bool preloading : 1;
24 Eina_Bool show : 1;
25 Eina_Bool edit : 1;
26 Eina_Bool edje : 1;
27 Eina_Bool aspect_fixed: 1;
28 Elm_Image_Orient orient;
29};
30
31/* local subsystem functions */
32static void _smart_reconfigure(Smart_Data *sd);
33static void _smart_init(void);
34static void _smart_add(Evas_Object *obj);
35static void _smart_del(Evas_Object *obj);
36static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
37static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
38static void _smart_show(Evas_Object *obj);
39static void _smart_hide(Evas_Object *obj);
40static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
41static void _smart_clip_set(Evas_Object *obj, Evas_Object * clip);
42static void _smart_clip_unset(Evas_Object *obj);
43
44static void _els_smart_icon_flip_horizontal(Smart_Data *sd);
45static void _els_smart_icon_flip_vertical(Smart_Data *sd);
46static void _els_smart_icon_rotate_180(Smart_Data *sd);
47static Eina_Bool _els_smart_icon_dropcb(void *,Evas_Object *, Elm_Selection_Data *);
48
49/* local subsystem globals */
50static Evas_Smart *_e_smart = NULL;
51
52/* externally accessible functions */
53Evas_Object *
54_els_smart_icon_add(Evas *evas)
55{
56 _smart_init();
57 return evas_object_smart_add(evas, _e_smart);
58}
59
60static void
61_preloaded(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event __UNUSED__)
62{
63 Smart_Data *sd = data;
64
65 sd->preloading = EINA_FALSE;
66 if (obj == sd->obj)
67 {
68 if (sd->show)
69 evas_object_show(sd->obj);
70 }
71 if (sd->prev) evas_object_del(sd->prev);
72 sd->prev = NULL;
73}
74
75static void
76_els_smart_icon_file_helper(Evas_Object *obj)
77{
78 Smart_Data *sd;
79 Evas_Object *pclip;
80
81 sd = evas_object_smart_data_get(obj);
82 /* smart code here */
83 if (sd->prev) evas_object_del(sd->prev);
84 pclip = evas_object_clip_get(sd->obj);
85 if (sd->obj) sd->prev = sd->obj;
86 sd->obj = evas_object_image_add(evas_object_evas_get(obj));
87 evas_object_image_load_orientation_set(sd->obj, EINA_TRUE);
88 evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED,
89 _preloaded, sd);
90 evas_object_smart_member_add(sd->obj, obj);
91 if (sd->prev) evas_object_smart_member_add(sd->prev, obj);
92 evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC);
93 evas_object_clip_set(sd->obj, pclip);
94
95 sd->edje = EINA_FALSE;
96
97 if (!sd->size)
98 evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
99}
100
101Eina_Bool
102_els_smart_icon_memfile_set(Evas_Object *obj, const void *img, size_t size, const char *format, const char *key)
103{
104 Smart_Data *sd;
105
106 sd = evas_object_smart_data_get(obj);
107 if (!sd) return EINA_FALSE;
108 _els_smart_icon_file_helper(obj);
109
110 evas_object_image_memfile_set(sd->obj, (void*)img, size, (char*)format, (char*)key);
111 sd->preloading = EINA_TRUE;
112 sd->show = EINA_TRUE;
113 evas_object_hide(sd->obj);
114 evas_object_image_preload(sd->obj, EINA_FALSE);
115 if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
116 {
117 ERR("Things are going bad for some random " FMT_SIZE_T " byte chunk of memory (%p)", size, sd->obj);
118 return EINA_FALSE;
119 }
120 _smart_reconfigure(sd);
121 return EINA_TRUE;
122}
123
124Eina_Bool
125_els_smart_icon_file_key_set(Evas_Object *obj, const char *file, const char *key)
126{
127 Smart_Data *sd;
128 Evas_Coord w, h;
129
130 sd = evas_object_smart_data_get(obj);
131 if (!sd) return EINA_FALSE;
132 _els_smart_icon_file_helper(obj);
133
134 evas_object_image_file_set(sd->obj, file, key);
135 sd->preloading = EINA_TRUE;
136 sd->show = EINA_TRUE;
137 evas_object_hide(sd->obj);
138 _els_smart_icon_size_get(obj, &w, &h);
139 evas_object_image_load_size_set(sd->obj, w, h);
140 evas_object_image_preload(sd->obj, EINA_FALSE);
141 if (evas_object_image_load_error_get(sd->obj) != EVAS_LOAD_ERROR_NONE)
142 {
143 ERR("Things are going bad for '%s' (%p)", file, sd->obj);
144 return EINA_FALSE;
145 }
146 _smart_reconfigure(sd);
147 return EINA_TRUE;
148}
149
150void
151_els_smart_icon_preload_set(Evas_Object *obj, Eina_Bool disable)
152{
153 Smart_Data *sd;
154
155 sd = evas_object_smart_data_get(obj);
156 if ((!sd) || sd->edje) return;
157 evas_object_image_preload(sd->obj, disable);
158 sd->preloading = !disable;
159}
160
161Eina_Bool
162_els_smart_icon_file_edje_set(Evas_Object *obj, const char *file, const char *part)
163{
164 Smart_Data *sd;
165 Evas_Object *pclip;
166
167 sd = evas_object_smart_data_get(obj);
168 if (!sd) return EINA_FALSE;
169 /* smart code here */
170 if (sd->prev) evas_object_del(sd->prev);
171 sd->prev = NULL;
172
173 if (!sd->edje)
174 {
175 pclip = evas_object_clip_get(sd->obj);
176 if (sd->obj) evas_object_del(sd->obj);
177 sd->obj = edje_object_add(evas_object_evas_get(obj));
178 evas_object_smart_member_add(sd->obj, obj);
179 if (sd->show) evas_object_show(sd->obj);
180 evas_object_clip_set(sd->obj, pclip);
181 }
182 sd->edje = EINA_TRUE;
183 if (!edje_object_file_set(sd->obj, file, part))
184 return EINA_FALSE;
185 _smart_reconfigure(sd);
186 return EINA_TRUE;
187}
188
189void
190_els_smart_icon_file_get(const Evas_Object *obj, const char **file, const char **key)
191{
192 Smart_Data *sd = evas_object_smart_data_get(obj);
193 if (!sd) return;
194 if (sd->edje)
195 edje_object_file_get(sd->obj, file, key);
196 else
197 evas_object_image_file_get(sd->obj, file, key);
198}
199
200void
201_els_smart_icon_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth)
202{
203 Smart_Data *sd = evas_object_smart_data_get(obj);
204 if (!sd) return;
205 if (sd->edje)
206 return;
207 evas_object_image_smooth_scale_set(sd->obj, smooth);
208}
209
210Eina_Bool
211_els_smart_icon_smooth_scale_get(const Evas_Object *obj)
212{
213 Smart_Data *sd = evas_object_smart_data_get(obj);
214 if (!sd) return EINA_FALSE;
215 if (sd->edje)
216 return EINA_FALSE;
217 return evas_object_image_smooth_scale_get(sd->obj);
218}
219
220Evas_Object *
221_els_smart_icon_object_get(const Evas_Object *obj)
222{
223 Smart_Data *sd = evas_object_smart_data_get(obj);
224 if (!sd) return NULL;
225 return sd->obj;
226}
227
228void
229_els_smart_icon_size_get(const Evas_Object *obj, int *w, int *h)
230{
231 Smart_Data *sd;
232 int tw, th;
233 int cw, ch;
234 const char *type;
235
236 sd = evas_object_smart_data_get(obj);
237 if (!sd) return;
238 type = evas_object_type_get(sd->obj);
239 if (!type) return;
240 if (!strcmp(type, "edje"))
241 edje_object_size_min_get(sd->obj, &tw, &th);
242 else
243 evas_object_image_size_get(sd->obj, &tw, &th);
244 evas_object_geometry_get(sd->obj, NULL, NULL, &cw, &ch);
245 tw = tw > cw ? tw : cw;
246 th = th > ch ? th : ch;
247 tw = ((double)tw) * sd->scale;
248 th = ((double)th) * sd->scale;
249 if (w) *w = tw;
250 if (h) *h = th;
251}
252
253void
254_els_smart_icon_fill_inside_set(Evas_Object *obj, Eina_Bool fill_inside)
255{
256 Smart_Data *sd;
257
258 sd = evas_object_smart_data_get(obj);
259 if (!sd) return;
260 if (((sd->fill_inside) && (fill_inside)) ||
261 ((!sd->fill_inside) && (!fill_inside))) return;
262 sd->fill_inside = fill_inside;
263 _smart_reconfigure(sd);
264}
265
266Eina_Bool
267_els_smart_icon_fill_inside_get(const Evas_Object *obj)
268{
269 Smart_Data *sd = evas_object_smart_data_get(obj);
270 if (!sd) return EINA_FALSE;
271 return sd->fill_inside;
272}
273
274void
275_els_smart_icon_scale_up_set(Evas_Object *obj, Eina_Bool scale_up)
276{
277 Smart_Data *sd;
278
279 sd = evas_object_smart_data_get(obj);
280 if (!sd) return;
281 if (((sd->scale_up) && (scale_up)) ||
282 ((!sd->scale_up) && (!scale_up))) return;
283 sd->scale_up = scale_up;
284 _smart_reconfigure(sd);
285}
286
287Eina_Bool
288_els_smart_icon_scale_up_get(const Evas_Object *obj)
289{
290 Smart_Data *sd; sd = evas_object_smart_data_get(obj);
291 if (!sd) return EINA_FALSE;
292 return sd->scale_up;
293}
294
295void
296_els_smart_icon_scale_down_set(Evas_Object *obj, Eina_Bool scale_down)
297{
298 Smart_Data *sd;
299
300 sd = evas_object_smart_data_get(obj);
301 if (!sd) return;
302 if (((sd->scale_down) && (scale_down)) ||
303 ((!sd->scale_down) && (!scale_down))) return;
304 sd->scale_down = scale_down;
305 _smart_reconfigure(sd);
306}
307
308Eina_Bool
309_els_smart_icon_scale_down_get(const Evas_Object *obj)
310{
311 Smart_Data *sd; sd = evas_object_smart_data_get(obj);
312 if (!sd) return EINA_FALSE;
313 return sd->scale_up;
314}
315
316void
317_els_smart_icon_scale_size_set(Evas_Object *obj, int size)
318{
319 Smart_Data *sd;
320
321 sd = evas_object_smart_data_get(obj);
322 if (!sd) return;
323 sd->size = size;
324 if (!sd->obj) return;
325 if (sd->edje)
326 return;
327 evas_object_image_load_size_set(sd->obj, sd->size, sd->size);
328}
329
330int
331_els_smart_icon_scale_size_get(const Evas_Object *obj)
332{
333 Smart_Data *sd; sd = evas_object_smart_data_get(obj);
334 if (!sd) return 0;
335 return sd->size;
336}
337
338void
339_els_smart_icon_scale_set(Evas_Object *obj, double scale)
340{
341 Smart_Data *sd = evas_object_smart_data_get(obj);
342 if (!sd) return;
343 sd->scale = scale;
344 _smart_reconfigure(sd);
345}
346
347double
348_els_smart_icon_scale_get(const Evas_Object *obj)
349{
350 Smart_Data *sd; sd = evas_object_smart_data_get(obj);
351 if (!sd) return 0.0;
352 return sd->scale;
353}
354
355void
356_els_smart_icon_orient_set(Evas_Object *obj, Elm_Image_Orient orient)
357{
358 Smart_Data *sd;
359 unsigned int *data, *data2 = NULL, *to, *from;
360 int x, y, w, hw, iw, ih;
361
362 sd = evas_object_smart_data_get(obj);
363 if (!sd) return;
364 if (sd->edje)
365 return;
366
367 switch (orient)
368 {
369 case ELM_IMAGE_FLIP_HORIZONTAL:
370 _els_smart_icon_flip_horizontal(sd);
371 return;
372 case ELM_IMAGE_FLIP_VERTICAL:
373 _els_smart_icon_flip_vertical(sd);
374 return;
375 case ELM_IMAGE_ROTATE_180:
376 _els_smart_icon_rotate_180(sd);
377 return;
378 default:
379 break;
380 }
381
382 evas_object_image_size_get(sd->obj, &iw, &ih);
383 /* we need separate destination memory if we want to rotate 90 or 270 degree */
384 evas_object_image_data_copy_set(sd->obj, data2);
385 if (!data2) return;
386
387 w = ih;
388 ih = iw;
389 iw = w;
390 hw = w * ih;
391
392 evas_object_image_size_set(sd->obj, iw, ih);
393 data = evas_object_image_data_get(sd->obj, EINA_TRUE);
394
395 switch (orient)
396 {
397 case ELM_IMAGE_FLIP_TRANSPOSE:
398 to = data;
399 hw = -hw + 1;
400 break;
401 case ELM_IMAGE_FLIP_TRANSVERSE:
402 to = data + hw - 1;
403 w = -w;
404 hw = hw - 1;
405 break;
406 case ELM_IMAGE_ROTATE_90:
407 to = data + w - 1;
408 hw = -hw - 1;
409 break;
410 case ELM_IMAGE_ROTATE_270:
411 to = data + hw - w;
412 w = -w;
413 hw = hw + 1;
414 break;
415 default:
416 ERR("unknown orient %d", orient);
417 evas_object_image_data_set(sd->obj, data); // give it back
418 if (data2) free(data2);
419 return;
420 }
421 from = data2;
422 for (x = iw; --x >= 0;)
423 {
424 for (y = ih; --y >= 0;)
425 {
426 *to = *from;
427 from++;
428 to += w;
429 }
430 to += hw;
431 }
432 sd->orient = orient;
433 if (data2) free(data2);
434 evas_object_image_data_set(sd->obj, data);
435 evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
436 _smart_reconfigure(sd);
437}
438
439Elm_Image_Orient
440_els_smart_icon_orient_get(const Evas_Object *obj)
441{
442 Smart_Data *sd; sd = evas_object_smart_data_get(obj);
443 if (!sd) return 0;
444 return sd->orient;
445}
446
447/**
448 * Turns on editing through drag and drop and copy and paste.
449 */
450void
451_els_smart_icon_edit_set(Evas_Object *obj, Eina_Bool edit, Evas_Object *parent)
452{
453 Smart_Data *sd = evas_object_smart_data_get(obj);
454 if (!sd) return;
455
456 if (sd->edje)
457 {
458 printf("No editing edje objects yet (ever)\n");
459 return;
460 }
461
462 /* Unfortunately eina bool is not a bool, but a char */
463 if (edit == sd->edit) return;
464
465 sd->edit = edit;
466
467 if (sd->edit)
468 elm_drop_target_add(obj, ELM_SEL_FORMAT_IMAGE, _els_smart_icon_dropcb,
469 parent);
470 else
471 elm_drop_target_del(obj);
472}
473
474Eina_Bool
475_els_smart_icon_edit_get(const Evas_Object *obj)
476{
477 Smart_Data *sd; sd = evas_object_smart_data_get(obj);
478 if (!sd) return EINA_FALSE;
479 return sd->edit;
480}
481
482Evas_Object *
483_els_smart_icon_edje_get(Evas_Object *obj)
484{
485 Smart_Data *sd = evas_object_smart_data_get(obj);
486 if (!sd) return NULL;
487 if (!sd->edje) return NULL;
488 return sd->obj;
489}
490
491void
492_els_smart_icon_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed)
493{
494 Smart_Data *sd;
495
496 sd = evas_object_smart_data_get(obj);
497 if (!sd) return;
498
499 fixed = !!fixed;
500 if (sd->aspect_fixed == fixed) return;
501 sd->aspect_fixed = fixed;
502 _smart_reconfigure(sd);
503}
504
505Eina_Bool
506_els_smart_icon_aspect_fixed_get(const Evas_Object *obj)
507{
508 Smart_Data *sd;
509
510 sd = evas_object_smart_data_get(obj);
511 if (!sd) return EINA_FALSE;
512 return sd->aspect_fixed;
513}
514
515/* local subsystem globals */
516static void
517_smart_reconfigure(Smart_Data *sd)
518{
519 Evas_Coord x, y, w, h;
520 const char *type;
521
522 if (!sd->obj) return;
523
524 w = sd->w;
525 h = sd->h;
526
527 type = evas_object_type_get(sd->obj);
528 if (!type) return;
529 if (!strcmp(type, "edje"))
530 {
531 x = sd->x;
532 y = sd->y;
533 evas_object_move(sd->obj, x, y);
534 evas_object_resize(sd->obj, w, h);
535 }
536 else
537 {
538 int iw = 0, ih = 0;
539 double alignh = 0.5, alignv = 0.5;
540 Evas_Object *parent;
541
542 evas_object_image_size_get(sd->obj, &iw, &ih);
543
544 iw = ((double)iw) * sd->scale;
545 ih = ((double)ih) * sd->scale;
546
547 if (iw < 1) iw = 1;
548 if (ih < 1) ih = 1;
549
550 if (sd->aspect_fixed)
551 {
552 h = ((double)ih * w) / (double)iw;
553 if (sd->fill_inside)
554 {
555 if (h > sd->h)
556 {
557 h = sd->h;
558 w = ((double)iw * h) / (double)ih;
559 }
560 }
561 else
562 {
563 if (h < sd->h)
564 {
565 h = sd->h;
566 w = ((double)iw * h) / (double)ih;
567 }
568 }
569 }
570 if (!sd->scale_up)
571 {
572 if (w > iw) w = iw;
573 if (h > ih) h = ih;
574 }
575 if (!sd->scale_down)
576 {
577 if (w < iw) w = iw;
578 if (h < ih) h = ih;
579 }
580 parent = elm_widget_parent_widget_get(sd->obj);
581 if (parent)
582 evas_object_size_hint_align_get(parent, &alignh, &alignv);
583 if (alignh == EVAS_HINT_FILL) alignh = 0.5;
584 if (alignv == EVAS_HINT_FILL) alignv = 0.5;
585 x = sd->x + ((sd->w - w) * alignh);
586 y = sd->y + ((sd->h - h) * alignv);
587 evas_object_move(sd->obj, x, y);
588 evas_object_image_fill_set(sd->obj, 0, 0, w, h);
589 evas_object_resize(sd->obj, w, h);
590 }
591}
592
593static void
594_smart_init(void)
595{
596 if (_e_smart) return;
597 {
598 static const Evas_Smart_Class sc =
599 {
600 "e_icon",
601 EVAS_SMART_CLASS_VERSION,
602 _smart_add,
603 _smart_del,
604 _smart_move,
605 _smart_resize,
606 _smart_show,
607 _smart_hide,
608 _smart_color_set,
609 _smart_clip_set,
610 _smart_clip_unset,
611 NULL,
612 NULL,
613 NULL,
614 NULL,
615 NULL,
616 NULL,
617 NULL
618 };
619 _e_smart = evas_smart_class_new(&sc);
620 }
621}
622
623static void
624_smart_add(Evas_Object *obj)
625{
626 Smart_Data *sd;
627
628 sd = calloc(1, sizeof(Smart_Data));
629 if (!sd) return;
630 sd->obj = evas_object_image_add(evas_object_evas_get(obj));
631 sd->prev = NULL;
632 evas_object_image_scale_hint_set(sd->obj, EVAS_IMAGE_SCALE_HINT_STATIC);
633 sd->x = 0;
634 sd->y = 0;
635 sd->w = 0;
636 sd->h = 0;
637 sd->fill_inside = EINA_TRUE;
638 sd->scale_up = EINA_TRUE;
639 sd->scale_down = EINA_TRUE;
640 sd->aspect_fixed = EINA_TRUE;
641 sd->size = 64;
642 sd->scale = 1.0;
643 evas_object_smart_member_add(sd->obj, obj);
644 evas_object_smart_data_set(obj, sd);
645 evas_object_event_callback_add(sd->obj, EVAS_CALLBACK_IMAGE_PRELOADED,
646 _preloaded, sd);
647}
648
649static void
650_smart_del(Evas_Object *obj)
651{
652 Smart_Data *sd;
653
654 sd = evas_object_smart_data_get(obj);
655 if (!sd) return;
656 evas_object_del(sd->obj);
657 if (sd->prev) evas_object_del(sd->prev);
658 free(sd);
659}
660
661static void
662_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
663{
664 Smart_Data *sd;
665
666 sd = evas_object_smart_data_get(obj);
667 if (!sd) return;
668 if ((sd->x == x) && (sd->y == y)) return;
669 sd->x = x;
670 sd->y = y;
671 _smart_reconfigure(sd);
672}
673
674static void
675_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
676{
677 Smart_Data *sd;
678
679 sd = evas_object_smart_data_get(obj);
680 if (!sd) return;
681 if ((sd->w == w) && (sd->h == h)) return;
682 sd->w = w;
683 sd->h = h;
684 _smart_reconfigure(sd);
685}
686
687static void
688_smart_show(Evas_Object *obj)
689{
690 Smart_Data *sd;
691
692 sd = evas_object_smart_data_get(obj);
693 if (!sd) return;
694 sd->show = EINA_TRUE;
695 if (!sd->preloading)
696 {
697 evas_object_show(sd->obj);
698 if (sd->prev) evas_object_del(sd->prev);
699 sd->prev = NULL;
700 }
701}
702
703static void
704_smart_hide(Evas_Object *obj)
705{
706 Smart_Data *sd;
707
708 sd = evas_object_smart_data_get(obj);
709 if (!sd) return;
710 sd->show = EINA_FALSE;
711 evas_object_hide(sd->obj);
712 if (sd->prev) evas_object_del(sd->prev);
713 sd->prev = NULL;
714}
715
716static void
717_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
718{
719 Smart_Data *sd;
720
721 sd = evas_object_smart_data_get(obj);
722 if (!sd) return;
723 evas_object_color_set(sd->obj, r, g, b, a);
724 if (sd->prev) evas_object_color_set(sd->prev, r, g, b, a);
725}
726
727static void
728_smart_clip_set(Evas_Object *obj, Evas_Object * clip)
729{
730 Smart_Data *sd;
731
732 sd = evas_object_smart_data_get(obj);
733 if (!sd) return;
734 evas_object_clip_set(sd->obj, clip);
735 if (sd->prev) evas_object_clip_set(sd->prev, clip);
736}
737
738static void
739_smart_clip_unset(Evas_Object *obj)
740{
741 Smart_Data *sd;
742
743 sd = evas_object_smart_data_get(obj);
744 if (!sd) return;
745 evas_object_clip_unset(sd->obj);
746 if (sd->prev) evas_object_clip_unset(sd->prev);
747}
748
749static void
750_els_smart_icon_flip_horizontal(Smart_Data *sd)
751{
752 unsigned int *data;
753 unsigned int *p1, *p2, tmp;
754 int x, y, iw, ih;
755
756 evas_object_image_size_get(sd->obj, &iw, &ih);
757 data = evas_object_image_data_get(sd->obj, EINA_TRUE);
758
759 for (y = 0; y < ih; y++)
760 {
761 p1 = data + (y * iw);
762 p2 = data + ((y + 1) * iw) - 1;
763 for (x = 0; x < (iw >> 1); x++)
764 {
765 tmp = *p1;
766 *p1 = *p2;
767 *p2 = tmp;
768 p1++;
769 p2--;
770 }
771 }
772
773 evas_object_image_data_set(sd->obj, data);
774 evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
775 _smart_reconfigure(sd);
776}
777
778static void
779_els_smart_icon_flip_vertical(Smart_Data *sd)
780{
781 unsigned int *data;
782 unsigned int *p1, *p2, tmp;
783 int x, y, iw, ih;
784
785 evas_object_image_size_get(sd->obj, &iw, &ih);
786 data = evas_object_image_data_get(sd->obj, EINA_TRUE);
787
788 for (y = 0; y < (ih >> 1); y++)
789 {
790 p1 = data + (y * iw);
791 p2 = data + ((ih - 1 - y) * iw);
792 for (x = 0; x < iw; x++)
793 {
794 tmp = *p1;
795 *p1 = *p2;
796 *p2 = tmp;
797 p1++;
798 p2++;
799 }
800 }
801
802 evas_object_image_data_set(sd->obj, data);
803 evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
804 _smart_reconfigure(sd);
805}
806
807static void
808_els_smart_icon_rotate_180(Smart_Data *sd)
809{
810 unsigned int *data;
811 unsigned int *p1, *p2, tmp;
812 int x, hw, iw, ih;
813
814 evas_object_image_size_get(sd->obj, &iw, &ih);
815 data = evas_object_image_data_get(sd->obj, 1);
816
817 hw = iw * ih;
818 x = (hw / 2);
819 p1 = data;
820 p2 = data + hw - 1;
821 for (; --x > 0;)
822 {
823 tmp = *p1;
824 *p1 = *p2;
825 *p2 = tmp;
826 p1++;
827 p2--;
828 }
829 evas_object_image_data_set(sd->obj, data);
830 evas_object_image_data_update_add(sd->obj, 0, 0, iw, ih);
831 _smart_reconfigure(sd);
832}
833
834static Eina_Bool
835_els_smart_icon_dropcb(void *elmobj,Evas_Object *obj, Elm_Selection_Data *drop)
836{
837 _els_smart_icon_file_key_set(obj, drop->data, NULL);
838 evas_object_smart_callback_call(elmobj, "drop", drop->data);
839
840 return EINA_TRUE;
841}
842/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0 :*/
diff --git a/libraries/elementary/src/lib/els_icon.h b/libraries/elementary/src/lib/els_icon.h
new file mode 100644
index 0000000..787c5bf
--- /dev/null
+++ b/libraries/elementary/src/lib/els_icon.h
@@ -0,0 +1,27 @@
1Evas_Object *_els_smart_icon_add(Evas *evas);
2Eina_Bool _els_smart_icon_memfile_set(Evas_Object *obj, const void *file, size_t size, const char *format, const char *key);
3Eina_Bool _els_smart_icon_file_key_set(Evas_Object *obj, const char *file, const char *key);
4Eina_Bool _els_smart_icon_file_edje_set(Evas_Object *obj, const char *file, const char *part);
5void _els_smart_icon_file_get(const Evas_Object *obj, const char **file, const char **key);
6void _els_smart_icon_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth);
7Eina_Bool _els_smart_icon_smooth_scale_get(const Evas_Object *obj);
8Evas_Object *_els_smart_icon_object_get(const Evas_Object *obj);
9void _els_smart_icon_size_get(const Evas_Object *obj, int *w, int *h);
10void _els_smart_icon_fill_inside_set(Evas_Object *obj, Eina_Bool fill_inside);
11Eina_Bool _els_smart_icon_fill_inside_get(const Evas_Object *obj);
12void _els_smart_icon_scale_up_set(Evas_Object *obj, Eina_Bool scale_up);
13Eina_Bool _els_smart_icon_scale_up_get(const Evas_Object *obj);
14void _els_smart_icon_scale_down_set(Evas_Object *obj, Eina_Bool scale_down);
15Eina_Bool _els_smart_icon_scale_down_get(const Evas_Object *obj);
16void _els_smart_icon_scale_size_set(Evas_Object *obj, int size);
17int _els_smart_icon_scale_size_get(const Evas_Object *obj);
18void _els_smart_icon_scale_set(Evas_Object *obj, double scale);
19double _els_smart_icon_scale_get(const Evas_Object *obj);
20void _els_smart_icon_orient_set(Evas_Object *obj, Elm_Image_Orient orient);
21Elm_Image_Orient _els_smart_icon_orient_get(const Evas_Object *obj);
22void _els_smart_icon_edit_set(Evas_Object *obj, Eina_Bool, Evas_Object *parent);
23Eina_Bool _els_smart_icon_edit_get(const Evas_Object *obj);
24Evas_Object *_els_smart_icon_edje_get(Evas_Object *obj);
25void _els_smart_icon_aspect_fixed_set(Evas_Object *obj, Eina_Bool fixed);
26Eina_Bool _els_smart_icon_aspect_fixed_get(const Evas_Object *obj);
27void _els_smart_icon_preload_set(Evas_Object *obj, Eina_Bool disable);
diff --git a/libraries/elementary/src/lib/els_pan.c b/libraries/elementary/src/lib/els_pan.c
new file mode 100644
index 0000000..4e02b3d
--- /dev/null
+++ b/libraries/elementary/src/lib/els_pan.c
@@ -0,0 +1,332 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#define SMART_NAME "elm_pan"
5#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)))
6#define INTERNAL_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
7typedef struct _Smart_Data Smart_Data;
8
9struct _Smart_Data
10{
11 Evas_Object *smart_obj;
12 Evas_Object *child_obj;
13 Evas_Coord x, y, w, h;
14 Evas_Coord child_w, child_h, px, py;
15 double gravity_x, gravity_y;
16 Evas_Coord prev_cw, prev_ch, delta_posx, delta_posy;
17};
18
19/* local subsystem functions */
20static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
21static void _smart_child_resize_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
22
23static void _smart_reconfigure(Smart_Data *sd);
24static void _smart_add(Evas_Object *obj);
25static void _smart_del(Evas_Object *obj);
26static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
27static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
28static void _smart_show(Evas_Object *obj);
29static void _smart_hide(Evas_Object *obj);
30static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
31static void _smart_clip_set(Evas_Object *obj, Evas_Object * clip);
32static void _smart_clip_unset(Evas_Object *obj);
33static void _smart_init(void);
34
35/* local subsystem globals */
36static Evas_Smart *_smart = NULL;
37
38/* externally accessible functions */
39Evas_Object *
40_elm_smart_pan_add(Evas *evas)
41{
42 _smart_init();
43 return evas_object_smart_add(evas, _smart);
44}
45
46void
47_elm_smart_pan_child_set(Evas_Object *obj, Evas_Object *child)
48{
49 API_ENTRY return;
50 if (child == sd->child_obj) return;
51 if (sd->child_obj)
52 {
53 evas_object_clip_unset(sd->child_obj);
54 evas_object_smart_member_del(sd->child_obj);
55 evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_FREE, _smart_child_del_hook, sd);
56 evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_RESIZE, _smart_child_resize_hook, sd);
57 sd->child_obj = NULL;
58 }
59 if (child)
60 {
61 Evas_Coord w, h;
62 int r, g, b, a;
63
64 sd->child_obj = child;
65 evas_object_smart_member_add(sd->child_obj, sd->smart_obj);
66 evas_object_geometry_get(sd->child_obj, NULL, NULL, &w, &h);
67 sd->child_w = w;
68 sd->child_h = h;
69 evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _smart_child_del_hook, sd);
70 evas_object_event_callback_add(child, EVAS_CALLBACK_RESIZE, _smart_child_resize_hook, sd);
71 evas_object_color_get(sd->smart_obj, &r, &g, &b, &a);
72 evas_object_color_set(sd->child_obj, r, g, b, a);
73 evas_object_clip_set(sd->child_obj, evas_object_clip_get(sd->smart_obj));
74 if (evas_object_visible_get(sd->smart_obj)) evas_object_show(sd->child_obj);
75 else evas_object_hide(sd->child_obj);
76 _smart_reconfigure(sd);
77 }
78 evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
79}
80
81Evas_Object *
82_elm_smart_pan_child_get(Evas_Object *obj)
83{
84 API_ENTRY return NULL;
85 return sd->child_obj;
86}
87
88void
89_elm_smart_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
90{
91 API_ENTRY return;
92 // if (x > (sd->child_w - sd->w)) x = sd->child_w - sd->w;
93 // if (y > (sd->child_h - sd->h)) y = sd->child_h - sd->h;
94 // if (x < 0) x = 0;
95 // if (y < 0) y = 0;
96 if ((x == sd->px) && (y == sd->py)) return;
97 sd->px = x;
98 sd->py = y;
99 _smart_reconfigure(sd);
100 evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
101}
102
103void
104_elm_smart_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
105{
106 API_ENTRY return;
107 if (x) *x = sd->px;
108 if (y) *y = sd->py;
109}
110
111void
112_elm_smart_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
113{
114 API_ENTRY return;
115 if (x)
116 {
117 if (sd->w < sd->child_w) *x = sd->child_w - sd->w;
118 else *x = 0;
119 }
120 if (y)
121 {
122 if (sd->h < sd->child_h) *y = sd->child_h - sd->h;
123 else *y = 0;
124 }
125}
126
127void
128_elm_smart_pan_min_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
129{
130 API_ENTRY return;
131 if (x)
132 *x = 0;
133 if (y)
134 *y = 0;
135}
136
137void
138_elm_smart_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
139{
140 API_ENTRY return;
141 if (w) *w = sd->child_w;
142 if (h) *h = sd->child_h;
143}
144
145void
146_elm_smart_pan_gravity_set(Evas_Object *obj, double x, double y)
147{
148 API_ENTRY return;
149 sd->gravity_x = x;
150 sd->gravity_y = y;
151 sd->prev_cw = sd->child_w;
152 sd->prev_ch = sd->child_h;
153 sd->delta_posx = 0;
154 sd->delta_posy = 0;
155}
156
157void
158_elm_smart_pan_gravity_get(Evas_Object *obj, double *x, double *y)
159{
160 API_ENTRY return;
161 if (x) *x = sd->gravity_x;
162 if (y) *y = sd->gravity_y;
163}
164
165/* local subsystem functions */
166static void
167_smart_child_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
168{
169 Smart_Data *sd;
170
171 sd = data;
172 sd->child_obj = NULL;
173 evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
174}
175
176static void
177_smart_child_resize_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
178{
179 Smart_Data *sd;
180 Evas_Coord w, h;
181
182 sd = data;
183 evas_object_geometry_get(sd->child_obj, NULL, NULL, &w, &h);
184 if ((w != sd->child_w) || (h != sd->child_h))
185 {
186 sd->child_w = w;
187 sd->child_h = h;
188 _smart_reconfigure(sd);
189 }
190 evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
191}
192
193static void
194_smart_reconfigure(Smart_Data *sd)
195{
196 if (sd->gravity_x || sd->gravity_y)
197 {
198 if ((!sd->px) && (!sd->py))
199 {
200 sd->px = sd->delta_posx*sd->gravity_x;
201 sd->py = sd->delta_posy*sd->gravity_y;
202 }
203 sd->delta_posx += sd->child_w - sd->prev_cw;
204 sd->prev_cw = sd->child_w;
205 sd->delta_posy += sd->child_h - sd->prev_ch;
206 sd->prev_ch = sd->child_h;
207
208 evas_object_move(sd->child_obj, sd->x - sd->px, sd->y - sd->py);
209 sd->px = sd->delta_posx*sd->gravity_x;
210 sd->py = sd->delta_posy*sd->gravity_y;
211
212 }
213 else
214 evas_object_move(sd->child_obj, sd->x - sd->px, sd->y - sd->py);
215}
216
217static void
218_smart_add(Evas_Object *obj)
219{
220 Smart_Data *sd;
221
222 sd = calloc(1, sizeof(Smart_Data));
223 if (!sd) return;
224 sd->smart_obj = obj;
225 sd->x = 0;
226 sd->y = 0;
227 sd->w = 0;
228 sd->h = 0;
229 sd->gravity_x = 0.0;
230 sd->gravity_y = 0.0;
231 evas_object_smart_data_set(obj, sd);
232}
233
234static void
235_smart_del(Evas_Object *obj)
236{
237 INTERNAL_ENTRY;
238 _elm_smart_pan_child_set(obj, NULL);
239 free(sd);
240}
241
242static void
243_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
244{
245 INTERNAL_ENTRY;
246 sd->x = x;
247 sd->y = y;
248 _smart_reconfigure(sd);
249}
250
251static void
252_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
253{
254 INTERNAL_ENTRY;
255 sd->w = w;
256 sd->h = h;
257 _smart_reconfigure(sd);
258 evas_object_smart_callback_call(sd->smart_obj, "changed", NULL);
259}
260
261static void
262_smart_show(Evas_Object *obj)
263{
264 INTERNAL_ENTRY;
265 if (sd->child_obj)
266 evas_object_show(sd->child_obj);
267}
268
269static void
270_smart_hide(Evas_Object *obj)
271{
272 INTERNAL_ENTRY;
273 if (sd->child_obj)
274 evas_object_hide(sd->child_obj);
275}
276
277static void
278_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
279{
280 INTERNAL_ENTRY;
281 if (sd->child_obj)
282 evas_object_color_set(sd->child_obj, r, g, b, a);
283}
284
285static void
286_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
287{
288 INTERNAL_ENTRY;
289 if (sd->child_obj)
290 evas_object_clip_set(sd->child_obj, clip);
291}
292
293static void
294_smart_clip_unset(Evas_Object *obj)
295{
296 INTERNAL_ENTRY;
297 if (sd->child_obj)
298 evas_object_clip_unset(sd->child_obj);
299}
300
301/* never need to touch this */
302
303static void
304_smart_init(void)
305{
306 if (_smart) return;
307 {
308 static const Evas_Smart_Class sc =
309 {
310 SMART_NAME,
311 EVAS_SMART_CLASS_VERSION,
312 _smart_add,
313 _smart_del,
314 _smart_move,
315 _smart_resize,
316 _smart_show,
317 _smart_hide,
318 _smart_color_set,
319 _smart_clip_set,
320 _smart_clip_unset,
321 NULL,
322 NULL,
323 NULL,
324 NULL,
325 NULL,
326 NULL,
327 NULL
328 };
329 _smart = evas_smart_class_new(&sc);
330 }
331}
332
diff --git a/libraries/elementary/src/lib/els_pan.h b/libraries/elementary/src/lib/els_pan.h
new file mode 100644
index 0000000..568e74f
--- /dev/null
+++ b/libraries/elementary/src/lib/els_pan.h
@@ -0,0 +1,10 @@
1Evas_Object *_elm_smart_pan_add(Evas *evas);
2void _elm_smart_pan_child_set(Evas_Object *obj, Evas_Object *child);
3Evas_Object *_elm_smart_pan_child_get(Evas_Object *obj);
4void _elm_smart_pan_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
5void _elm_smart_pan_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
6void _elm_smart_pan_max_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
7void _elm_smart_pan_min_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
8void _elm_smart_pan_child_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
9void _elm_smart_pan_gravity_set(Evas_Object *obj, double x, double y);
10void _elm_smart_pan_gravity_get(Evas_Object *obj, double *x, double *y);
diff --git a/libraries/elementary/src/lib/els_scroller.c b/libraries/elementary/src/lib/els_scroller.c
new file mode 100644
index 0000000..82b2b8e
--- /dev/null
+++ b/libraries/elementary/src/lib/els_scroller.c
@@ -0,0 +1,3000 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3#include "els_scroller.h"
4#include "els_pan.h"
5
6#define SMART_NAME "els_scroller"
7#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)))
8#define INTERNAL_ENTRY Smart_Data *sd; sd = evas_object_smart_data_get(obj); if (!sd) return;
9typedef struct _Smart_Data Smart_Data;
10
11#define EVTIME 1
12//#define SCROLLDBG 1
13
14struct _Smart_Data
15{
16 Evas_Coord x, y, w, h;
17 Evas_Coord wx, wy, ww, wh; /* Last "wanted" geometry */
18
19 Evas_Object *smart_obj;
20 Evas_Object *child_obj;
21 Evas_Object *pan_obj;
22 Evas_Object *edje_obj;
23 Evas_Object *event_obj;
24
25 Evas_Object *widget;
26
27 Elm_Smart_Scroller_Policy hbar_flags, vbar_flags;
28
29 struct
30 {
31 Evas_Coord x, y;
32 Evas_Coord sx, sy;
33 Evas_Coord dx, dy;
34 Evas_Coord pdx, pdy;
35 Evas_Coord bx, by;
36 Evas_Coord ax, ay;
37 Evas_Coord bx0, by0;
38 Evas_Coord b0x, b0y;
39 Evas_Coord b2x, b2y;
40 struct
41 {
42 Evas_Coord x, y;
43 double timestamp, localtimestamp;
44 } history[60];
45 struct
46 {
47 double tadd, dxsum, dysum;
48 double est_timestamp_diff;
49 } hist;
50 double anim_start;
51 double anim_start2;
52 double anim_start3;
53 double onhold_vx, onhold_vy, onhold_tlast, onhold_vxe, onhold_vye;
54 double extra_time;
55 Evas_Coord hold_x, hold_y;
56 Ecore_Animator *hold_animator;
57 Ecore_Animator *onhold_animator;
58 Ecore_Animator *momentum_animator;
59 Ecore_Animator *bounce_x_animator;
60 Ecore_Animator *bounce_y_animator;
61 Evas_Coord locked_x, locked_y;
62 int hdir, vdir;
63 Eina_Bool now : 1;
64 Eina_Bool cancelled : 1;
65 Eina_Bool hold : 1;
66 Eina_Bool hold_parent : 1;
67 Eina_Bool want_dragged : 1;
68 Eina_Bool dragged : 1;
69 Eina_Bool dragged_began : 1;
70 Eina_Bool dir_x : 1;
71 Eina_Bool dir_y : 1;
72 Eina_Bool locked : 1;
73 Eina_Bool bounce_x_hold : 1;
74 Eina_Bool bounce_y_hold : 1;
75 Eina_Bool scroll : 1;
76 Eina_Bool want_reset : 1;
77 } down;
78
79 struct
80 {
81 Evas_Coord w, h;
82 Eina_Bool resized : 1;
83 } child;
84 struct
85 {
86 Evas_Coord x, y;
87 } step, page;
88
89 struct
90 {
91 void (*set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y);
92 void (*get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
93 void (*max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
94 void (*min_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
95 void (*child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
96 void (*gravity_set) (Evas_Object *obj, double x, double y);
97 void (*gravity_get) (Evas_Object *obj, double *x, double *y);
98 } pan_func;
99
100 struct
101 {
102 struct
103 {
104 Evas_Coord start, end;
105 double t_start, t_end;
106 Ecore_Animator *animator;
107 } x, y;
108 } scrollto;
109
110 double pagerel_h, pagerel_v;
111 Evas_Coord pagesize_h, pagesize_v;
112
113 Eina_Bool hbar_visible : 1;
114 Eina_Bool vbar_visible : 1;
115 Eina_Bool extern_pan : 1;
116 Eina_Bool one_dir_at_a_time : 1;
117 Eina_Bool hold : 1;
118 Eina_Bool freeze : 1;
119 Eina_Bool bouncemex : 1;
120 Eina_Bool bouncemey : 1;
121 Eina_Bool bounce_horiz : 1;
122 Eina_Bool bounce_vert : 1;
123 Eina_Bool momentum_animator_disabled :1;
124 Eina_Bool bounce_animator_disabled :1;
125 Eina_Bool is_mirrored : 1;
126 Eina_Bool wheel_disabled : 1;
127};
128
129/* local subsystem functions */
130static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
131static void _smart_pan_changed_hook(void *data, Evas_Object *obj, void *event_info);
132static void _smart_event_wheel(void *data, Evas *e, Evas_Object *obj, void *event_info);
133static void _smart_event_mouse_down(void *data, Evas *e, Evas_Object *obj, void *event_info);
134static Eina_Bool _smart_hold_animator(void *data);
135static Eina_Bool _smart_momentum_animator(void *data);
136static void _smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj, void *event_info);
137static Eina_Bool _smart_onhold_animator(void *data);
138static void _smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj, void *event_info);
139static void _smart_edje_drag_v_start(void *data, Evas_Object *obj, const char *emission, const char *source);
140static void _smart_edje_drag_v_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
141static void _smart_edje_drag_v(void *data, Evas_Object *obj, const char *emission, const char *source);
142static void _smart_edje_drag_h_start(void *data, Evas_Object *obj, const char *emission, const char *source);
143static void _smart_edje_drag_h_stop(void *data, Evas_Object *obj, const char *emission, const char *source);
144static void _smart_edje_drag_h(void *data, Evas_Object *obj, const char *emission, const char *source);
145static void _smart_scrollbar_read(Smart_Data *sd);
146static void _smart_scrollbar_reset(Smart_Data *sd);
147static int _smart_scrollbar_bar_h_visibility_adjust(Smart_Data *sd);
148static int _smart_scrollbar_bar_v_visibility_adjust(Smart_Data *sd);
149static void _smart_scrollbar_bar_visibility_adjust(Smart_Data *sd);
150static void _smart_scrollbar_size_adjust(Smart_Data *sd);
151static void _smart_reconfigure(Smart_Data *sd);
152static void _smart_add(Evas_Object *obj);
153static void _smart_del(Evas_Object *obj);
154static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
155static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
156static void _smart_show(Evas_Object *obj);
157static void _smart_hide(Evas_Object *obj);
158static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
159static void _smart_clip_set(Evas_Object *obj, Evas_Object *clip);
160static void _smart_clip_unset(Evas_Object *obj);
161static void _smart_init(void);
162
163static void _elm_smart_scroller_wanted_region_set(Evas_Object *obj);
164
165/* local subsystem globals */
166static Evas_Smart *_smart = NULL;
167
168/* externally accessible functions */
169Evas_Object *
170elm_smart_scroller_add(Evas *evas)
171{
172 _smart_init();
173 return evas_object_smart_add(evas, _smart);
174}
175
176static Evas_Coord
177_elm_smart_scroller_x_mirrored_get(Evas_Object *obj, Evas_Coord x)
178{
179 API_ENTRY return x;
180
181 Evas_Coord cw, ch, w, ret;
182 elm_smart_scroller_child_viewport_size_get(obj, &w, NULL);
183 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
184 ret = (cw - (x + w));
185 return (ret >= 0) ? ret : 0;
186}
187
188void
189elm_smart_scroller_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
190{
191 API_ENTRY return;
192 Evas_Coord wx;
193 if (sd->is_mirrored == mirrored)
194 return;
195
196 sd->is_mirrored = mirrored;
197 edje_object_mirrored_set(sd->edje_obj, mirrored);
198
199 if (sd->is_mirrored)
200 wx = _elm_smart_scroller_x_mirrored_get(sd->smart_obj, sd->wx);
201 else
202 wx = sd->wx;
203
204 elm_smart_scroller_child_pos_set(sd->smart_obj, wx, sd->wy);
205}
206
207void
208elm_smart_scroller_child_set(Evas_Object *obj, Evas_Object *child)
209{
210 Evas_Coord w, h;
211 Evas_Object *o;
212
213 API_ENTRY return;
214 if (sd->child_obj)
215 {
216 _elm_smart_pan_child_set(sd->pan_obj, NULL);
217 evas_object_event_callback_del_full(sd->child_obj, EVAS_CALLBACK_DEL, _smart_child_del_hook, sd);
218 }
219
220 sd->child_obj = child;
221 sd->wx = sd->wy = 0;
222 /* (-1) means want viewports size */
223 sd->ww = sd->wh = -1;
224 if (!child) return;
225
226 if (!sd->pan_obj)
227 {
228 o = _elm_smart_pan_add(evas_object_evas_get(obj));
229 sd->pan_obj = o;
230 evas_object_smart_callback_add(o, "changed", _smart_pan_changed_hook, sd);
231 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", o);
232 }
233
234 sd->pan_func.set = _elm_smart_pan_set;
235 sd->pan_func.get = _elm_smart_pan_get;
236 sd->pan_func.max_get = _elm_smart_pan_max_get;
237 sd->pan_func.min_get = _elm_smart_pan_min_get;
238 sd->pan_func.child_size_get = _elm_smart_pan_child_size_get;
239 sd->pan_func.gravity_set = _elm_smart_pan_gravity_set;
240 sd->pan_func.gravity_get = _elm_smart_pan_gravity_get;
241
242 evas_object_event_callback_add(child, EVAS_CALLBACK_DEL, _smart_child_del_hook, sd);
243 _elm_smart_pan_child_set(sd->pan_obj, child);
244 sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
245 sd->child.w = w;
246 sd->child.h = h;
247 _smart_scrollbar_size_adjust(sd);
248 _smart_scrollbar_reset(sd);
249}
250
251void
252elm_smart_scroller_extern_pan_set(Evas_Object *obj, Evas_Object *pan,
253 void (*pan_set) (Evas_Object *obj, Evas_Coord x, Evas_Coord y),
254 void (*pan_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
255 void (*pan_max_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
256 void (*pan_min_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y),
257 void (*pan_child_size_get) (Evas_Object *obj, Evas_Coord *x, Evas_Coord *y))
258{
259 API_ENTRY return;
260
261 elm_smart_scroller_child_set(obj, NULL);
262
263 if (sd->pan_obj)
264 {
265 evas_object_smart_callback_del(sd->pan_obj, "changed", _smart_pan_changed_hook);
266 }
267
268 if (sd->extern_pan)
269 {
270 if (sd->pan_obj)
271 {
272 edje_object_part_unswallow(sd->edje_obj, sd->pan_obj);
273 sd->pan_obj = NULL;
274 }
275 }
276 else
277 {
278 if (sd->pan_obj)
279 {
280 evas_object_del(sd->pan_obj);
281 sd->pan_obj = NULL;
282 }
283 }
284 if (!pan)
285 {
286 sd->extern_pan = EINA_FALSE;
287 return;
288 }
289
290 sd->pan_obj = pan;
291 sd->pan_func.set = pan_set;
292 sd->pan_func.get = pan_get;
293 sd->pan_func.max_get = pan_max_get;
294 sd->pan_func.min_get = pan_min_get;
295 sd->pan_func.child_size_get = pan_child_size_get;
296 sd->pan_func.gravity_set = _elm_smart_pan_gravity_set;
297 sd->pan_func.gravity_get = _elm_smart_pan_gravity_get;
298 sd->extern_pan = EINA_TRUE;
299 evas_object_smart_callback_add(sd->pan_obj, "changed", _smart_pan_changed_hook, sd);
300 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
301 evas_object_show(sd->pan_obj);
302}
303
304void
305elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *group)
306{
307 API_ENTRY return;
308
309 edje_object_file_set(sd->edje_obj, file, group);
310 if (sd->pan_obj)
311 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
312 sd->vbar_visible = !sd->vbar_visible;
313 sd->hbar_visible = !sd->hbar_visible;
314 _smart_scrollbar_bar_visibility_adjust(sd);
315 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
316 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
317 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
318 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
319 else
320 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,hbar", "elm");
321 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
322 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
323 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
324 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
325 else
326 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
327}
328
329Eina_Bool
330elm_smart_scroller_momentum_animator_disabled_get(Evas_Object *obj)
331{
332 API_ENTRY return EINA_FALSE;
333 return sd->momentum_animator_disabled;
334}
335
336void
337elm_smart_scroller_momentum_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
338{
339 API_ENTRY return;
340 sd->momentum_animator_disabled = disabled;
341 if (sd->momentum_animator_disabled)
342 {
343 if (sd->down.momentum_animator)
344 {
345 ecore_animator_del(sd->down.momentum_animator);
346 sd->down.momentum_animator = NULL;
347 if (sd->child.resized)
348 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
349 }
350 }
351}
352
353Eina_Bool
354elm_smart_scroller_bounce_animator_disabled_get(Evas_Object *obj)
355{
356 API_ENTRY return EINA_FALSE;
357 return sd->bounce_animator_disabled;
358}
359
360void
361elm_smart_scroller_bounce_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled)
362{
363 API_ENTRY return;
364 sd->bounce_animator_disabled = disabled;
365 if (sd->bounce_animator_disabled)
366 {
367 if (sd->scrollto.x.animator)
368 {
369 ecore_animator_del(sd->scrollto.x.animator);
370 sd->scrollto.x.animator = NULL;
371 }
372
373 if (sd->scrollto.y.animator)
374 {
375 ecore_animator_del(sd->scrollto.y.animator);
376 sd->scrollto.y.animator = NULL;
377 }
378 }
379}
380
381Eina_Bool
382elm_smart_scroller_wheel_disabled_get(Evas_Object *obj)
383{
384 API_ENTRY return EINA_FALSE;
385 return sd->wheel_disabled;
386}
387
388void
389elm_smart_scroller_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled)
390{
391 API_ENTRY return;
392 if ((!sd->wheel_disabled) && (disabled))
393 evas_object_event_callback_del_full(sd->event_obj, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
394 else if ((sd->wheel_disabled) && (!disabled))
395 evas_object_event_callback_add(sd->event_obj, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
396 sd->wheel_disabled = disabled;
397}
398
399/* Update the wanted coordinates according to the x, y passed
400 * widget directionality, child size and etc. */
401static void
402_update_wanted_coordinates(Smart_Data *sd, Evas_Coord x, Evas_Coord y)
403{
404 Evas_Coord cw, ch;
405
406 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
407
408 /* Update wx/y/w/h - and if the requested positions aren't legal
409 * adjust a bit. */
410 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &sd->ww, &sd->wh);
411 if (x < 0)
412 sd->wx = 0;
413 else if ((x + sd->ww) > cw)
414 sd->wx = cw - sd->ww;
415 else if (sd->is_mirrored)
416 sd->wx = _elm_smart_scroller_x_mirrored_get(sd->smart_obj, x);
417 else
418 sd->wx = x;
419 if (y < 0) sd->wy = 0;
420 else if ((y + sd->wh) > ch) sd->wy = ch - sd->wh;
421 else sd->wy = y;
422}
423
424static void
425_smart_anim_start(Evas_Object *obj)
426{
427 evas_object_smart_callback_call(obj, "animate,start", NULL);
428}
429
430static void
431_smart_anim_stop(Evas_Object *obj)
432{
433 evas_object_smart_callback_call(obj, "animate,stop", NULL);
434}
435
436static void
437_smart_drag_start(Evas_Object *obj)
438{
439 evas_object_smart_callback_call(obj, "drag,start", NULL);
440}
441
442static void
443_smart_drag_stop(Evas_Object *obj)
444{
445 evas_object_smart_callback_call(obj, "drag,stop", NULL);
446}
447
448static Eina_Bool
449_smart_scrollto_x_animator(void *data)
450{
451 Smart_Data *sd = data;
452 Evas_Coord px, py;
453 double t, tt;
454
455 t = ecore_loop_time_get();
456 tt = (t - sd->scrollto.x.t_start) / (sd->scrollto.x.t_end - sd->scrollto.x.t_start);
457 tt = 1.0 - tt;
458 tt = 1.0 - (tt * tt);
459 sd->pan_func.get(sd->pan_obj, &px, &py);
460 px = (sd->scrollto.x.start * (1.0 - tt)) +
461 (sd->scrollto.x.end * tt);
462 if (t >= sd->scrollto.x.t_end)
463 {
464 px = sd->scrollto.x.end;
465 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
466 sd->down.sx = px;
467 sd->down.x = sd->down.history[0].x;
468 _update_wanted_coordinates(sd, px, py);
469 sd->scrollto.x.animator = NULL;
470 if ((!sd->scrollto.y.animator) && (!sd->down.bounce_y_animator))
471 _smart_anim_stop(sd->smart_obj);
472 return ECORE_CALLBACK_CANCEL;
473 }
474 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
475 _update_wanted_coordinates(sd, px, py);
476 return ECORE_CALLBACK_RENEW;
477}
478
479static void
480_smart_momentum_end(Smart_Data *sd)
481{
482 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator)) return;
483 if (sd->down.momentum_animator)
484 {
485 Evas_Coord px, py;
486 elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py);
487 _update_wanted_coordinates(sd, px, py);
488
489 ecore_animator_del(sd->down.momentum_animator);
490 sd->down.momentum_animator = NULL;
491 sd->down.bounce_x_hold = EINA_FALSE;
492 sd->down.bounce_y_hold = EINA_FALSE;
493 sd->down.ax = 0;
494 sd->down.ay = 0;
495 sd->down.dx = 0;
496 sd->down.dy = 0;
497 sd->down.pdx = 0;
498 sd->down.pdy = 0;
499 if (sd->child.resized)
500 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
501 }
502}
503
504static void
505_smart_scrollto_x(Smart_Data *sd, double t_in, Evas_Coord pos_x)
506{
507 Evas_Coord px, py, x, y, w, h;
508 double t;
509
510 if (sd->freeze) return;
511 if (t_in <= 0.0)
512 {
513 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
514 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
515 x = pos_x;
516 elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
517 return;
518 }
519 t = ecore_loop_time_get();
520 sd->pan_func.get(sd->pan_obj, &px, &py);
521 sd->scrollto.x.start = px;
522 sd->scrollto.x.end = pos_x;
523 sd->scrollto.x.t_start = t;
524 sd->scrollto.x.t_end = t + t_in;
525 if (!sd->scrollto.x.animator)
526 {
527 sd->scrollto.x.animator = ecore_animator_add(_smart_scrollto_x_animator, sd);
528 if (!sd->scrollto.y.animator)
529 _smart_anim_start(sd->smart_obj);
530 }
531 if (sd->down.bounce_x_animator)
532 {
533 ecore_animator_del(sd->down.bounce_x_animator);
534 sd->down.bounce_x_animator = NULL;
535 _smart_momentum_end(sd);
536 if (sd->child.resized)
537 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
538 }
539 sd->bouncemex = EINA_FALSE;
540}
541
542static Eina_Bool
543_smart_scrollto_y_animator(void *data)
544{
545 Smart_Data *sd = data;
546 Evas_Coord px, py;
547 double t, tt;
548
549 t = ecore_loop_time_get();
550 tt = (t - sd->scrollto.y.t_start) / (sd->scrollto.y.t_end - sd->scrollto.y.t_start);
551 tt = 1.0 - tt;
552 tt = 1.0 - (tt * tt);
553 sd->pan_func.get(sd->pan_obj, &px, &py);
554 py = (sd->scrollto.y.start * (1.0 - tt)) +
555 (sd->scrollto.y.end * tt);
556 if (t >= sd->scrollto.y.t_end)
557 {
558 py = sd->scrollto.y.end;
559 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
560 sd->down.sy = py;
561 sd->down.y = sd->down.history[0].y;
562 _update_wanted_coordinates(sd, px, py);
563 sd->scrollto.y.animator = NULL;
564 if ((!sd->scrollto.x.animator) && (!sd->down.bounce_x_animator))
565 _smart_anim_stop(sd->smart_obj);
566 return ECORE_CALLBACK_CANCEL;
567 }
568 elm_smart_scroller_child_pos_set(sd->smart_obj, px, py);
569 _update_wanted_coordinates(sd, px, py);
570
571 return ECORE_CALLBACK_RENEW;
572}
573
574static void
575_smart_scrollto_y(Smart_Data *sd, double t_in, Evas_Coord pos_y)
576{
577 Evas_Coord px, py, x, y, w, h;
578 double t;
579
580 if (sd->freeze) return;
581 if (t_in <= 0.0)
582 {
583 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
584 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
585 y = pos_y;
586 elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
587 return;
588 }
589 t = ecore_loop_time_get();
590 sd->pan_func.get(sd->pan_obj, &px, &py);
591 sd->scrollto.y.start = py;
592 sd->scrollto.y.end = pos_y;
593 sd->scrollto.y.t_start = t;
594 sd->scrollto.y.t_end = t + t_in;
595 if (!sd->scrollto.y.animator)
596 {
597 sd->scrollto.y.animator = ecore_animator_add(_smart_scrollto_y_animator, sd);
598 if (!sd->scrollto.x.animator)
599 _smart_anim_start(sd->smart_obj);
600 }
601 if (sd->down.bounce_y_animator)
602 {
603 ecore_animator_del(sd->down.bounce_y_animator);
604 sd->down.bounce_y_animator = NULL;
605 _smart_momentum_end(sd);
606 if (sd->child.resized)
607 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
608 }
609 sd->bouncemey = EINA_FALSE;
610}
611
612static Eina_Bool
613_smart_do_page(Smart_Data *sd)
614{
615 if ((sd->pagerel_h == 0.0) && (!sd->pagesize_h) &&
616 (sd->pagerel_v == 0.0) && (!sd->pagesize_v))
617 return EINA_FALSE;
618 return EINA_TRUE;
619}
620
621static Evas_Coord
622_smart_page_x_get(Smart_Data *sd, int offset)
623{
624 Evas_Coord x, y, w, h, cw, ch, minx = 0;
625
626 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
627 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
628 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
629 sd->pan_func.min_get(sd->pan_obj, &minx, NULL);
630
631 x += offset;
632
633 if (sd->pagerel_h > 0.0)
634 sd->pagesize_h = w * sd->pagerel_h;
635 if (sd->pagesize_h > 0)
636 {
637 x = x + (sd->pagesize_h * 0.5);
638 x = x / (sd->pagesize_h);
639 x = x * (sd->pagesize_h);
640 }
641 if ((x + w) > cw) x = cw - w;
642 if (x < minx) x = minx;
643 return x;
644}
645
646static Evas_Coord
647_smart_page_y_get(Smart_Data *sd, int offset)
648{
649 Evas_Coord x, y, w, h, cw, ch, miny = 0;
650
651 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
652 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
653 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
654 sd->pan_func.min_get(sd->pan_obj, NULL, &miny);
655
656 y += offset;
657
658 if (sd->pagerel_v > 0.0)
659 sd->pagesize_v = h * sd->pagerel_v;
660 if (sd->pagesize_v > 0)
661 {
662 y = y + (sd->pagesize_v * 0.5);
663 y = y / (sd->pagesize_v);
664 y = y * (sd->pagesize_v);
665 }
666 if ((y + h) > ch) y = ch - h;
667 if (y < miny) y = miny;
668 return y;
669}
670
671static void
672_smart_page_adjust(Smart_Data *sd)
673{
674 Evas_Coord x, y, w, h;
675
676 if (!_smart_do_page(sd)) return;
677
678 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
679
680 x = _smart_page_x_get(sd, 0);
681 y = _smart_page_y_get(sd, 0);
682
683 elm_smart_scroller_child_region_set(sd->smart_obj, x, y, w, h);
684}
685
686static Eina_Bool
687_smart_bounce_x_animator(void *data)
688{
689 Smart_Data *sd;
690 Evas_Coord x, y, dx, w, odx, ed, md;
691 double t, p, dt, pd, r;
692
693 sd = data;
694 t = ecore_loop_time_get();
695 dt = t - sd->down.anim_start2;
696 if (dt >= 0.0)
697 {
698 dt = dt / _elm_config->thumbscroll_bounce_friction;
699 odx = sd->down.b2x - sd->down.bx;
700 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, NULL);
701 if (!sd->down.momentum_animator && (w > abs(odx)))
702 {
703 pd = (double)odx / (double)w;
704 pd = (pd > 0) ? pd : -pd;
705 pd = 1.0 - ((1.0 - pd) * (1.0 - pd));
706 dt = dt / pd;
707 }
708 if (dt > 1.0) dt = 1.0;
709 p = 1.0 - ((1.0 - dt) * (1.0 - dt));
710 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
711 dx = (odx * p);
712 r = 1.0;
713 if (sd->down.momentum_animator)
714 {
715 ed = abs(sd->down.dx * (_elm_config->thumbscroll_friction + sd->down.extra_time) - sd->down.b0x);
716 md = abs(_elm_config->thumbscroll_friction * 5 * w);
717 if (ed > md) r = (double)(md)/(double)ed;
718 }
719 x = sd->down.b2x + (int)((double)(dx - odx) * r);
720 if (!sd->down.cancelled)
721 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
722 if (dt >= 1.0)
723 {
724 if (sd->down.momentum_animator)
725 sd->down.bounce_x_hold = EINA_TRUE;
726 if ((!sd->down.bounce_y_animator) &&
727 (!sd->scrollto.y.animator))
728 _smart_anim_stop(sd->smart_obj);
729 sd->down.bounce_x_animator = NULL;
730 sd->down.pdx = 0;
731 sd->bouncemex = EINA_FALSE;
732 _smart_momentum_end(sd);
733 if (sd->child.resized)
734 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
735 return ECORE_CALLBACK_CANCEL;
736 }
737 }
738 return ECORE_CALLBACK_RENEW;
739}
740
741static Eina_Bool
742_smart_bounce_y_animator(void *data)
743{
744 Smart_Data *sd;
745 Evas_Coord x, y, dy, h, ody, ed, md;
746 double t, p, dt, pd, r;
747
748 sd = data;
749 t = ecore_loop_time_get();
750 dt = t - sd->down.anim_start3;
751 if (dt >= 0.0)
752 {
753 dt = dt / _elm_config->thumbscroll_bounce_friction;
754 ody = sd->down.b2y - sd->down.by;
755 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, NULL, &h);
756 if (!sd->down.momentum_animator && (h > abs(ody)))
757 {
758 pd = (double)ody / (double)h;
759 pd = (pd > 0) ? pd : -pd;
760 pd = 1.0 - ((1.0 - pd) * (1.0 - pd));
761 dt = dt / pd;
762 }
763 if (dt > 1.0) dt = 1.0;
764 p = 1.0 - ((1.0 - dt) * (1.0 - dt));
765 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
766 dy = (ody * p);
767 r = 1.0;
768 if (sd->down.momentum_animator)
769 {
770 ed = abs(sd->down.dy * (_elm_config->thumbscroll_friction + sd->down.extra_time) - sd->down.b0y);
771 md = abs(_elm_config->thumbscroll_friction * 5 * h);
772 if (ed > md) r = (double)(md)/(double)ed;
773 }
774 y = sd->down.b2y + (int)((double)(dy - ody) * r);
775 if (!sd->down.cancelled)
776 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
777 if (dt >= 1.0)
778 {
779 if (sd->down.momentum_animator)
780 sd->down.bounce_y_hold = EINA_TRUE;
781 if ((!sd->down.bounce_x_animator) &&
782 (!sd->scrollto.y.animator))
783 _smart_anim_stop(sd->smart_obj);
784 sd->down.bounce_y_animator = NULL;
785 sd->down.pdy = 0;
786 sd->bouncemey = EINA_FALSE;
787 _smart_momentum_end(sd);
788 if (sd->child.resized)
789 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
790 return ECORE_CALLBACK_CANCEL;
791 }
792 }
793 return ECORE_CALLBACK_RENEW;
794}
795
796#define LEFT 0
797#define RIGHT 1
798#define UP 2
799#define DOWN 3
800static Eina_Bool
801can_scroll(Smart_Data *sd, int dir)
802{
803 Evas_Coord mx = 0, my = 0, px = 0, py = 0, minx = 0, miny = 0;
804
805 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
806 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
807 sd->pan_func.get(sd->pan_obj, &px, &py);
808 switch (dir)
809 {
810 case LEFT:
811 if (px > minx) return EINA_TRUE;
812 break;
813 case RIGHT:
814 if ((px - minx) < mx) return EINA_TRUE;
815 break;
816 case UP:
817 if (py > miny) return EINA_TRUE;
818 break;
819 case DOWN:
820 if ((py - miny) < my) return EINA_TRUE;
821 break;
822 default:
823 break;
824 }
825 return EINA_FALSE;
826}
827
828static Eina_Bool
829_smart_momentum_animator(void *data)
830{
831 Smart_Data *sd;
832 double t, dt, p;
833 Evas_Coord x, y, dx, dy, px, py, maxx, maxy, minx, miny;
834 Eina_Bool no_bounce_x_end = EINA_FALSE, no_bounce_y_end = EINA_FALSE;
835
836 sd = data;
837 t = ecore_loop_time_get();
838 dt = t - sd->down.anim_start;
839 if (dt >= 0.0)
840 {
841 /*
842 if (sd->down.hold_parent)
843 {
844 if ((sd->down.dir_x) && !can_scroll(sd, sd->down.hdir))
845 {
846 sd->down.dir_x = 0;
847 }
848 if ((sd->down.dir_y) && !can_scroll(sd, sd->down.vdir))
849 {
850 sd->down.dir_y = 0;
851 }
852 }
853 if ((!sd->down.dir_x) && (!sd->down.dir_y))
854 {
855 sd->down.cancelled = 1;
856 }
857 */
858 dt = dt / (_elm_config->thumbscroll_friction + sd->down.extra_time);
859 if (dt > 1.0) dt = 1.0;
860 p = 1.0 - ((1.0 - dt) * (1.0 - dt));
861 dx = (sd->down.dx * (_elm_config->thumbscroll_friction + sd->down.extra_time) * p);
862 dy = (sd->down.dy * (_elm_config->thumbscroll_friction + sd->down.extra_time) * p);
863 sd->down.ax = dx;
864 sd->down.ay = dy;
865 x = sd->down.sx - dx;
866 y = sd->down.sy - dy;
867 elm_smart_scroller_child_pos_get(sd->smart_obj, &px, &py);
868 if ((sd->down.bounce_x_animator) ||
869 (sd->down.bounce_x_hold))
870 {
871 sd->down.bx = sd->down.bx0 - dx + sd->down.b0x;
872 x = px;
873 }
874 if ((sd->down.bounce_y_animator) ||
875 (sd->down.bounce_y_hold))
876 {
877 sd->down.by = sd->down.by0 - dy + sd->down.b0y;
878 y = py;
879 }
880 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
881 _update_wanted_coordinates(sd, x, y);
882 sd->pan_func.max_get(sd->pan_obj, &maxx, &maxy);
883 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
884 if (!sd->bounce_horiz)
885 {
886 if (x <= minx) no_bounce_x_end = EINA_TRUE;
887 if ((x - minx) >= maxx) no_bounce_x_end = EINA_TRUE;
888 }
889 if (!sd->bounce_vert)
890 {
891 if (y <= miny) no_bounce_y_end = EINA_TRUE;
892 if ((y - miny) >= maxy) no_bounce_y_end = EINA_TRUE;
893 }
894 if ((dt >= 1.0) ||
895 ((sd->down.bounce_x_hold) && (sd->down.bounce_y_hold)) ||
896 (no_bounce_x_end && no_bounce_y_end))
897 {
898 _smart_anim_stop(sd->smart_obj);
899
900 sd->down.momentum_animator = NULL;
901 sd->down.bounce_x_hold = EINA_FALSE;
902 sd->down.bounce_y_hold = EINA_FALSE;
903 sd->down.ax = 0;
904 sd->down.ay = 0;
905 sd->down.pdx = 0;
906 sd->down.pdy = 0;
907 if (sd->child.resized)
908 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
909 return ECORE_CALLBACK_CANCEL;
910 }
911 }
912 return ECORE_CALLBACK_RENEW;
913}
914
915static void
916bounce_eval(Smart_Data *sd)
917{
918 Evas_Coord mx, my, px, py, bx, by, b2x, b2y, minx = 0, miny = 0;
919
920 if (sd->freeze) return;
921 if ((!sd->bouncemex) && (!sd->bouncemey)) return;
922 if (sd->down.now) return; // down bounce while still held down
923 if (sd->down.onhold_animator)
924 {
925 ecore_animator_del(sd->down.onhold_animator);
926 sd->down.onhold_animator = NULL;
927 if (sd->child.resized)
928 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
929 }
930 if (sd->down.hold_animator)
931 {
932 ecore_animator_del(sd->down.hold_animator);
933 sd->down.hold_animator = NULL;
934 if (sd->child.resized)
935 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
936 }
937 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
938 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
939 sd->pan_func.get(sd->pan_obj, &px, &py);
940 bx = px;
941 by = py;
942 if (px < minx) px = minx;
943 if ((px - minx) > mx) px = mx + minx;
944 if (py < miny) py = miny;
945 if ((py - miny) > my) py = my + miny;
946 b2x = px;
947 b2y = py;
948 if ((!sd->widget) ||
949 (!elm_widget_drag_child_locked_x_get(sd->widget)))
950 {
951 if ((!sd->down.bounce_x_animator) && (!sd->bounce_animator_disabled))
952 {
953 if (sd->bouncemex)
954 {
955 if (sd->scrollto.x.animator)
956 {
957 ecore_animator_del(sd->scrollto.x.animator);
958 sd->scrollto.x.animator = NULL;
959 }
960 sd->down.bounce_x_animator = ecore_animator_add(_smart_bounce_x_animator, sd);
961 sd->down.anim_start2 = ecore_loop_time_get();
962 sd->down.bx = bx;
963 sd->down.bx0 = bx;
964 sd->down.b2x = b2x;
965 if (sd->down.momentum_animator) sd->down.b0x = sd->down.ax;
966 else sd->down.b0x = 0;
967 }
968 }
969 }
970 if ((!sd->widget) ||
971 (!elm_widget_drag_child_locked_y_get(sd->widget)))
972 {
973 if ((!sd->down.bounce_y_animator) && (!sd->bounce_animator_disabled))
974 {
975 if (sd->bouncemey)
976 {
977 if (sd->scrollto.y.animator)
978 {
979 ecore_animator_del(sd->scrollto.y.animator);
980 sd->scrollto.y.animator = NULL;
981 }
982 sd->down.bounce_y_animator = ecore_animator_add(_smart_bounce_y_animator, sd);
983 sd->down.anim_start3 = ecore_loop_time_get();
984 sd->down.by = by;
985 sd->down.by0 = by;
986 sd->down.b2y = b2y;
987 if (sd->down.momentum_animator) sd->down.b0y = sd->down.ay;
988 else sd->down.b0y = 0;
989 }
990 }
991 }
992}
993
994void
995elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
996{
997 Evas_Coord mx = 0, my = 0, px = 0, py = 0, minx = 0, miny = 0;
998 double vx, vy;
999
1000 API_ENTRY return;
1001 // FIXME: allow for bounce outside of range
1002 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
1003 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1004 if (mx > 0) vx = (double)(x - minx) / (double)mx;
1005 else vx = 0.0;
1006 if (vx < 0.0) vx = 0.0;
1007 else if (vx > 1.0) vx = 1.0;
1008 if (my > 0) vy = (double)(y - miny) / (double)my;
1009 else vy = 0.0;
1010 if (vy < 0.0) vy = 0.0;
1011 else if (vy > 1.0) vy = 1.0;
1012 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, vy);
1013 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", vx, 0.0);
1014 sd->pan_func.get(sd->pan_obj, &px, &py);
1015 if (!_elm_config->thumbscroll_bounce_enable)
1016 {
1017 if (x < minx) x = minx;
1018 if ((x - minx) > mx) x = mx + minx;
1019 if (y < miny) y = miny;
1020 if ((y - miny) > my) y = my + miny;
1021 }
1022
1023 if (!sd->bounce_horiz)
1024 {
1025 if (x < minx) x = minx;
1026 if ((x - minx) > mx) x = mx + minx;
1027 }
1028 if (!sd->bounce_vert)
1029 {
1030 if (y < miny) y = miny;
1031 if (y - miny > my) y = my + miny;
1032 }
1033
1034 sd->pan_func.set(sd->pan_obj, x, y);
1035 if ((px != x) || (py != y))
1036 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
1037 if (!sd->down.bounce_x_animator)
1038 {
1039 if (((x < minx) && (0 <= sd->down.dx)) ||
1040 ((x > (mx + minx)) && (0 >= sd->down.dx)))
1041 {
1042 sd->bouncemex = EINA_TRUE;
1043 bounce_eval(sd);
1044 }
1045 else
1046 sd->bouncemex = EINA_FALSE;
1047 }
1048 if (!sd->down.bounce_y_animator)
1049 {
1050 if (((y < miny) && (0 <= sd->down.dy)) ||
1051 ((y > (my + miny)) && (0 >= sd->down.dy)))
1052 {
1053 sd->bouncemey = EINA_TRUE;
1054 bounce_eval(sd);
1055 }
1056 else
1057 sd->bouncemey = EINA_FALSE;
1058 }
1059 if ((x != px) || (y != py))
1060 {
1061 evas_object_smart_callback_call(obj, "scroll", NULL);
1062 }
1063 if ((x != px)/* && (!sd->bouncemex)*/)
1064 {
1065 if (x == minx)
1066 evas_object_smart_callback_call(obj, "edge,left", NULL);
1067 if (x == (mx + minx))
1068 evas_object_smart_callback_call(obj, "edge,right", NULL);
1069 }
1070 if ((y != py)/* && (!sd->bouncemey)*/)
1071 {
1072 if (y == miny)
1073 evas_object_smart_callback_call(obj, "edge,top", NULL);
1074 if (y == my + miny)
1075 evas_object_smart_callback_call(obj, "edge,bottom", NULL);
1076 }
1077}
1078
1079void
1080elm_smart_scroller_child_pos_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1081{
1082 API_ENTRY return;
1083 sd->pan_func.get(sd->pan_obj, x, y);
1084}
1085
1086/* returns TRUE when we need to move the scroller, FALSE otherwise.
1087 * Updates w and h either way, so save them if you need them. */
1088static Eina_Bool
1089_elm_smart_scroller_child_region_show_internal(Evas_Object *obj, Evas_Coord *_x, Evas_Coord *_y, Evas_Coord w, Evas_Coord h)
1090{
1091 Evas_Coord mx = 0, my = 0, cw = 0, ch = 0, px = 0, py = 0, nx, ny, minx = 0, miny = 0, pw = 0, ph = 0, x = *_x, y = *_y;
1092
1093 API_ENTRY return EINA_FALSE;
1094 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
1095 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1096 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
1097 sd->pan_func.get(sd->pan_obj, &px, &py);
1098 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &pw, &ph);
1099
1100 nx = px;
1101 if ((x < px) && ((x + w) < (px + (cw - mx)))) nx = x;
1102 else if ((x > px) && ((x + w) > (px + (cw - mx)))) nx = x + w - (cw - mx);
1103 ny = py;
1104 if ((y < py) && ((y + h) < (py + (ch - my)))) ny = y;
1105 else if ((y > py) && ((y + h) > (py + (ch - my)))) ny = y + h - (ch - my);
1106
1107 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
1108 (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
1109 {
1110 _smart_anim_stop(sd->smart_obj);
1111 }
1112 if (sd->scrollto.x.animator)
1113 {
1114 ecore_animator_del(sd->scrollto.x.animator);
1115 sd->scrollto.x.animator = NULL;
1116 }
1117 if (sd->scrollto.y.animator)
1118 {
1119 ecore_animator_del(sd->scrollto.y.animator);
1120 sd->scrollto.y.animator = NULL;
1121 }
1122 if (sd->down.bounce_x_animator)
1123 {
1124 ecore_animator_del(sd->down.bounce_x_animator);
1125 sd->down.bounce_x_animator = NULL;
1126 sd->bouncemex = EINA_FALSE;
1127 if (sd->child.resized)
1128 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1129 }
1130 if (sd->down.bounce_y_animator)
1131 {
1132 ecore_animator_del(sd->down.bounce_y_animator);
1133 sd->down.bounce_y_animator = NULL;
1134 sd->bouncemey = EINA_FALSE;
1135 if (sd->child.resized)
1136 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1137 }
1138 if (sd->down.hold_animator)
1139 {
1140 ecore_animator_del(sd->down.hold_animator);
1141 sd->down.hold_animator = NULL;
1142 _smart_drag_stop(sd->smart_obj);
1143 if (sd->child.resized)
1144 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1145 }
1146 if (sd->down.momentum_animator)
1147 {
1148 ecore_animator_del(sd->down.momentum_animator);
1149 sd->down.momentum_animator = NULL;
1150 sd->down.bounce_x_hold = EINA_FALSE;
1151 sd->down.bounce_y_hold = EINA_FALSE;
1152 sd->down.ax = 0;
1153 sd->down.ay = 0;
1154 sd->down.pdx = 0;
1155 sd->down.pdy = 0;
1156 if (sd->child.resized)
1157 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1158 }
1159
1160 x = nx;
1161 if ((x + pw) > cw) x = cw - pw;
1162 if (x < minx) x = minx;
1163 y = ny;
1164 if ((y + ph) > ch) y = ch - ph;
1165 if (y < miny) y = miny;
1166
1167 if ((x == px) && (y == py)) return EINA_FALSE;
1168 *_x = x;
1169 *_y = y;
1170 return EINA_TRUE;
1171}
1172
1173/* Set should be used for calculated positions, for example, when we move
1174 * because of an animation or because this is the correct position after
1175 * constraints. */
1176void
1177elm_smart_scroller_child_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1178{
1179 API_ENTRY return;
1180 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1181 {
1182 elm_smart_scroller_child_pos_set(obj, x, y);
1183 sd->down.sx = x;
1184 sd->down.sy = y;
1185 sd->down.x = sd->down.history[0].x;
1186 sd->down.y = sd->down.history[0].y;
1187 }
1188}
1189
1190/* Set should be used for setting the wanted position, for example a user scroll
1191 * or moving the cursor in an entry. */
1192void
1193elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1194{
1195 API_ENTRY return;
1196 sd->wx = x;
1197 sd->wy = y;
1198 sd->ww = w;
1199 sd->wh = h;
1200 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1201 {
1202 elm_smart_scroller_child_pos_set(obj, x, y);
1203 sd->down.sx = x;
1204 sd->down.sy = y;
1205 sd->down.x = sd->down.history[0].x;
1206 sd->down.y = sd->down.history[0].y;
1207 }
1208}
1209
1210void
1211elm_smart_scroller_child_viewport_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
1212{
1213 API_ENTRY return;
1214 if (!sd->pan_obj) return;
1215 edje_object_calc_force(sd->edje_obj);
1216 evas_object_geometry_get(sd->pan_obj, NULL, NULL, w, h);
1217}
1218
1219void
1220elm_smart_scroller_step_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1221{
1222 API_ENTRY return;
1223 if (x < 1) x = 1;
1224 if (y < 1) y = 1;
1225 sd->step.x = x;
1226 sd->step.y = y;
1227 _smart_scrollbar_size_adjust(sd);
1228}
1229
1230void
1231elm_smart_scroller_step_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1232{
1233 API_ENTRY return;
1234 if (x) *x = sd->step.x;
1235 if (y) *y = sd->step.y;
1236}
1237
1238void
1239elm_smart_scroller_page_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
1240{
1241 API_ENTRY return;
1242 sd->page.x = x;
1243 sd->page.y = y;
1244 _smart_scrollbar_size_adjust(sd);
1245}
1246
1247void
1248elm_smart_scroller_page_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y)
1249{
1250 API_ENTRY return;
1251 if (x) *x = sd->page.x;
1252 if (y) *y = sd->page.y;
1253}
1254
1255void
1256elm_smart_scroller_policy_set(Evas_Object *obj, Elm_Smart_Scroller_Policy hbar, Elm_Smart_Scroller_Policy vbar)
1257{
1258 API_ENTRY return;
1259 if ((sd->hbar_flags == hbar) && (sd->vbar_flags == vbar)) return;
1260 sd->hbar_flags = hbar;
1261 sd->vbar_flags = vbar;
1262 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
1263 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,hbar", "elm");
1264 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
1265 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
1266 else
1267 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,hbar", "elm");
1268 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
1269 edje_object_signal_emit(sd->edje_obj, "elm,action,show_always,vbar", "elm");
1270 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
1271 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
1272 else
1273 edje_object_signal_emit(sd->edje_obj, "elm,action,show_notalways,vbar", "elm");
1274 _smart_scrollbar_size_adjust(sd);
1275}
1276
1277void
1278elm_smart_scroller_policy_get(Evas_Object *obj, Elm_Smart_Scroller_Policy *hbar, Elm_Smart_Scroller_Policy *vbar)
1279{
1280 API_ENTRY return;
1281 if (hbar) *hbar = sd->hbar_flags;
1282 if (vbar) *vbar = sd->vbar_flags;
1283}
1284
1285Evas_Object *
1286elm_smart_scroller_edje_object_get(Evas_Object *obj)
1287{
1288 API_ENTRY return NULL;
1289 return sd->edje_obj;
1290}
1291
1292void
1293elm_smart_scroller_single_dir_set(Evas_Object *obj, Eina_Bool single_dir)
1294{
1295 API_ENTRY return;
1296 sd->one_dir_at_a_time = single_dir;
1297}
1298
1299Eina_Bool
1300elm_smart_scroller_single_dir_get(Evas_Object *obj)
1301{
1302 API_ENTRY return EINA_FALSE;
1303 return sd->one_dir_at_a_time;
1304}
1305
1306void
1307elm_smart_scroller_object_theme_set(Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style)
1308{
1309 API_ENTRY return;
1310 Evas_Coord mw, mh;
1311 //Does this API require parent object absolutely? if then remove this exception.
1312 double parent_scale = parent ? elm_widget_scale_get(parent) : 1;
1313 _elm_theme_object_set(parent, sd->edje_obj, clas, group, style);
1314 edje_object_scale_set(sd->edje_obj, parent_scale * _elm_config->scale);
1315 if (sd->pan_obj)
1316 edje_object_part_swallow(sd->edje_obj, "elm.swallow.content", sd->pan_obj);
1317 mw = mh = -1;
1318 elm_coords_finger_size_adjust(1, &mw, 1, &mh);
1319 if (edje_object_part_exists(sd->edje_obj, "elm.scrollbar.base"))
1320 {
1321 Evas_Object *base;
1322 base = edje_object_part_swallow_get(sd->edje_obj, "elm.scrollbar.base");
1323 if (!base)
1324 {
1325 base = evas_object_rectangle_add(evas_object_evas_get(sd->edje_obj));
1326 evas_object_color_set(base, 0, 0, 0, 0);
1327 edje_object_part_swallow(sd->edje_obj, "elm.scrollbar.base", base);
1328 }
1329 if (!_elm_config->thumbscroll_enable)
1330 evas_object_size_hint_min_set(base, mw, mh);
1331 }
1332 sd->vbar_visible = !sd->vbar_visible;
1333 sd->hbar_visible = !sd->hbar_visible;
1334 _smart_scrollbar_bar_visibility_adjust(sd);
1335}
1336
1337void
1338elm_smart_scroller_hold_set(Evas_Object *obj, Eina_Bool hold)
1339{
1340 API_ENTRY return;
1341 sd->hold = hold;
1342}
1343
1344void
1345elm_smart_scroller_freeze_set(Evas_Object *obj, Eina_Bool freeze)
1346{
1347 API_ENTRY return;
1348 sd->freeze = freeze;
1349 if (sd->freeze)
1350 {
1351 if (sd->down.onhold_animator)
1352 {
1353 ecore_animator_del(sd->down.onhold_animator);
1354 sd->down.onhold_animator = NULL;
1355 if (sd->child.resized)
1356 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1357 }
1358 }
1359 else
1360 bounce_eval(sd);
1361}
1362
1363void
1364elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert)
1365{
1366 API_ENTRY return;
1367 sd->bounce_horiz = !!horiz;
1368 sd->bounce_vert = !!vert;
1369}
1370
1371void
1372elm_smart_scroller_bounce_allow_get(const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert)
1373{
1374 API_ENTRY return;
1375 if (horiz) *horiz = sd->bounce_horiz;
1376 if (vert) *vert = sd->bounce_vert;
1377}
1378
1379void
1380elm_smart_scroller_paging_set(Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v)
1381{
1382 API_ENTRY return;
1383 sd->pagerel_h = pagerel_h;
1384 sd->pagerel_v = pagerel_v;
1385 sd->pagesize_h = pagesize_h;
1386 sd->pagesize_v = pagesize_v;
1387 _smart_page_adjust(sd);
1388}
1389
1390void
1391elm_smart_scroller_paging_get(Evas_Object *obj, double *pagerel_h, double *pagerel_v, Evas_Coord *pagesize_h, Evas_Coord *pagesize_v)
1392{
1393 API_ENTRY return;
1394 if (pagerel_h) *pagerel_h = sd->pagerel_h;
1395 if (pagerel_v) *pagerel_v = sd->pagerel_v;
1396 if (pagesize_h) *pagesize_h = sd->pagesize_h;
1397 if (pagesize_v) *pagesize_v = sd->pagesize_v;
1398}
1399
1400void
1401elm_smart_scroller_current_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v)
1402{
1403 API_ENTRY return;
1404 Evas_Coord x, y;
1405 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
1406 if (pagenumber_h)
1407 {
1408 if (sd->pagesize_h > 0)
1409 *pagenumber_h = (x + sd->pagesize_h - 1) / sd->pagesize_h;
1410 else
1411 *pagenumber_h = 0;
1412 }
1413 if (pagenumber_v)
1414 {
1415 if (sd->pagesize_v > 0)
1416 *pagenumber_v = (y + sd->pagesize_v - 1) / sd->pagesize_v;
1417 else
1418 *pagenumber_v = 0;
1419 }
1420}
1421
1422void
1423elm_smart_scroller_last_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v)
1424{
1425 API_ENTRY return;
1426 Evas_Coord cw, ch;
1427 sd->pan_func.child_size_get(sd->pan_obj, &cw, &ch);
1428 if (pagenumber_h)
1429 {
1430 if (sd->pagesize_h > 0)
1431 *pagenumber_h = cw / sd->pagesize_h + 1;
1432 else
1433 *pagenumber_h = 0;
1434 }
1435 if (pagenumber_v)
1436 {
1437 if (sd->pagesize_v > 0)
1438 *pagenumber_v = ch / sd->pagesize_v + 1;
1439 else
1440 *pagenumber_v = 0;
1441 }
1442}
1443
1444void
1445elm_smart_scroller_page_show(Evas_Object *obj, int pagenumber_h, int pagenumber_v)
1446{
1447 API_ENTRY return;
1448 Evas_Coord x, y, w, h;
1449 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
1450 if (pagenumber_h >= 0) x = sd->pagesize_h * pagenumber_h;
1451 if (pagenumber_v >= 0) y = sd->pagesize_v * pagenumber_v;
1452 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1453 elm_smart_scroller_child_pos_set(obj, x, y);
1454}
1455
1456void
1457elm_smart_scroller_page_bring_in(Evas_Object *obj, int pagenumber_h, int pagenumber_v)
1458{
1459 API_ENTRY return;
1460 Evas_Coord x, y, w, h;
1461 elm_smart_scroller_child_viewport_size_get(sd->smart_obj, &w, &h);
1462 if (pagenumber_h >= 0) x = sd->pagesize_h * pagenumber_h;
1463 if (pagenumber_v >= 0) y = sd->pagesize_v * pagenumber_v;
1464 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1465 {
1466 _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, x);
1467 _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, y);
1468 }
1469}
1470
1471void
1472elm_smart_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
1473{
1474 API_ENTRY return;
1475 if (_elm_smart_scroller_child_region_show_internal(obj, &x, &y, w, h))
1476 {
1477 _smart_scrollto_x(sd, _elm_config->bring_in_scroll_friction, x);
1478 _smart_scrollto_y(sd, _elm_config->bring_in_scroll_friction, y);
1479 }
1480}
1481
1482void
1483elm_smart_scroller_widget_set(Evas_Object *obj, Evas_Object *wid)
1484{
1485 API_ENTRY return;
1486 sd->widget = wid;
1487}
1488
1489static void
1490_elm_smart_scroller_wanted_region_set(Evas_Object *obj)
1491{
1492 INTERNAL_ENTRY;
1493 Evas_Coord ww, wh, wx = sd->wx;
1494
1495 if (sd->down.now || sd->down.momentum_animator ||
1496 sd->down.bounce_x_animator || sd->down.bounce_y_animator ||
1497 sd->down.hold_animator || sd->down.onhold_animator ||
1498 sd->scrollto.x.animator || sd->scrollto.y.animator) return;
1499
1500 sd->child.resized = EINA_FALSE;
1501
1502 /* Flip to RTL cords only if init in RTL mode */
1503 if (sd->is_mirrored)
1504 wx = _elm_smart_scroller_x_mirrored_get(obj, sd->wx);
1505
1506 if (sd->ww == -1)
1507 {
1508 elm_smart_scroller_child_viewport_size_get(obj, &ww, &wh);
1509 }
1510 else
1511 {
1512 ww = sd->ww;
1513 wh = sd->wh;
1514 }
1515
1516 elm_smart_scroller_child_region_set(obj, wx, sd->wy, ww, wh);
1517}
1518
1519/* local subsystem functions */
1520static void
1521_smart_edje_drag_v_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1522{
1523 Smart_Data *sd;
1524
1525 sd = data;
1526 _smart_scrollbar_read(sd);
1527 _smart_drag_start(sd->smart_obj);
1528 sd->freeze = EINA_TRUE;
1529}
1530
1531static void
1532_smart_edje_drag_v_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1533{
1534 Smart_Data *sd;
1535
1536 sd = data;
1537 _smart_scrollbar_read(sd);
1538 _smart_drag_stop(sd->smart_obj);
1539 sd->freeze = EINA_FALSE;
1540}
1541
1542static void
1543_smart_edje_drag_v(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1544{
1545 Smart_Data *sd;
1546
1547 sd = data;
1548 _smart_scrollbar_read(sd);
1549}
1550
1551static void
1552_smart_edje_drag_h_start(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1553{
1554 Smart_Data *sd;
1555
1556 sd = data;
1557 _smart_scrollbar_read(sd);
1558 _smart_drag_start(sd->smart_obj);
1559 sd->freeze = EINA_TRUE;
1560}
1561
1562static void
1563_smart_edje_drag_h_stop(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1564{
1565 Smart_Data *sd;
1566
1567 sd = data;
1568 _smart_scrollbar_read(sd);
1569 _smart_drag_stop(sd->smart_obj);
1570 sd->freeze = EINA_FALSE;
1571}
1572
1573static void
1574_smart_edje_drag_h(void *data, Evas_Object *obj __UNUSED__, const char *emission __UNUSED__, const char *source __UNUSED__)
1575{
1576 Smart_Data *sd;
1577
1578 sd = data;
1579 _smart_scrollbar_read(sd);
1580}
1581
1582static void
1583_smart_child_del_hook(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1584{
1585 Smart_Data *sd;
1586
1587 sd = data;
1588 sd->child_obj = NULL;
1589 _smart_scrollbar_size_adjust(sd);
1590 _smart_scrollbar_reset(sd);
1591}
1592
1593static void
1594_smart_pan_changed_hook(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
1595{
1596 Evas_Coord w, h;
1597 Smart_Data *sd;
1598
1599 sd = data;
1600 sd->pan_func.child_size_get(sd->pan_obj, &w, &h);
1601 if ((w != sd->child.w) || (h != sd->child.h))
1602 {
1603 sd->child.w = w;
1604 sd->child.h = h;
1605 _smart_scrollbar_size_adjust(sd);
1606 evas_object_size_hint_min_set(sd->smart_obj, sd->child.w, sd->child.h);
1607 sd->child.resized = EINA_TRUE;
1608 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1609 }
1610}
1611
1612void
1613elm_smart_scroller_gravity_set(Evas_Object *obj, double x, double y)
1614{
1615 API_ENTRY return;
1616
1617 sd->pan_func.gravity_set(sd->pan_obj, x, y);
1618}
1619
1620void
1621elm_smart_scroller_gravity_get(Evas_Object *obj, double *x, double *y)
1622{
1623 API_ENTRY return;
1624
1625 sd->pan_func.gravity_get(sd->pan_obj, x, y);
1626}
1627
1628static void
1629_smart_event_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1630{
1631 Evas_Event_Mouse_Wheel *ev;
1632 Smart_Data *sd;
1633 Evas_Coord x = 0, y = 0;
1634 int direction = 0;
1635
1636 sd = data;
1637 ev = event_info;
1638 direction = ev->direction;
1639 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1640 if ((evas_key_modifier_is_set(ev->modifiers, "Control")) ||
1641 (evas_key_modifier_is_set(ev->modifiers, "Alt")) ||
1642 (evas_key_modifier_is_set(ev->modifiers, "Meta")) ||
1643 (evas_key_modifier_is_set(ev->modifiers, "Hyper")) ||
1644 (evas_key_modifier_is_set(ev->modifiers, "Super")))
1645 return;
1646 else if (evas_key_modifier_is_set(ev->modifiers, "Shift"))
1647 direction = 1;
1648 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
1649 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
1650 (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
1651 {
1652 _smart_anim_stop(sd->smart_obj);
1653 }
1654 if (sd->scrollto.x.animator)
1655 {
1656 ecore_animator_del(sd->scrollto.x.animator);
1657 sd->scrollto.x.animator = NULL;
1658 }
1659 if (sd->scrollto.y.animator)
1660 {
1661 ecore_animator_del(sd->scrollto.y.animator);
1662 sd->scrollto.y.animator = NULL;
1663 }
1664 if (sd->down.bounce_x_animator)
1665 {
1666 ecore_animator_del(sd->down.bounce_x_animator);
1667 sd->down.bounce_x_animator = NULL;
1668 sd->bouncemex = EINA_FALSE;
1669 if (sd->child.resized)
1670 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1671 }
1672 if (sd->down.bounce_y_animator)
1673 {
1674 ecore_animator_del(sd->down.bounce_y_animator);
1675 sd->down.bounce_y_animator = NULL;
1676 sd->bouncemey = EINA_FALSE;
1677 if (sd->child.resized)
1678 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1679 }
1680 if (!direction)
1681 y += ev->z * sd->step.y;
1682 else if (direction == 1)
1683 x += ev->z * sd->step.x;
1684
1685 if ((!sd->hold) && (!sd->freeze))
1686 {
1687 _update_wanted_coordinates(sd, x, y);
1688 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
1689 }
1690}
1691
1692static void
1693_smart_event_mouse_down(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
1694{
1695 Evas_Event_Mouse_Down *ev;
1696 Smart_Data *sd;
1697 Evas_Coord x = 0, y = 0;
1698
1699 sd = data;
1700 ev = event_info;
1701 // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1702 if (_elm_config->thumbscroll_enable)
1703 {
1704 sd->down.hold = EINA_FALSE;
1705 if ((sd->down.bounce_x_animator) || (sd->down.bounce_y_animator) ||
1706 (sd->down.momentum_animator) || (sd->scrollto.x.animator) ||
1707 (sd->scrollto.y.animator))
1708 {
1709 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL | EVAS_EVENT_FLAG_ON_HOLD;
1710 sd->down.scroll = EINA_TRUE;
1711 sd->down.hold = EINA_TRUE;
1712 _smart_anim_stop(sd->smart_obj);
1713 }
1714 if (sd->scrollto.x.animator)
1715 {
1716 ecore_animator_del(sd->scrollto.x.animator);
1717 sd->scrollto.x.animator = NULL;
1718 }
1719 if (sd->scrollto.y.animator)
1720 {
1721 ecore_animator_del(sd->scrollto.y.animator);
1722 sd->scrollto.y.animator = NULL;
1723 }
1724 if (sd->down.bounce_x_animator)
1725 {
1726 ecore_animator_del(sd->down.bounce_x_animator);
1727 sd->down.bounce_x_animator = NULL;
1728 sd->bouncemex = EINA_FALSE;
1729 if (sd->child.resized)
1730 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1731 }
1732 if (sd->down.bounce_y_animator)
1733 {
1734 ecore_animator_del(sd->down.bounce_y_animator);
1735 sd->down.bounce_y_animator = NULL;
1736 sd->bouncemey = EINA_FALSE;
1737 if (sd->child.resized)
1738 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1739 }
1740 if (sd->down.hold_animator)
1741 {
1742 ecore_animator_del(sd->down.hold_animator);
1743 sd->down.hold_animator = NULL;
1744 _smart_drag_stop(sd->smart_obj);
1745 if (sd->child.resized)
1746 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1747 }
1748 if (sd->down.momentum_animator)
1749 {
1750 ecore_animator_del(sd->down.momentum_animator);
1751 sd->down.momentum_animator = NULL;
1752 sd->down.bounce_x_hold = EINA_FALSE;
1753 sd->down.bounce_y_hold = EINA_FALSE;
1754 sd->down.ax = 0;
1755 sd->down.ay = 0;
1756 if (sd->child.resized)
1757 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1758 }
1759 if (ev->button == 1)
1760 {
1761 sd->down.hist.est_timestamp_diff =
1762 ecore_loop_time_get() - ((double)ev->timestamp / 1000.0);
1763 sd->down.hist.tadd = 0.0;
1764 sd->down.hist.dxsum = 0.0;
1765 sd->down.hist.dysum = 0.0;
1766 sd->down.now = EINA_TRUE;
1767 sd->down.dragged = EINA_FALSE;
1768 sd->down.dir_x = EINA_FALSE;
1769 sd->down.dir_y = EINA_FALSE;
1770 sd->down.x = ev->canvas.x;
1771 sd->down.y = ev->canvas.y;
1772 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
1773 sd->down.sx = x;
1774 sd->down.sy = y;
1775 sd->down.locked = EINA_FALSE;
1776 memset(&(sd->down.history[0]), 0, sizeof(sd->down.history[0]) * 60);
1777#ifdef EVTIME
1778 sd->down.history[0].timestamp = ev->timestamp / 1000.0;
1779 sd->down.history[0].localtimestamp = ecore_loop_time_get();
1780#else
1781 sd->down.history[0].timestamp = ecore_loop_time_get();
1782#endif
1783 sd->down.history[0].x = ev->canvas.x;
1784 sd->down.history[0].y = ev->canvas.y;
1785 }
1786 sd->down.dragged_began = EINA_FALSE;
1787 sd->down.hold_parent = EINA_FALSE;
1788 sd->down.cancelled = EINA_FALSE;
1789 if (sd->hold || sd->freeze)
1790 sd->down.want_reset = EINA_TRUE;
1791 else
1792 sd->down.want_reset = EINA_FALSE;
1793 }
1794}
1795
1796static void
1797_down_coord_eval(Smart_Data *sd, Evas_Coord *x, Evas_Coord *y)
1798{
1799 Evas_Coord minx, miny;
1800
1801 if (sd->down.dir_x) *x = sd->down.sx - (*x - sd->down.x);
1802 else *x = sd->down.sx;
1803 if (sd->down.dir_y) *y = sd->down.sy - (*y - sd->down.y);
1804 else *y = sd->down.sy;
1805
1806 if ((sd->down.dir_x) || (sd->down.dir_y))
1807 {
1808 if (!((sd->down.dir_x) && (sd->down.dir_y)))
1809 {
1810 if (sd->down.dir_x) *y = sd->down.locked_y;
1811 else *x = sd->down.locked_x;
1812 }
1813 }
1814
1815 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
1816
1817 if (*x < minx)
1818 *x += (minx - *x) * _elm_config->thumbscroll_border_friction;
1819 else if (sd->child.w <= sd->w)
1820 *x += (sd->down.sx - *x) * _elm_config->thumbscroll_border_friction;
1821 else if ((sd->child.w - sd->w + minx) < *x)
1822 *x += (sd->child.w - sd->w + minx - *x) *
1823 _elm_config->thumbscroll_border_friction;
1824
1825 if (*y < miny)
1826 *y += (miny - *y) * _elm_config->thumbscroll_border_friction;
1827 else if (sd->child.h <= sd->h)
1828 *y += (sd->down.sy - *y) * _elm_config->thumbscroll_border_friction;
1829 else if ((sd->child.h - sd->h + miny) < *y)
1830 *y += (sd->child.h - sd->h + miny - *y) *
1831 _elm_config->thumbscroll_border_friction;
1832}
1833
1834static Eina_Bool
1835_smart_hold_animator(void *data)
1836{
1837 Smart_Data *sd = data;
1838 Evas_Coord ox = 0, oy = 0, fx = 0, fy= 0;
1839
1840 fx = sd->down.hold_x;
1841 fy = sd->down.hold_y;
1842 if (_elm_config->scroll_smooth_amount > 0.0)
1843 {
1844 int i, count = 0;
1845 Evas_Coord basex = 0, basey = 0, x, y;
1846 double dt, t, tdiff, tnow, twin;
1847 struct
1848 {
1849 Evas_Coord x, y, dx, dy;
1850 double t, dt;
1851 } pos[60];
1852
1853 tdiff = sd->down.hist.est_timestamp_diff;
1854 tnow = ecore_time_get() - tdiff;
1855 t = tnow;
1856 twin = _elm_config->scroll_smooth_time_window;
1857 for (i = 0; i < 60; i++)
1858 {
1859 // oldest point is sd->down.history[i]
1860 // newset is sd->down.history[0]
1861 dt = t - sd->down.history[i].timestamp;
1862 if (dt > twin)
1863 {
1864 i--;
1865 break;
1866 }
1867 x = sd->down.history[i].x;
1868 y = sd->down.history[i].y;
1869 _down_coord_eval(sd, &x, &y);
1870 if (i == 0)
1871 {
1872 basex = x;
1873 basey = y;
1874 }
1875 pos[i].x = x - basex;
1876 pos[i].y = y - basey;
1877 pos[i].t =
1878 sd->down.history[i].timestamp - sd->down.history[0].timestamp;
1879 count++;
1880 }
1881 count = i;
1882 if (count >= 2)
1883 {
1884 double dtsum = 0.0, tadd, maxdt;
1885 double dxsum = 0.0, dysum = 0.0, xsum = 0.0, ysum = 0.0;
1886
1887 for (i = 0; i < (count - 1); i++)
1888 {
1889 pos[i].dx = pos[i].x - pos[i + 1].x;
1890 pos[i].dy = pos[i].y - pos[i + 1].y;
1891 pos[i].dt = pos[i].t - pos[i + 1].t;
1892 dxsum += pos[i].dx;
1893 dysum += pos[i].dy;
1894 dtsum += pos[i].dt;
1895 xsum += pos[i].x;
1896 ysum += pos[i].y;
1897 }
1898 maxdt = pos[i].t;
1899 dxsum /= (double)i;
1900 dysum /= (double)i;
1901 dtsum /= (double)i;
1902 xsum /= (double)i;
1903 ysum /= (double)i;
1904 tadd = tnow - sd->down.history[0].timestamp + _elm_config->scroll_smooth_future_time;
1905 tadd = tadd - (maxdt / 2);
1906#define WEIGHT(n, o, v) n = (((double)o * (1.0 - v)) + ((double)n * v))
1907 WEIGHT(tadd, sd->down.hist.tadd, _elm_config->scroll_smooth_history_weight);
1908 WEIGHT(dxsum, sd->down.hist.dxsum, _elm_config->scroll_smooth_history_weight);
1909 WEIGHT(dysum, sd->down.hist.dysum, _elm_config->scroll_smooth_history_weight);
1910 fx = basex + xsum + ((dxsum * tadd) / dtsum);
1911 fy = basey + ysum + ((dysum * tadd) / dtsum);
1912 sd->down.hist.tadd = tadd;
1913 sd->down.hist.dxsum = dxsum;
1914 sd->down.hist.dysum = dysum;
1915 WEIGHT(fx, sd->down.hold_x, _elm_config->scroll_smooth_amount);
1916 WEIGHT(fy, sd->down.hold_y, _elm_config->scroll_smooth_amount);
1917 }
1918 // printf("%3.5f %i %i\n", ecore_time_get(), sd->down.hold_y, fy);
1919 }
1920
1921 elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
1922 if (sd->down.dir_x)
1923 {
1924 if ((!sd->widget) ||
1925 (!elm_widget_drag_child_locked_x_get(sd->widget)))
1926 ox = fx;
1927 }
1928 if (sd->down.dir_y)
1929 {
1930 if ((!sd->widget) ||
1931 (!elm_widget_drag_child_locked_y_get(sd->widget)))
1932 oy = fy;
1933 }
1934
1935 elm_smart_scroller_child_pos_set(sd->smart_obj, ox, oy);
1936 return ECORE_CALLBACK_RENEW;
1937}
1938
1939static Eina_Bool
1940_smart_event_post_up(void *data, Evas *e __UNUSED__)
1941{
1942 Smart_Data *sd = data;
1943 if (sd->widget)
1944 {
1945 if (sd->down.dragged)
1946 {
1947 elm_widget_drag_lock_x_set(sd->widget, 0);
1948 elm_widget_drag_lock_y_set(sd->widget, 0);
1949 }
1950 }
1951 return EINA_TRUE;
1952}
1953
1954static void
1955_smart_event_mouse_up(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
1956{
1957 Evas_Event_Mouse_Down *ev;
1958 Smart_Data *sd;
1959 Evas_Coord x = 0, y = 0, ox = 0, oy = 0;
1960
1961 sd = data;
1962 ev = event_info;
1963 sd->down.hold_parent = EINA_FALSE;
1964 sd->down.dx = 0;
1965 sd->down.dy = 0;
1966 // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
1967 evas_post_event_callback_push(e, _smart_event_post_up, sd);
1968 // FIXME: respect elm_widget_scroll_hold_get of parent container
1969 if (_elm_config->thumbscroll_enable)
1970 {
1971 if (ev->button == 1)
1972 {
1973 if (sd->down.onhold_animator)
1974 {
1975 ecore_animator_del(sd->down.onhold_animator);
1976 sd->down.onhold_animator = NULL;
1977 if (sd->child.resized)
1978 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
1979 }
1980 x = ev->canvas.x - sd->down.x;
1981 y = ev->canvas.y - sd->down.y;
1982 if (sd->down.dragged)
1983 {
1984 _smart_drag_stop(sd->smart_obj);
1985 if ((!sd->hold) && (!sd->freeze))
1986 {
1987 double t, at, dt;
1988 int i;
1989 Evas_Coord ax, ay, dx, dy, vel;
1990
1991#ifdef EVTIME
1992 t = ev->timestamp / 1000.0;
1993#else
1994 t = ecore_loop_time_get();
1995#endif
1996 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
1997 ax = ev->canvas.x;
1998 ay = ev->canvas.y;
1999 at = 0.0;
2000#ifdef SCROLLDBG
2001 printf("------ %i %i\n", ev->canvas.x, ev->canvas.y);
2002#endif
2003 for (i = 0; i < 60; i++)
2004 {
2005 dt = t - sd->down.history[i].timestamp;
2006 if (dt > 0.2) break;
2007#ifdef SCROLLDBG
2008 printf("H: %i %i @ %1.3f\n",
2009 sd->down.history[i].x,
2010 sd->down.history[i].y, dt);
2011#endif
2012 at += dt;
2013 ax += sd->down.history[i].x;
2014 ay += sd->down.history[i].y;
2015 }
2016 ax /= (i + 1);
2017 ay /= (i + 1);
2018 at /= (i + 1);
2019 at /= _elm_config->thumbscroll_sensitivity_friction;
2020 dx = ev->canvas.x - ax;
2021 dy = ev->canvas.y - ay;
2022 if (at > 0)
2023 {
2024 vel = sqrt((dx * dx) + (dy * dy)) / at;
2025 if ((_elm_config->thumbscroll_friction > 0.0) &&
2026 (vel > _elm_config->thumbscroll_momentum_threshold))
2027 {
2028 int minx, miny, mx, my, px, py;
2029 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2030 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
2031 sd->pan_func.get(sd->pan_obj, &px, &py);
2032 sd->down.dx = ((double)dx / at);
2033 sd->down.dy = ((double)dy / at);
2034 if (((sd->down.dx > 0) && (sd->down.pdx > 0)) ||
2035 ((sd->down.dx < 0) && (sd->down.pdx < 0)))
2036 if (px > minx && px < mx)
2037 sd->down.dx += (double)sd->down.pdx * 1.5; // FIXME: * 1.5 - probably should be config
2038 if (((sd->down.dy > 0) && (sd->down.pdy > 0)) ||
2039 ((sd->down.dy < 0) && (sd->down.pdy < 0)))
2040 if (py > miny && py < my)
2041 sd->down.dy += (double)sd->down.pdy * 1.5; // FIXME: * 1.5 - probably should be config
2042 if (((sd->down.dx > 0) && (sd->down.pdx > 0)) ||
2043 ((sd->down.dx < 0) && (sd->down.pdx < 0)) ||
2044 ((sd->down.dy > 0) && (sd->down.pdy > 0)) ||
2045 ((sd->down.dy < 0) && (sd->down.pdy < 0)))
2046 {
2047 double tt = ecore_loop_time_get();
2048 double dtt = tt - sd->down.anim_start;
2049
2050 if (dtt < 0.0) dtt = 0.0;
2051 else if (dtt > _elm_config->thumbscroll_friction)
2052 dtt = _elm_config->thumbscroll_friction;
2053 sd->down.extra_time = _elm_config->thumbscroll_friction - dtt;
2054 }
2055 else
2056 sd->down.extra_time = 0.0;
2057 sd->down.pdx = sd->down.dx;
2058 sd->down.pdy = sd->down.dy;
2059 ox = -sd->down.dx;
2060 oy = -sd->down.dy;
2061 if (!_smart_do_page(sd))
2062 {
2063 if ((!sd->down.momentum_animator) && (!sd->momentum_animator_disabled))
2064 {
2065 sd->down.momentum_animator = ecore_animator_add(_smart_momentum_animator, sd);
2066 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2067 _smart_anim_start(sd->smart_obj);
2068 }
2069 sd->down.anim_start = ecore_loop_time_get();
2070 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2071 sd->down.sx = x;
2072 sd->down.sy = y;
2073 sd->down.b0x = 0;
2074 sd->down.b0y = 0;
2075 }
2076 }
2077 }
2078 }
2079 else
2080 {
2081 sd->down.pdx = 0;
2082 sd->down.pdy = 0;
2083 }
2084 evas_event_feed_hold(e, 0, ev->timestamp, ev->data);
2085 if (_smart_do_page(sd))
2086 {
2087 Evas_Coord pgx, pgy;
2088
2089 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2090 if ((!sd->widget) ||
2091 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2092 {
2093 pgx = _smart_page_x_get(sd, ox);
2094 if (pgx != x)
2095 {
2096 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2097 _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
2098 }
2099 }
2100 if ((!sd->widget) ||
2101 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2102 {
2103 pgy = _smart_page_y_get(sd, oy);
2104 if (pgy != y)
2105 {
2106 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2107 _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
2108 }
2109 }
2110 }
2111 }
2112 else
2113 {
2114 sd->down.pdx = 0;
2115 sd->down.pdy = 0;
2116 if (_smart_do_page(sd))
2117 {
2118 Evas_Coord pgx, pgy;
2119
2120 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2121 if ((!sd->widget) ||
2122 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2123 {
2124 pgx = _smart_page_x_get(sd, ox);
2125 if (pgx != x) _smart_scrollto_x(sd, _elm_config->page_scroll_friction, pgx);
2126 }
2127 if ((!sd->widget) ||
2128 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2129 {
2130 pgy = _smart_page_y_get(sd, oy);
2131 if (pgy != y) _smart_scrollto_y(sd, _elm_config->page_scroll_friction, pgy);
2132 }
2133 }
2134 }
2135 if (sd->down.hold_animator)
2136 {
2137 ecore_animator_del(sd->down.hold_animator);
2138 sd->down.hold_animator = NULL;
2139 if (sd->child.resized)
2140 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2141 }
2142 if (sd->down.scroll)
2143 {
2144 ev->event_flags |= EVAS_EVENT_FLAG_ON_SCROLL;
2145 sd->down.scroll = EINA_FALSE;
2146 }
2147 if (sd->down.hold)
2148 {
2149 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2150 sd->down.hold = EINA_FALSE;
2151 }
2152 sd->down.dragged_began = EINA_FALSE;
2153 sd->down.dir_x = EINA_FALSE;
2154 sd->down.dir_y = EINA_FALSE;
2155 sd->down.want_dragged = EINA_FALSE;
2156 sd->down.dragged = EINA_FALSE;
2157 sd->down.now = EINA_FALSE;
2158 elm_smart_scroller_child_pos_get(sd->smart_obj, &x, &y);
2159 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
2160 _update_wanted_coordinates(sd, x, y);
2161
2162 if (sd->child.resized)
2163 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2164
2165 if (!_smart_do_page(sd))
2166 bounce_eval(sd);
2167 }
2168 }
2169}
2170
2171static Eina_Bool
2172_smart_onhold_animator(void *data)
2173{
2174 Smart_Data *sd;
2175 double t, td;
2176 double vx, vy;
2177 Evas_Coord x, y, ox, oy;
2178
2179 sd = data;
2180 t = ecore_loop_time_get();
2181 if (sd->down.onhold_tlast > 0.0)
2182 {
2183 td = t - sd->down.onhold_tlast;
2184 vx = sd->down.onhold_vx * td * (double)_elm_config->thumbscroll_threshold * 2.0;
2185 vy = sd->down.onhold_vy * td * (double)_elm_config->thumbscroll_threshold * 2.0;
2186 elm_smart_scroller_child_pos_get(sd->smart_obj, &ox, &oy);
2187 x = ox;
2188 y = oy;
2189
2190 if (sd->down.dir_x)
2191 {
2192 if ((!sd->widget) ||
2193 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2194 {
2195 sd->down.onhold_vxe += vx;
2196 x = ox + (int)sd->down.onhold_vxe;
2197 sd->down.onhold_vxe -= (int)sd->down.onhold_vxe;
2198 }
2199 }
2200
2201 if (sd->down.dir_y)
2202 {
2203 if ((!sd->widget) ||
2204 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2205 {
2206 sd->down.onhold_vye += vy;
2207 y = oy + (int)sd->down.onhold_vye;
2208 sd->down.onhold_vye -= (int)sd->down.onhold_vye;
2209 }
2210 }
2211
2212 elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
2213 }
2214 sd->down.onhold_tlast = t;
2215 return ECORE_CALLBACK_RENEW;
2216}
2217
2218static Eina_Bool
2219_smart_event_post_move(void *data, Evas *e __UNUSED__)
2220{
2221 Smart_Data *sd = data;
2222
2223 if (sd->down.want_dragged)
2224 {
2225 int start = 0;
2226
2227 if (sd->down.hold_parent)
2228 {
2229 if ((sd->down.dir_x) && !can_scroll(sd, sd->down.hdir))
2230 {
2231 sd->down.dir_x = EINA_FALSE;
2232 }
2233 if ((sd->down.dir_y) && !can_scroll(sd, sd->down.vdir))
2234 {
2235 sd->down.dir_y = EINA_FALSE;
2236 }
2237 }
2238 if (sd->down.dir_x)
2239 {
2240 if ((!sd->widget) ||
2241 (!elm_widget_drag_child_locked_x_get(sd->widget)))
2242 {
2243 sd->down.want_dragged = EINA_FALSE;
2244 sd->down.dragged = EINA_TRUE;
2245 if (sd->widget)
2246 {
2247 elm_widget_drag_lock_x_set(sd->widget, 1);
2248 }
2249 start = 1;
2250 }
2251 else
2252 sd->down.dir_x = EINA_FALSE;
2253 }
2254 if (sd->down.dir_y)
2255 {
2256 if ((!sd->widget) ||
2257 (!elm_widget_drag_child_locked_y_get(sd->widget)))
2258 {
2259 sd->down.want_dragged = EINA_FALSE;
2260 sd->down.dragged = EINA_TRUE;
2261 if (sd->widget)
2262 {
2263 elm_widget_drag_lock_y_set(sd->widget, 1);
2264 }
2265 start = 1;
2266 }
2267 else
2268 sd->down.dir_y = EINA_FALSE;
2269 }
2270 if ((!sd->down.dir_x) && (!sd->down.dir_y))
2271 {
2272 sd->down.cancelled = EINA_TRUE;
2273 }
2274 if (start) _smart_drag_start(sd->smart_obj);
2275 }
2276 return EINA_TRUE;
2277}
2278
2279static void
2280_smart_event_mouse_move(void *data, Evas *e, Evas_Object *obj __UNUSED__, void *event_info)
2281{
2282 Evas_Event_Mouse_Move *ev;
2283 Smart_Data *sd;
2284 Evas_Coord x = 0, y = 0;
2285
2286 sd = data;
2287 ev = event_info;
2288 // if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD) return ;
2289 if (ev->event_flags & EVAS_EVENT_FLAG_ON_HOLD)
2290 sd->down.hold_parent = EINA_TRUE;
2291 evas_post_event_callback_push(e, _smart_event_post_move, sd);
2292
2293 // FIXME: respect elm_widget_scroll_hold_get of parent container
2294 if (_elm_config->thumbscroll_enable)
2295 {
2296 if (sd->down.now)
2297 {
2298 int dodir = 0;
2299
2300 if ((sd->scrollto.x.animator) && (!sd->hold) && (!sd->freeze))
2301 {
2302 Evas_Coord px;
2303 ecore_animator_del(sd->scrollto.x.animator);
2304 sd->scrollto.x.animator = NULL;
2305 sd->pan_func.get(sd->pan_obj, &px, NULL);
2306 sd->down.sx = px;
2307 sd->down.x = sd->down.history[0].x;
2308 }
2309
2310 if ((sd->scrollto.y.animator) && (!sd->hold) && (!sd->freeze))
2311 {
2312 Evas_Coord py;
2313 ecore_animator_del(sd->scrollto.y.animator);
2314 sd->scrollto.y.animator = NULL;
2315 sd->pan_func.get(sd->pan_obj, NULL, &py);
2316 sd->down.sy = py;
2317 sd->down.y = sd->down.history[0].y;
2318 }
2319
2320#ifdef SCROLLDBG
2321 printf("::: %i %i\n", ev->cur.canvas.x, ev->cur.canvas.y);
2322#endif
2323 memmove(&(sd->down.history[1]), &(sd->down.history[0]),
2324 sizeof(sd->down.history[0]) * (60 - 1));
2325#ifdef EVTIME
2326 sd->down.history[0].timestamp = ev->timestamp / 1000.0;
2327 sd->down.history[0].localtimestamp = ecore_loop_time_get();
2328#else
2329 sd->down.history[0].timestamp = ecore_loop_time_get();
2330#endif
2331 sd->down.history[0].x = ev->cur.canvas.x;
2332 sd->down.history[0].y = ev->cur.canvas.y;
2333
2334 if (!sd->down.dragged_began)
2335 {
2336 x = ev->cur.canvas.x - sd->down.x;
2337 y = ev->cur.canvas.y - sd->down.y;
2338
2339 sd->down.hdir = -1;
2340 sd->down.vdir = -1;
2341
2342 if (x > 0) sd->down.hdir = LEFT;
2343 else if (x < 0) sd->down.hdir = RIGHT;
2344 if (y > 0) sd->down.vdir = UP;
2345 else if (y < 0) sd->down.vdir = DOWN;
2346
2347 if (x < 0) x = -x;
2348 if (y < 0) y = -y;
2349
2350 if ((sd->one_dir_at_a_time) &&
2351 (!((sd->down.dir_x) || (sd->down.dir_y))))
2352 {
2353 if (x > _elm_config->thumbscroll_threshold)
2354 {
2355 if (x > (y * 2))
2356 {
2357 sd->down.dir_x = EINA_TRUE;
2358 sd->down.dir_y = EINA_FALSE;
2359 dodir++;
2360 }
2361 }
2362 if (y > _elm_config->thumbscroll_threshold)
2363 {
2364 if (y > (x * 2))
2365 {
2366 sd->down.dir_x = EINA_FALSE;
2367 sd->down.dir_y = EINA_TRUE;
2368 dodir++;
2369 }
2370 }
2371 if (!dodir)
2372 {
2373 sd->down.dir_x = EINA_TRUE;
2374 sd->down.dir_y = EINA_TRUE;
2375 }
2376 }
2377 else
2378 {
2379 sd->down.dir_x = EINA_TRUE;
2380 sd->down.dir_y = EINA_TRUE;
2381 }
2382 }
2383 if ((!sd->hold) && (!sd->freeze))
2384 {
2385 if ((sd->down.dragged) ||
2386 (((x * x) + (y * y)) >
2387 (_elm_config->thumbscroll_threshold *
2388 _elm_config->thumbscroll_threshold)))
2389 {
2390 sd->down.dragged_began = EINA_TRUE;
2391 if (!sd->down.dragged)
2392 {
2393 sd->down.want_dragged = EINA_TRUE;
2394 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2395 // evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
2396 // _smart_drag_start(sd->smart_obj);
2397 }
2398 if (sd->down.dragged)
2399 {
2400 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2401 }
2402 // ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2403 // sd->down.dragged = 1;
2404 if (sd->down.dir_x)
2405 x = sd->down.sx - (ev->cur.canvas.x - sd->down.x);
2406 else
2407 x = sd->down.sx;
2408 if (sd->down.dir_y)
2409 y = sd->down.sy - (ev->cur.canvas.y - sd->down.y);
2410 else
2411 y = sd->down.sy;
2412 if (sd->down.want_reset)
2413 {
2414 sd->down.x = ev->cur.canvas.x;
2415 sd->down.y = ev->cur.canvas.y;
2416 sd->down.want_reset = EINA_FALSE;
2417 }
2418 if ((sd->down.dir_x) || (sd->down.dir_y))
2419 {
2420 if (!sd->down.locked)
2421 {
2422 sd->down.locked_x = x;
2423 sd->down.locked_y = y;
2424 sd->down.locked = EINA_TRUE;
2425 }
2426 if (!((sd->down.dir_x) && (sd->down.dir_y)))
2427 {
2428 if (sd->down.dir_x) y = sd->down.locked_y;
2429 else x = sd->down.locked_x;
2430 }
2431 }
2432 {
2433 Evas_Coord minx, miny;
2434 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2435 if (y < miny)
2436 y += (miny - y) *
2437 _elm_config->thumbscroll_border_friction;
2438 else if (sd->child.h <= sd->h)
2439 y += (sd->down.sy - y) *
2440 _elm_config->thumbscroll_border_friction;
2441 else if ((sd->child.h - sd->h + miny) < y)
2442 y += (sd->child.h - sd->h + miny - y) *
2443 _elm_config->thumbscroll_border_friction;
2444 if (x < minx)
2445 x += (minx - x) *
2446 _elm_config->thumbscroll_border_friction;
2447 else if (sd->child.w <= sd->w)
2448 x += (sd->down.sx - x) *
2449 _elm_config->thumbscroll_border_friction;
2450 else if ((sd->child.w - sd->w + minx) < x)
2451 x += (sd->child.w - sd->w + minx - x) *
2452 _elm_config->thumbscroll_border_friction;
2453 }
2454
2455 sd->down.hold_x = x;
2456 sd->down.hold_y = y;
2457 if (!sd->down.hold_animator)
2458 sd->down.hold_animator =
2459 ecore_animator_add(_smart_hold_animator, sd);
2460 // printf("a %i %i\n", sd->down.hold_x, sd->down.hold_y);
2461 // _smart_onhold_animator(sd);
2462 // elm_smart_scroller_child_pos_set(sd->smart_obj, x, y);
2463 }
2464 else
2465 {
2466 if (sd->down.dragged_began)
2467 {
2468 ev->event_flags |= EVAS_EVENT_FLAG_ON_HOLD;
2469 if (!sd->down.hold)
2470 {
2471 sd->down.hold = EINA_TRUE;
2472 evas_event_feed_hold(e, 1, ev->timestamp, ev->data);
2473 }
2474 }
2475 }
2476 }
2477 else if (!sd->freeze)
2478 {
2479 Evas_Coord ex, ey, ew, eh;
2480 double vx = 0.0, vy = 0.0;
2481
2482 evas_object_geometry_get(sd->event_obj, &ex, &ey, &ew, &eh);
2483 x = ev->cur.canvas.x - ex;
2484 y = ev->cur.canvas.y - ey;
2485 if (x < _elm_config->thumbscroll_threshold)
2486 {
2487 if (_elm_config->thumbscroll_threshold > 0.0)
2488 vx = -(double)(_elm_config->thumbscroll_threshold - x) /
2489 _elm_config->thumbscroll_threshold;
2490 else
2491 vx = -1.0;
2492 }
2493 else if (x > (ew - _elm_config->thumbscroll_threshold))
2494 {
2495 if (_elm_config->thumbscroll_threshold > 0.0)
2496 vx = (double)(_elm_config->thumbscroll_threshold - (ew - x)) /
2497 _elm_config->thumbscroll_threshold;
2498 else
2499 vx = 1.0;
2500 }
2501 if (y < _elm_config->thumbscroll_threshold)
2502 {
2503 if (_elm_config->thumbscroll_threshold > 0.0)
2504 vy = -(double)(_elm_config->thumbscroll_threshold - y) /
2505 _elm_config->thumbscroll_threshold;
2506 else
2507 vy = -1.0;
2508 }
2509 else if (y > (eh - _elm_config->thumbscroll_threshold))
2510 {
2511 if (_elm_config->thumbscroll_threshold > 0.0)
2512 vy = (double)(_elm_config->thumbscroll_threshold - (eh - y)) /
2513 _elm_config->thumbscroll_threshold;
2514 else
2515 vy = 1.0;
2516 }
2517 if ((vx != 0.0) || (vy != 0.0))
2518 {
2519 sd->down.onhold_vx = vx;
2520 sd->down.onhold_vy = vy;
2521 if (!sd->down.onhold_animator)
2522 {
2523 sd->down.onhold_vxe = 0.0;
2524 sd->down.onhold_vye = 0.0;
2525 sd->down.onhold_tlast = 0.0;
2526 sd->down.onhold_animator = ecore_animator_add(_smart_onhold_animator, sd);
2527 }
2528 // printf("b %i %i\n", sd->down.hold_x, sd->down.hold_y);
2529 }
2530 else
2531 {
2532 if (sd->down.onhold_animator)
2533 {
2534 ecore_animator_del(sd->down.onhold_animator);
2535 sd->down.onhold_animator = NULL;
2536 if (sd->child.resized)
2537 _elm_smart_scroller_wanted_region_set(sd->smart_obj);
2538 }
2539 }
2540 }
2541 }
2542 }
2543}
2544
2545static void
2546_smart_scrollbar_read(Smart_Data *sd)
2547{
2548 Evas_Coord x, y, mx = 0, my = 0, px, py, minx = 0, miny = 0;
2549 double vx, vy;
2550
2551 if ((sd->down.dragged) || (sd->down.bounce_x_animator)
2552 || (sd->down.bounce_y_animator) || (sd->down.momentum_animator)
2553 || (sd->scrollto.x.animator) || (sd->scrollto.y.animator))
2554 return;
2555 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
2556 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
2557 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
2558 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2559 x = vx * (double)mx + minx;
2560 y = vy * (double)my + miny;
2561 sd->pan_func.get(sd->pan_obj, &px, &py);
2562 sd->pan_func.set(sd->pan_obj, x, y);
2563 if ((px != x) || (py != y))
2564 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
2565}
2566
2567static void
2568_smart_scrollbar_reset(Smart_Data *sd)
2569{
2570 Evas_Coord px = 0, py = 0, minx = 0, miny = 0;
2571
2572 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
2573 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
2574 if ((!sd->child_obj) && (!sd->extern_pan))
2575 {
2576 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
2577 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
2578 }
2579 if (sd->pan_obj)
2580 {
2581 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2582 sd->pan_func.get(sd->pan_obj, &px, &py);
2583 sd->pan_func.set(sd->pan_obj, minx, miny);
2584 }
2585 if ((px != minx) || (py != miny))
2586 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
2587}
2588
2589static int
2590_smart_scrollbar_bar_v_visibility_adjust(Smart_Data *sd)
2591{
2592 int scroll_v_vis_change = 0;
2593 Evas_Coord h, vw = 0, vh = 0;
2594
2595 h = sd->child.h;
2596 if (sd->pan_obj)
2597 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
2598 if (sd->vbar_visible)
2599 {
2600 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2601 {
2602 if ((sd->child_obj) || (sd->extern_pan))
2603 {
2604 if (h <= vh)
2605 {
2606 scroll_v_vis_change = 1;
2607 sd->vbar_visible = EINA_FALSE;
2608 }
2609 }
2610 else
2611 {
2612 scroll_v_vis_change = 1;
2613 sd->vbar_visible = EINA_FALSE;
2614 }
2615 }
2616 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
2617 {
2618 scroll_v_vis_change = 1;
2619 sd->vbar_visible = EINA_FALSE;
2620 }
2621 }
2622 else
2623 {
2624 if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2625 {
2626 if ((sd->child_obj) || (sd->extern_pan))
2627 {
2628 if (h > vh)
2629 {
2630 scroll_v_vis_change = 1;
2631 sd->vbar_visible = EINA_TRUE;
2632 }
2633 }
2634 }
2635 else if (sd->vbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
2636 {
2637 scroll_v_vis_change = 1;
2638 sd->vbar_visible = EINA_TRUE;
2639 }
2640 }
2641 if (scroll_v_vis_change)
2642 {
2643 if (sd->vbar_flags != ELM_SMART_SCROLLER_POLICY_OFF)
2644 {
2645 if (sd->vbar_visible)
2646 edje_object_signal_emit(sd->edje_obj, "elm,action,show,vbar", "elm");
2647 else
2648 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
2649 edje_object_message_signal_process(sd->edje_obj);
2650 _smart_scrollbar_size_adjust(sd);
2651 }
2652 else
2653 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,vbar", "elm");
2654 }
2655 return scroll_v_vis_change;
2656}
2657
2658static int
2659_smart_scrollbar_bar_h_visibility_adjust(Smart_Data *sd)
2660{
2661 int scroll_h_vis_change = 0;
2662 Evas_Coord w, vw = 0, vh = 0;
2663
2664 w = sd->child.w;
2665 if (sd->pan_obj)
2666 evas_object_geometry_get(sd->pan_obj, NULL, NULL, &vw, &vh);
2667 if (sd->hbar_visible)
2668 {
2669 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2670 {
2671 if ((sd->child_obj) || (sd->extern_pan))
2672 {
2673 if (w <= vw)
2674 {
2675 scroll_h_vis_change = 1;
2676 sd->hbar_visible = EINA_FALSE;
2677 }
2678 }
2679 else
2680 {
2681 scroll_h_vis_change = 1;
2682 sd->hbar_visible = EINA_FALSE;
2683 }
2684 }
2685 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_OFF)
2686 {
2687 scroll_h_vis_change = 1;
2688 sd->hbar_visible = EINA_FALSE;
2689 }
2690 }
2691 else
2692 {
2693 if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_AUTO)
2694 {
2695 if ((sd->child_obj) || (sd->extern_pan))
2696 {
2697 if (w > vw)
2698 {
2699 scroll_h_vis_change = 1;
2700 sd->hbar_visible = EINA_TRUE;
2701 }
2702 }
2703 }
2704 else if (sd->hbar_flags == ELM_SMART_SCROLLER_POLICY_ON)
2705 {
2706 scroll_h_vis_change = 1;
2707 sd->hbar_visible = EINA_TRUE;
2708 }
2709 }
2710 if (scroll_h_vis_change)
2711 {
2712 if (sd->hbar_flags != ELM_SMART_SCROLLER_POLICY_OFF)
2713 {
2714 if (sd->hbar_visible)
2715 edje_object_signal_emit(sd->edje_obj, "elm,action,show,hbar", "elm");
2716 else
2717 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
2718 edje_object_message_signal_process(sd->edje_obj);
2719 _smart_scrollbar_size_adjust(sd);
2720 }
2721 else
2722 edje_object_signal_emit(sd->edje_obj, "elm,action,hide,hbar", "elm");
2723 _smart_scrollbar_size_adjust(sd);
2724 }
2725 return scroll_h_vis_change;
2726}
2727
2728static void
2729_smart_scrollbar_bar_visibility_adjust(Smart_Data *sd)
2730{
2731 int changed = 0;
2732
2733 changed |= _smart_scrollbar_bar_h_visibility_adjust(sd);
2734 changed |= _smart_scrollbar_bar_v_visibility_adjust(sd);
2735 if (changed)
2736 {
2737 _smart_scrollbar_bar_h_visibility_adjust(sd);
2738 _smart_scrollbar_bar_v_visibility_adjust(sd);
2739 }
2740}
2741
2742static void
2743_smart_scrollbar_size_adjust(Smart_Data *sd)
2744{
2745 if ((sd->child_obj) || (sd->extern_pan))
2746 {
2747 Evas_Coord x, y, w, h, mx = 0, my = 0, vw = 0, vh = 0, px, py, minx = 0, miny = 0;
2748 double vx, vy, size;
2749
2750 edje_object_part_geometry_get(sd->edje_obj, "elm.swallow.content",
2751 NULL, NULL, &vw, &vh);
2752 w = sd->child.w;
2753 if (w < 1) w = 1;
2754 size = (double)vw / (double)w;
2755 if (size > 1.0)
2756 {
2757 size = 1.0;
2758 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.hbar", 0.0, 0.0);
2759 }
2760 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", size, 1.0);
2761
2762 h = sd->child.h;
2763 if (h < 1) h = 1;
2764 size = (double)vh / (double)h;
2765 if (size > 1.0)
2766 {
2767 size = 1.0;
2768 edje_object_part_drag_value_set(sd->edje_obj, "elm.dragable.vbar", 0.0, 0.0);
2769 }
2770 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, size);
2771
2772 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.hbar", &vx, NULL);
2773 edje_object_part_drag_value_get(sd->edje_obj, "elm.dragable.vbar", NULL, &vy);
2774 sd->pan_func.max_get(sd->pan_obj, &mx, &my);
2775 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2776 x = vx * mx + minx;
2777 y = vy * my + miny;
2778
2779 edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->step.x / (double)w, 0.0);
2780 edje_object_part_drag_step_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->step.y / (double)h);
2781 if (sd->page.x > 0)
2782 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", (double)sd->page.x / (double)w, 0.0);
2783 else
2784 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.hbar", -((double)sd->page.x * ((double)vw / (double)w)) / 100.0, 0.0);
2785 if (sd->page.y > 0)
2786 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, (double)sd->page.y / (double)h);
2787 else
2788 edje_object_part_drag_page_set(sd->edje_obj, "elm.dragable.vbar", 0.0, -((double)sd->page.y * ((double)vh / (double)h)) / 100.0);
2789
2790 sd->pan_func.get(sd->pan_obj, &px, &py);
2791 if (vx != mx) x = px;
2792 if (vy != my) y = py;
2793 sd->pan_func.set(sd->pan_obj, x, y);
2794 // if ((px != 0) || (py != 0))
2795 // edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
2796 }
2797 else
2798 {
2799 Evas_Coord px = 0, py = 0, minx = 0, miny = 0;
2800
2801 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.vbar", 1.0, 1.0);
2802 edje_object_part_drag_size_set(sd->edje_obj, "elm.dragable.hbar", 1.0, 1.0);
2803 sd->pan_func.min_get(sd->pan_obj, &minx, &miny);
2804 sd->pan_func.get(sd->pan_obj, &px, &py);
2805 sd->pan_func.set(sd->pan_obj, minx, miny);
2806 if ((px != minx) || (py != miny))
2807 edje_object_signal_emit(sd->edje_obj, "elm,action,scroll", "elm");
2808 }
2809 _smart_scrollbar_bar_visibility_adjust(sd);
2810}
2811
2812static void
2813_smart_reconfigure(Smart_Data *sd)
2814{
2815 evas_object_move(sd->edje_obj, sd->x, sd->y);
2816 evas_object_resize(sd->edje_obj, sd->w, sd->h);
2817 evas_object_move(sd->event_obj, sd->x, sd->y);
2818 evas_object_resize(sd->event_obj, sd->w, sd->h);
2819 _smart_scrollbar_size_adjust(sd);
2820 _smart_page_adjust(sd);
2821}
2822
2823static void
2824_smart_add(Evas_Object *obj)
2825{
2826 Smart_Data *sd;
2827 Evas_Object *o;
2828
2829 sd = calloc(1, sizeof(Smart_Data));
2830 if (!sd) return;
2831 evas_object_smart_data_set(obj, sd);
2832
2833 sd->smart_obj = obj;
2834 sd->x = 0;
2835 sd->y = 0;
2836 sd->w = 0;
2837 sd->h = 0;
2838 sd->step.x = 32;
2839 sd->step.y = 32;
2840 sd->page.x = -50;
2841 sd->page.y = -50;
2842 sd->hbar_flags = ELM_SMART_SCROLLER_POLICY_AUTO;
2843 sd->vbar_flags = ELM_SMART_SCROLLER_POLICY_AUTO;
2844 sd->hbar_visible = EINA_TRUE;
2845 sd->vbar_visible = EINA_TRUE;
2846
2847 sd->bounce_horiz = EINA_TRUE;
2848 sd->bounce_vert = EINA_TRUE;
2849
2850 sd->one_dir_at_a_time = EINA_TRUE;
2851 sd->momentum_animator_disabled = EINA_FALSE;
2852 sd->bounce_animator_disabled = EINA_FALSE;
2853
2854 o = edje_object_add(evas_object_evas_get(obj));
2855 evas_object_propagate_events_set(o, 0);
2856 sd->edje_obj = o;
2857 elm_smart_scroller_object_theme_set(NULL, obj, "scroller", "base", "default");
2858 edje_object_signal_callback_add(o, "drag", "elm.dragable.vbar", _smart_edje_drag_v, sd);
2859 edje_object_signal_callback_add(o, "drag,set", "elm.dragable.vbar", _smart_edje_drag_v, sd);
2860 edje_object_signal_callback_add(o, "drag,start", "elm.dragable.vbar", _smart_edje_drag_v_start, sd);
2861 edje_object_signal_callback_add(o, "drag,stop", "elm.dragable.vbar", _smart_edje_drag_v_stop, sd);
2862 edje_object_signal_callback_add(o, "drag,step", "elm.dragable.vbar", _smart_edje_drag_v, sd);
2863 edje_object_signal_callback_add(o, "drag,page", "elm.dragable.vbar", _smart_edje_drag_v, sd);
2864 edje_object_signal_callback_add(o, "drag", "elm.dragable.hbar", _smart_edje_drag_h, sd);
2865 edje_object_signal_callback_add(o, "drag,set", "elm.dragable.hbar", _smart_edje_drag_h, sd);
2866 edje_object_signal_callback_add(o, "drag,start", "elm.dragable.hbar", _smart_edje_drag_h_start, sd);
2867 edje_object_signal_callback_add(o, "drag,stop", "elm.dragable.hbar", _smart_edje_drag_h_stop, sd);
2868 edje_object_signal_callback_add(o, "drag,step", "elm.dragable.hbar", _smart_edje_drag_h, sd);
2869 edje_object_signal_callback_add(o, "drag,page", "elm.dragable.hbar", _smart_edje_drag_h, sd);
2870 evas_object_smart_member_add(o, obj);
2871
2872 o = evas_object_rectangle_add(evas_object_evas_get(obj));
2873 sd->event_obj = o;
2874 evas_object_color_set(o, 0, 0, 0, 0);
2875 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL, _smart_event_wheel, sd);
2876 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN, _smart_event_mouse_down, sd);
2877 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP, _smart_event_mouse_up, sd);
2878 evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_MOVE, _smart_event_mouse_move, sd);
2879 evas_object_smart_member_add(o, obj);
2880 evas_object_repeat_events_set(o, 1);
2881
2882 sd->pan_func.set = _elm_smart_pan_set;
2883 sd->pan_func.get = _elm_smart_pan_get;
2884 sd->pan_func.max_get = _elm_smart_pan_max_get;
2885 sd->pan_func.min_get = _elm_smart_pan_min_get;
2886 sd->pan_func.child_size_get = _elm_smart_pan_child_size_get;
2887 sd->pan_func.gravity_set = _elm_smart_pan_gravity_set;
2888 sd->pan_func.gravity_get = _elm_smart_pan_gravity_get;
2889
2890 _smart_scrollbar_reset(sd);
2891}
2892
2893static void
2894_smart_del(Evas_Object *obj)
2895{
2896 INTERNAL_ENTRY;
2897 elm_smart_scroller_child_set(obj, NULL);
2898 if (!sd->extern_pan) evas_object_del(sd->pan_obj);
2899 evas_object_del(sd->edje_obj);
2900 evas_object_del(sd->event_obj);
2901 if (sd->down.hold_animator) ecore_animator_del(sd->down.hold_animator);
2902 if (sd->down.onhold_animator) ecore_animator_del(sd->down.onhold_animator);
2903 if (sd->down.momentum_animator) ecore_animator_del(sd->down.momentum_animator);
2904 if (sd->down.bounce_x_animator) ecore_animator_del(sd->down.bounce_x_animator);
2905 if (sd->down.bounce_y_animator) ecore_animator_del(sd->down.bounce_y_animator);
2906 if (sd->scrollto.x.animator) ecore_animator_del(sd->scrollto.x.animator);
2907 if (sd->scrollto.y.animator) ecore_animator_del(sd->scrollto.y.animator);
2908 free(sd);
2909 evas_object_smart_data_set(obj, NULL);
2910}
2911
2912static void
2913_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
2914{
2915 INTERNAL_ENTRY;
2916 sd->x = x;
2917 sd->y = y;
2918 _smart_reconfigure(sd);
2919}
2920
2921static void
2922_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
2923{
2924 INTERNAL_ENTRY;
2925 sd->w = w;
2926 sd->h = h;
2927 _smart_reconfigure(sd);
2928 _elm_smart_scroller_wanted_region_set(obj);
2929}
2930
2931static void
2932_smart_show(Evas_Object *obj)
2933{
2934 INTERNAL_ENTRY;
2935 evas_object_show(sd->edje_obj);
2936 evas_object_show(sd->event_obj);
2937}
2938
2939static void
2940_smart_hide(Evas_Object *obj)
2941{
2942 INTERNAL_ENTRY;
2943 evas_object_hide(sd->edje_obj);
2944 evas_object_hide(sd->event_obj);
2945}
2946
2947static void
2948_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
2949{
2950 INTERNAL_ENTRY;
2951 evas_object_color_set(sd->edje_obj, r, g, b, a);
2952}
2953
2954static void
2955_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
2956{
2957 INTERNAL_ENTRY;
2958 evas_object_clip_set(sd->edje_obj, clip);
2959 evas_object_clip_set(sd->event_obj, clip);
2960}
2961
2962static void
2963_smart_clip_unset(Evas_Object *obj)
2964{
2965 INTERNAL_ENTRY;
2966 evas_object_clip_unset(sd->edje_obj);
2967 evas_object_clip_unset(sd->event_obj);
2968}
2969
2970/* never need to touch this */
2971
2972static void
2973_smart_init(void)
2974{
2975 if (_smart) return;
2976 {
2977 static const Evas_Smart_Class sc =
2978 {
2979 SMART_NAME,
2980 EVAS_SMART_CLASS_VERSION,
2981 _smart_add,
2982 _smart_del,
2983 _smart_move,
2984 _smart_resize,
2985 _smart_show,
2986 _smart_hide,
2987 _smart_color_set,
2988 _smart_clip_set,
2989 _smart_clip_unset,
2990 NULL,
2991 NULL,
2992 NULL,
2993 NULL,
2994 NULL,
2995 NULL,
2996 NULL
2997 };
2998 _smart = evas_smart_class_new(&sc);
2999 }
3000}
diff --git a/libraries/elementary/src/lib/els_scroller.h b/libraries/elementary/src/lib/els_scroller.h
new file mode 100644
index 0000000..5566f4e
--- /dev/null
+++ b/libraries/elementary/src/lib/els_scroller.h
@@ -0,0 +1,48 @@
1typedef enum
2{
3 ELM_SMART_SCROLLER_POLICY_AUTO,
4 ELM_SMART_SCROLLER_POLICY_ON,
5 ELM_SMART_SCROLLER_POLICY_OFF
6}
7Elm_Smart_Scroller_Policy;
8
9Evas_Object *elm_smart_scroller_add(Evas *evas);
10void elm_smart_scroller_child_set(Evas_Object *obj, Evas_Object *child);
11void 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));
12void elm_smart_scroller_custom_edje_file_set(Evas_Object *obj, char *file, char *group);
13void elm_smart_scroller_child_pos_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
14void elm_smart_scroller_child_pos_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
15void elm_smart_scroller_child_region_show(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
16void elm_smart_scroller_child_region_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
17void elm_smart_scroller_child_viewport_size_get(Evas_Object *obj, Evas_Coord *w, Evas_Coord *h);
18void elm_smart_scroller_step_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
19void elm_smart_scroller_step_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
20void elm_smart_scroller_page_size_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
21void elm_smart_scroller_page_size_get(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y);
22void elm_smart_scroller_policy_set(Evas_Object *obj, Elm_Smart_Scroller_Policy hbar, Elm_Smart_Scroller_Policy vbar);
23void elm_smart_scroller_policy_get(Evas_Object *obj, Elm_Smart_Scroller_Policy *hbar, Elm_Smart_Scroller_Policy *vbar);
24Evas_Object *elm_smart_scroller_edje_object_get(Evas_Object *obj);
25void elm_smart_scroller_single_dir_set(Evas_Object *obj, Eina_Bool single_dir);
26Eina_Bool elm_smart_scroller_single_dir_get(Evas_Object *obj);
27void elm_smart_scroller_object_theme_set(Evas_Object *parent, Evas_Object *obj, const char *clas, const char *group, const char *style);
28void elm_smart_scroller_mirrored_set(Evas_Object *obj, Eina_Bool mirrored);
29void elm_smart_scroller_hold_set(Evas_Object *obj, Eina_Bool hold);
30void elm_smart_scroller_freeze_set(Evas_Object *obj, Eina_Bool freeze);
31void elm_smart_scroller_bounce_allow_set(Evas_Object *obj, Eina_Bool horiz, Eina_Bool vert);
32void elm_smart_scroller_bounce_allow_get(const Evas_Object *obj, Eina_Bool *horiz, Eina_Bool *vert);
33void elm_smart_scroller_paging_set(Evas_Object *obj, double pagerel_h, double pagerel_v, Evas_Coord pagesize_h, Evas_Coord pagesize_v);
34void elm_smart_scroller_paging_get(Evas_Object *obj, double *pagerel_h, double *pagerel_v, Evas_Coord *pagesize_h, Evas_Coord *pagesize_v);
35void elm_smart_scroller_current_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v);
36void elm_smart_scroller_last_page_get(Evas_Object *obj, int *pagenumber_h, int *pagenumber_v);
37void elm_smart_scroller_page_show(Evas_Object *obj, int pagenumber_h, int pagenumber_v);
38void elm_smart_scroller_page_bring_in(Evas_Object *obj, int pagenumber_h, int pagenumber_v);
39void elm_smart_scroller_region_bring_in(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h);
40void elm_smart_scroller_widget_set(Evas_Object *obj, Evas_Object *wid);
41void elm_smart_scroller_gravity_set(Evas_Object *obj, double x, double y);
42void elm_smart_scroller_gravity_get(Evas_Object *obj, double *x, double *y);
43Eina_Bool elm_smart_scroller_momentum_animator_disabled_get(Evas_Object *obj);
44void elm_smart_scroller_momentum_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled);
45void elm_smart_scroller_bounce_animator_disabled_set(Evas_Object *obj, Eina_Bool disabled);
46Eina_Bool elm_smart_scroller_bounce_animator_disabled_get(Evas_Object *obj);
47Eina_Bool elm_smart_scroller_wheel_disabled_get(Evas_Object *obj);
48void elm_smart_scroller_wheel_disabled_set(Evas_Object *obj, Eina_Bool disabled);
diff --git a/libraries/elementary/src/lib/els_tooltip.c b/libraries/elementary/src/lib/els_tooltip.c
new file mode 100644
index 0000000..f1a451f
--- /dev/null
+++ b/libraries/elementary/src/lib/els_tooltip.c
@@ -0,0 +1,951 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4#ifdef ISCOMFITOR
5# define STR(X) #X
6# define STUPID(X) STR(X)
7# define TTDBG(x...) fprintf(stderr, STUPID(__LINE__)": " x)
8#else
9# define TTDBG(X...)
10#endif
11
12static const char _tooltip_key[] = "_elm_tooltip";
13
14#define ELM_TOOLTIP_GET_OR_RETURN(tt, obj, ...) \
15 Elm_Tooltip *tt; \
16 do \
17 { \
18 if (!(obj)) \
19 { \
20 CRITICAL("Null pointer: " #obj); \
21 return __VA_ARGS__; \
22 } \
23 tt = evas_object_data_get((obj), _tooltip_key); \
24 if (!tt) \
25 { \
26 ERR("Object does not have tooltip: " #obj); \
27 return __VA_ARGS__; \
28 } \
29 } \
30 while (0)
31
32struct _Elm_Tooltip
33{
34 Elm_Tooltip_Content_Cb func;
35 Evas_Smart_Cb del_cb;
36 const void *data;
37 const char *style;
38 Evas *evas, *tt_evas;
39 Evas_Object *eventarea, *owner;
40 Evas_Object *tooltip, *content;
41 Evas_Object *tt_win;
42 Ecore_Timer *show_timer;
43 Ecore_Timer *hide_timer;
44 Ecore_Job *reconfigure_job;
45 Evas_Coord mouse_x, mouse_y;
46 struct
47 {
48 Evas_Coord x, y, bx, by;
49 } pad;
50 struct
51 {
52 double x, y;
53 } rel_pos;
54 double hide_timeout; /* from theme */
55 Eina_Bool visible_lock:1;
56 Eina_Bool changed_style:1;
57 Eina_Bool free_size : 1;
58};
59
60static void _elm_tooltip_reconfigure(Elm_Tooltip *tt);
61static void _elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt);
62static void _elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt);
63static void _elm_tooltip_hide_anim_start(Elm_Tooltip *tt);
64static void _elm_tooltip_hide_anim_stop(Elm_Tooltip *tt);
65static void _elm_tooltip_show_timer_stop(Elm_Tooltip *tt);
66static void _elm_tooltip_hide(Elm_Tooltip *tt);
67static void _elm_tooltip_data_clean(Elm_Tooltip *tt);
68
69static void
70_elm_tooltip_content_changed_hints_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
71{
72 _elm_tooltip_reconfigure_job_start(data);
73 TTDBG("HINTS CHANGED\n");
74}
75
76static void
77_elm_tooltip_content_del_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
78{
79 Elm_Tooltip *tt = data;
80 tt->content = NULL;
81 tt->visible_lock = EINA_FALSE;
82 if (tt->tooltip) _elm_tooltip_hide(tt);
83}
84
85static void
86_elm_tooltip_obj_move_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
87{
88 Elm_Tooltip *tt = data;
89 _elm_tooltip_reconfigure_job_start(tt);
90 TTDBG("TT MOVED\n");
91}
92
93static void
94_elm_tooltip_obj_resize_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
95{
96 Elm_Tooltip *tt = data;
97 _elm_tooltip_reconfigure_job_start(tt);
98 TTDBG("TT RESIZE\n");
99}
100
101static void
102_elm_tooltip_obj_mouse_move_cb(Elm_Tooltip *tt, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Move *ev)
103{
104 if (tt->mouse_x || tt->mouse_y)
105 {
106 if ((abs(ev->cur.output.x - tt->mouse_x) < 3) &&
107 (abs(ev->cur.output.y - tt->mouse_y) < 3))
108 {
109 TTDBG("MOUSE MOVE REJECTED!\n");
110 return;
111 }
112 }
113 tt->mouse_x = ev->cur.output.x;
114 tt->mouse_y = ev->cur.output.y;
115 TTDBG("MOUSE MOVED\n");
116 _elm_tooltip_reconfigure_job_start(tt);
117}
118
119static void
120_elm_tooltip_show(Elm_Tooltip *tt)
121{
122 _elm_tooltip_show_timer_stop(tt);
123 _elm_tooltip_hide_anim_stop(tt);
124
125 TTDBG("TT SHOW\n");
126 if (tt->tooltip)
127 {
128 _elm_tooltip_reconfigure_job_start(tt);
129 TTDBG("RECURSIVE JOB\n");
130 return;
131 }
132 if (tt->free_size)
133 {
134 tt->tt_win = elm_win_add(NULL, "tooltip", ELM_WIN_BASIC);
135 elm_win_borderless_set(tt->tt_win, EINA_TRUE);
136 elm_win_override_set(tt->tt_win, EINA_TRUE);
137 tt->tt_evas = evas_object_evas_get(tt->tt_win);
138 tt->tooltip = edje_object_add(tt->tt_evas);
139 evas_object_move(tt->tooltip, 0, 0);
140 elm_win_resize_object_add(tt->tt_win, tt->tooltip);
141#ifdef HAVE_ELEMENTARY_X
142 ecore_x_window_shape_input_rectangle_set(elm_win_xwindow_get(tt->tt_win), 0, 0, 0, 0);
143#endif
144 evas_object_show(tt->tt_win);
145 }
146 else
147 tt->tooltip = edje_object_add(tt->evas);
148 if (!tt->tooltip) return;
149
150 evas_object_layer_set(tt->tt_win ?: tt->tooltip, ELM_OBJECT_LAYER_TOOLTIP);
151
152 evas_object_event_callback_add
153 (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
154 evas_object_event_callback_add
155 (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
156 evas_object_event_callback_add
157 (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_move_cb, tt);
158
159 tt->changed_style = EINA_TRUE;
160 _elm_tooltip_reconfigure_job_start(tt);
161}
162
163static void
164_elm_tooltip_content_del(Elm_Tooltip *tt)
165{
166 if (!tt->content) return;
167
168 TTDBG("CONTENT DEL\n");
169 evas_object_event_callback_del_full
170 (tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
171 _elm_tooltip_content_changed_hints_cb, tt);
172 evas_object_event_callback_del_full
173 (tt->content, EVAS_CALLBACK_DEL,
174 _elm_tooltip_content_del_cb, tt);
175 evas_object_hide(tt->content);
176 evas_object_del(tt->content);
177 tt->content = NULL;
178}
179
180
181static void
182_elm_tooltip_hide(Elm_Tooltip *tt)
183{
184 Evas_Object *del;
185 TTDBG("TT HIDE\n");
186 _elm_tooltip_show_timer_stop(tt);
187 _elm_tooltip_hide_anim_stop(tt);
188 _elm_tooltip_reconfigure_job_stop(tt);
189
190 if (!tt->tooltip) return;
191 if (tt->visible_lock) return;
192
193 _elm_tooltip_content_del(tt);
194
195 evas_object_event_callback_del_full
196 (tt->eventarea, EVAS_CALLBACK_MOVE, _elm_tooltip_obj_move_cb, tt);
197 evas_object_event_callback_del_full
198 (tt->eventarea, EVAS_CALLBACK_RESIZE, _elm_tooltip_obj_resize_cb, tt);
199 evas_object_event_callback_del_full
200 (tt->eventarea, EVAS_CALLBACK_MOUSE_MOVE, (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_move_cb, tt);
201
202 del = tt->tt_win ?: tt->tooltip;
203
204 tt->tt_win = NULL;
205 tt->tt_evas = NULL;
206 tt->tooltip = NULL;
207 evas_object_del(del);
208}
209
210static void
211_elm_tooltip_reconfigure_job(void *data)
212{
213 Elm_Tooltip *tt = data;
214 tt->reconfigure_job = NULL;
215 _elm_tooltip_reconfigure(data);
216}
217
218static void
219_elm_tooltip_reconfigure_job_stop(Elm_Tooltip *tt)
220{
221 if (!tt->reconfigure_job) return;
222 ecore_job_del(tt->reconfigure_job);
223 tt->reconfigure_job = NULL;
224}
225
226static void
227_elm_tooltip_reconfigure_job_start(Elm_Tooltip *tt)
228{
229 if (tt->reconfigure_job) ecore_job_del(tt->reconfigure_job);
230 tt->reconfigure_job = ecore_job_add(_elm_tooltip_reconfigure_job, tt);
231}
232
233static Eina_Bool
234_elm_tooltip_hide_anim_cb(void *data)
235{
236 Elm_Tooltip *tt = data;
237 tt->hide_timer = NULL;
238 _elm_tooltip_hide(tt);
239 return EINA_FALSE;
240}
241
242static void
243_elm_tooltip_hide_anim_start(Elm_Tooltip *tt)
244{
245 double extra = 0;
246 if (tt->hide_timer) return;
247 TTDBG("HIDE START\n");
248 /* hide slightly faster when in window mode to look less stupid */
249 if ((tt->hide_timeout > 0) && tt->tt_win) extra = 0.1;
250 edje_object_signal_emit(tt->tooltip, "elm,action,hide", "elm");
251 tt->hide_timer = ecore_timer_add
252 (tt->hide_timeout - extra, _elm_tooltip_hide_anim_cb, tt);
253}
254
255static void
256_elm_tooltip_hide_anim_stop(Elm_Tooltip *tt)
257{
258 if (!tt->hide_timer) return;
259 if (tt->tooltip)
260 edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
261 ecore_timer_del(tt->hide_timer);
262 tt->hide_timer = NULL;
263}
264
265static void
266_elm_tooltip_reconfigure(Elm_Tooltip *tt)
267{
268 Evas_Coord ox, oy, ow, oh, px, py, tx, ty, tw, th, cw = 0, ch = 0;
269 Evas_Coord eminw, eminh, ominw, ominh;
270 double rel_x, rel_y;
271 Eina_Bool inside_eventarea;
272
273 _elm_tooltip_reconfigure_job_stop(tt);
274
275 if (tt->hide_timer) return;
276 if (!tt->tooltip) return;
277 if (tt->changed_style)
278 {
279 const char *style = tt->style ? tt->style : "default";
280 const char *str;
281 if (!_elm_theme_object_set(tt->tt_win ? NULL : tt->owner, tt->tooltip, "tooltip", "base", style))
282 {
283 ERR("Could not apply the theme to the tooltip! style=%s", style);
284 if (tt->tt_win) evas_object_del(tt->tt_win);
285 else evas_object_del(tt->tooltip);
286 tt->tt_win = NULL;
287 tt->tt_evas = NULL;
288 tt->tooltip = NULL;
289 return;
290 }
291
292 tt->rel_pos.x = 0;
293 tt->rel_pos.y = 0;
294
295 tt->pad.x = 0;
296 tt->pad.y = 0;
297 tt->pad.bx = 0;
298 tt->pad.by = 0;
299 tt->hide_timeout = 0.0;
300
301 str = edje_object_data_get(tt->tooltip, "transparent");
302 if (tt->tt_win)
303 { /* FIXME: hardcoded here is bad */
304 if (str && (!strcmp(str, "enabled")))
305 {
306 elm_win_alpha_set(tt->tt_win, EINA_TRUE);
307 }
308 else
309 {
310 elm_win_alpha_set(tt->tt_win, EINA_FALSE);
311 }
312 }
313
314 str = edje_object_data_get(tt->tooltip, "pad_x");
315 if (str) tt->pad.x = atoi(str);
316 str = edje_object_data_get(tt->tooltip, "pad_y");
317 if (str) tt->pad.y = atoi(str);
318
319 str = edje_object_data_get(tt->tooltip, "pad_border_x");
320 if (str) tt->pad.bx = atoi(str);
321 str = edje_object_data_get(tt->tooltip, "pad_border_y");
322 if (str) tt->pad.by = atoi(str);
323
324 str = edje_object_data_get(tt->tooltip, "hide_timeout");
325 if (str)
326 {
327 tt->hide_timeout = atof(str);
328 if (tt->hide_timeout < 0.0) tt->hide_timeout = 0.0;
329 }
330
331 evas_object_pass_events_set(tt->tooltip, EINA_TRUE);
332 tt->changed_style = EINA_FALSE;
333 if (tt->tooltip)
334 edje_object_part_swallow(tt->tooltip, "elm.swallow.content",
335 tt->content);
336
337 edje_object_signal_emit(tt->tooltip, "elm,action,show", "elm");
338 }
339
340 if (!tt->content)
341 {
342 tt->content = tt->func((void *)tt->data, tt->owner, tt->tt_win ? : tt->owner);
343 if (!tt->content)
344 {
345 WRN("could not create tooltip content!");
346 if (tt->tt_win) evas_object_del(tt->tt_win);
347 else evas_object_del(tt->tooltip);
348
349 tt->tt_win = NULL;
350 tt->tt_evas = NULL;
351 tt->tooltip = NULL;
352 return;
353 }
354 evas_object_show(tt->content);
355 evas_object_layer_set(tt->content, ELM_OBJECT_LAYER_TOOLTIP);
356 evas_object_pass_events_set(tt->content, EINA_TRUE);
357 edje_object_part_swallow
358 (tt->tooltip, "elm.swallow.content", tt->content);
359 evas_object_event_callback_add(tt->content, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
360 _elm_tooltip_content_changed_hints_cb, tt);
361 evas_object_event_callback_add(tt->content, EVAS_CALLBACK_DEL,
362 _elm_tooltip_content_del_cb, tt);
363
364 }
365 TTDBG("*******RECALC\n");
366 evas_object_size_hint_min_get(tt->content, &ominw, &ominh);
367 edje_object_size_min_get(tt->tooltip, &eminw, &eminh);
368
369 if (eminw && (ominw < eminw)) ominw = eminw;
370 if (eminw && (ominh < eminh)) ominh = eminh;
371
372 if (ominw < 1) ominw = 10; /* at least it is noticeable */
373 if (ominh < 1) ominh = 10; /* at least it is noticeable */
374
375 edje_object_size_min_restricted_calc(tt->tooltip, &tw, &th, ominw, ominh);
376 TTDBG("TTSIZE: tw=%d,th=%d,ominw=%d,ominh=%d\n", tw, th, ominw, ominh);
377
378 if (tt->tt_win)
379 elm_win_screen_size_get(elm_object_top_widget_get(tt->owner), NULL, NULL, &cw, &ch);
380 if (!cw)
381 evas_output_size_get(tt->tt_evas ?: tt->evas, &cw, &ch);
382 TTDBG("SCREEN: cw=%d,ch=%d\n", cw, ch);
383
384 evas_object_geometry_get(tt->eventarea, &ox, &oy, &ow, &oh);
385 TTDBG("EVENTAREA: ox=%d,oy=%d,ow=%d,oh=%d\n", ox, oy, ow, oh);
386
387 if (tt->tt_win)
388 {
389 int x, y;
390 Evas_Object *win = elm_object_top_widget_get(tt->owner);
391#ifdef HAVE_ELEMENTARY_X
392 Ecore_X_Window xwin = elm_win_xwindow_get(win);
393 ecore_x_pointer_xy_get(xwin, &px, &py);
394#endif
395 elm_win_screen_position_get(win, &x, &y);
396 ox += x;
397 if (px) px += x;
398 oy += y;
399 if (py) py += y;
400 }
401 else
402 evas_pointer_canvas_xy_get(tt->evas, &px, &py);
403 TTDBG("POINTER: px=%d,py=%d\n", px, py);
404 inside_eventarea = ((px >= ox) && (py >= oy) &&
405 (px <= ox + ow) && (py <= oy + oh));
406 if (inside_eventarea)
407 {
408 /* try to position bottom right corner at pointer */
409 tx = px - tw;
410 ty = py - th;
411 TTDBG("INIT (EVENTAREA)\n");
412 }
413 else
414 {
415 /* try centered on middle of eventarea */
416 tx = ox + (ow / 2) - (tw / 2);
417 if (0 > (th - oy - oh)) ty = oy + th;
418 else ty = oy - oh;
419 TTDBG("INIT (INTERPRETED)\n");
420 }
421 TTDBG("ADJUST (POINTER): tx=%d,ty=%d\n", tx, ty);
422 if (tx < 0)
423 {
424 /* if we're offscreen, try to flip over the Y axis */
425 if (abs((tx + 2 * tw) - cw) < abs(tx))
426 tx += tw;
427 }
428 else if ((tx > px) && (px > tw))
429 {
430 if (tx + tw < cw)
431 tx += tw;
432 }
433 if (ty < 0)
434 {
435 /* if we're offscreen, try to flip over the X axis */
436 if (abs((ty + 2 * th) - ch) < abs(ty))
437 ty += th;
438 }
439 else if ((ty > py) && (py > th))
440 {
441 if (ty + th < ch)
442 ty += th;
443 }
444 TTDBG("ADJUST (FLIP): tx=%d,ty=%d\n", tx, ty);
445 if (inside_eventarea)
446 {
447 if ((tx == px) && ((tx + tw + tt->pad.x < cw) || (tx + tw > cw))) tx += tt->pad.x;
448 else if ((tx - tt->pad.x > 0) || (tx < 0)) tx -= tt->pad.x;
449 if ((ty == py) && ((ty + th + tt->pad.y < ch) || (ty + th > ch))) ty += tt->pad.y;
450 else if ((ty - tt->pad.y > 0) || (ty < 0)) ty -= tt->pad.y;
451 }
452 TTDBG("PAD: tx=%d,ty=%d\n", tx, ty);
453 if (tt->pad.bx * 2 + tw < cw)
454 {
455 if (tx < tt->pad.bx) tx = tt->pad.bx;
456 else if ((tx >= tw) && (tx + tt->pad.bx <= cw)) tx += tt->pad.bx;
457 else if (tx - tt->pad.bx >= 0) tx -= tt->pad.bx;
458 }
459 else if (tx < 0) tx -= tt->pad.bx;
460 else if (tx > cw) tx += tt->pad.bx;
461 if (tt->pad.by * 2 + th < ch)
462 {
463 if (ty < tt->pad.by) ty = tt->pad.by;
464 else if ((ty >= th) && (ty + tt->pad.by <= ch)) ty += tt->pad.by;
465 else if (ty - tt->pad.by >= 0) ty -= tt->pad.by;
466 }
467 else if (ty < 0) ty -= tt->pad.by;
468 else if (ty > ch) ty += tt->pad.by;
469 TTDBG("PAD (BORDER): tx=%d,ty=%d\n", tx, ty);
470 if (((tx < 0) && (tw < cw)) || ((ty < 0) && (th < ch)))
471 {
472 TTDBG("POSITIONING FAILED! THIS IS A BUG SOMEWHERE!\n");
473 abort();
474 return;
475 }
476 evas_object_move(tt->tt_win ? : tt->tooltip, tx, ty);
477 evas_object_resize(tt->tt_win ? : tt->tooltip, tw, th);
478 TTDBG("FINAL: tx=%d,ty=%d,tw=%d,th=%d\n", tx, ty, tw, th);
479 evas_object_show(tt->tooltip);
480
481 if (inside_eventarea)
482 {
483 rel_x = (px - tx) / (double)tw;
484 rel_y = (py - ty) / (double)th;
485 }
486 else
487 {
488 rel_x = (ox + (ow / 2) - tx) / (double)tw;
489 rel_y = (oy + (oh / 2) - ty) / (double)th;
490 }
491
492#define FDIF(a, b) (fabs((a) - (b)) > 0.0001)
493 if ((FDIF(rel_x, tt->rel_pos.x)) || (FDIF(rel_y, tt->rel_pos.y)))
494 {
495 Edje_Message_Float_Set *msg;
496
497 msg = alloca(sizeof(Edje_Message_Float_Set) + sizeof(double));
498 msg->count = 2;
499 msg->val[0] = rel_x;
500 msg->val[1] = rel_y;
501 tt->rel_pos.x = rel_x;
502 tt->rel_pos.y = rel_y;
503
504 edje_object_message_send(tt->tooltip, EDJE_MESSAGE_FLOAT_SET, 1, msg);
505 }
506#undef FDIF
507}
508
509static void
510_elm_tooltip_show_timer_stop(Elm_Tooltip *tt)
511{
512 if (!tt->show_timer) return;
513 ecore_timer_del(tt->show_timer);
514 tt->show_timer = NULL;
515}
516
517static Eina_Bool
518_elm_tooltip_timer_show_cb(void *data)
519{
520 Elm_Tooltip *tt = data;
521 tt->show_timer = NULL;
522 _elm_tooltip_show(tt);
523 return ECORE_CALLBACK_CANCEL;
524}
525
526static void
527_elm_tooltip_obj_mouse_in_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
528{
529 Elm_Tooltip *tt = data;
530
531 _elm_tooltip_hide_anim_stop(tt);
532
533 if ((tt->show_timer) || (tt->tooltip)) return;
534
535 tt->show_timer = ecore_timer_add(_elm_config->tooltip_delay, _elm_tooltip_timer_show_cb, tt);
536 TTDBG("MOUSE IN\n");
537}
538
539static void
540_elm_tooltip_obj_mouse_out_cb(Elm_Tooltip *tt, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, Evas_Event_Mouse_Out *event __UNUSED__)
541{
542 if (tt->visible_lock) return;
543
544 if (!tt->tooltip)
545 {
546 _elm_tooltip_show_timer_stop(tt);
547 return;
548 }
549 _elm_tooltip_hide_anim_start(tt);
550 TTDBG("MOUSE OUT\n");
551}
552
553static void _elm_tooltip_obj_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__);
554
555static void
556_elm_tooltip_unset(Elm_Tooltip *tt)
557{
558 tt->visible_lock = EINA_FALSE;
559 _elm_tooltip_hide(tt);
560 _elm_tooltip_data_clean(tt);
561
562 if (tt->eventarea)
563 {
564 evas_object_event_callback_del_full
565 (tt->eventarea, EVAS_CALLBACK_MOUSE_IN,
566 _elm_tooltip_obj_mouse_in_cb, tt);
567 evas_object_event_callback_del_full
568 (tt->eventarea, EVAS_CALLBACK_MOUSE_OUT,
569 (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_out_cb, tt);
570 evas_object_event_callback_del_full
571 (tt->eventarea, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
572
573 evas_object_data_del(tt->eventarea, _tooltip_key);
574 }
575 if (tt->owner)
576 {
577 evas_object_event_callback_del_full
578 (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
579 elm_widget_tooltip_del(tt->owner, tt);
580 }
581
582 eina_stringshare_del(tt->style);
583 free(tt);
584}
585
586static void
587_elm_tooltip_obj_free_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
588{
589 Elm_Tooltip *tt = data;
590 if (tt->eventarea == obj) tt->eventarea = NULL;
591 if (tt->owner == obj) tt->owner = NULL;
592 _elm_tooltip_unset(tt);
593}
594
595static Evas_Object *
596_elm_tooltip_label_create(void *data, Evas_Object *obj __UNUSED__, Evas_Object *tooltip)
597{
598 Evas_Object *label = elm_label_add(tooltip);
599 if (!label)
600 return NULL;
601 elm_object_style_set(label, "tooltip");
602 elm_object_text_set(label, data);
603 return label;
604}
605
606static Evas_Object *
607_elm_tooltip_trans_label_create(void *data, Evas_Object *obj __UNUSED__, Evas_Object *tooltip)
608{
609 Evas_Object *label = elm_label_add(tooltip);
610 const char **text = data;
611 if (!label)
612 return NULL;
613 elm_object_style_set(label, "tooltip");
614 elm_object_domain_translatable_text_set(label, text[0], text[1]);
615 return label;
616}
617
618static void
619_elm_tooltip_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
620{
621 eina_stringshare_del(data);
622}
623
624static void
625_elm_tooltip_trans_label_del_cb(void *data, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
626{
627 const char **text = data;
628 eina_stringshare_del(text[0]);
629 eina_stringshare_del(text[1]);
630 free(text);
631}
632
633static void
634_elm_tooltip_data_clean(Elm_Tooltip *tt)
635{
636 if (tt->del_cb) tt->del_cb((void *)tt->data, tt->owner, NULL);
637
638 _elm_tooltip_content_del(tt);
639
640 tt->data = NULL;
641 tt->del_cb = NULL;
642}
643
644/**
645 * Notify tooltip should recalculate its theme.
646 * @internal
647 */
648void
649elm_tooltip_theme(Elm_Tooltip *tt)
650{
651 if (!tt->tooltip) return;
652 tt->changed_style = EINA_TRUE;
653 _elm_tooltip_reconfigure_job_start(tt);
654}
655
656
657/**
658 * Set the content to be shown in the tooltip object for specific event area.
659 *
660 * Setup the tooltip to object. The object @a eventarea can have only
661 * one tooltip, so any previous tooltip data is removed. @p func(with
662 * @p data) will be called every time that need show the tooltip and
663 * it should return a valid Evas_Object. This object is then managed
664 * fully by tooltip system and is deleted when the tooltip is gone.
665 *
666 * This is an internal function that is used by objects with sub-items
667 * that want to provide different tooltips for each of them. The @a
668 * owner object should be an elm_widget and will be used to track
669 * theme changes and to feed @a func and @a del_cb. The @a eventarea
670 * may be any object and is the one that should be used later on with
671 * elm_object_tooltip apis, such as elm_object_tooltip_hide(),
672 * elm_object_tooltip_show() or elm_object_tooltip_unset().
673 *
674 * @param eventarea the object being attached a tooltip.
675 * @param owner the elm_widget that owns this object, will be used to
676 * track theme changes and to be used in @a func or @a del_cb.
677 * @param func the function used to create the tooltip contents. The
678 * @a Evas_Object parameters will receive @a owner as value.
679 * @param data what to provide to @a func as callback data/context.
680 * @param del_cb called when data is not needed anymore, either when
681 * another callback replaces @p func, the tooltip is unset with
682 * elm_object_tooltip_unset() or the owner object @a obj
683 * dies. This callback receives as the first parameter the
684 * given @a data, and @c event_info is NULL.
685 *
686 * @internal
687 * @ingroup Tooltips
688 */
689void
690elm_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)
691{
692 Elm_Tooltip *tt = NULL;
693 Eina_Bool just_created;
694
695 EINA_SAFETY_ON_NULL_GOTO(owner, error);
696 EINA_SAFETY_ON_NULL_GOTO(eventarea, error);
697
698 if (!func)
699 {
700 elm_object_tooltip_unset(eventarea);
701 return;
702 }
703
704 tt = evas_object_data_get(eventarea, _tooltip_key);
705 if (tt)
706 {
707 if (tt->owner != owner)
708 {
709 if (tt->owner != eventarea)
710 evas_object_event_callback_del_full
711 (tt->owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
712
713 elm_widget_tooltip_del(tt->owner, tt);
714
715 if (owner != eventarea)
716 evas_object_event_callback_add
717 (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
718
719 elm_widget_tooltip_add(tt->owner, tt);
720 }
721
722 if ((tt->func == func) && (tt->data == data) &&
723 (tt->del_cb == del_cb))
724 return;
725 _elm_tooltip_data_clean(tt);
726 just_created = EINA_FALSE;
727 }
728 else
729 {
730 tt = ELM_NEW(Elm_Tooltip);
731 if (!tt) goto error;
732
733 tt->owner = owner;
734 tt->eventarea = eventarea;
735 tt->evas = evas_object_evas_get(eventarea);
736 evas_object_data_set(eventarea, _tooltip_key, tt);
737
738 just_created = EINA_TRUE;
739
740 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_IN,
741 _elm_tooltip_obj_mouse_in_cb, tt);
742 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_MOUSE_OUT,
743 (Evas_Object_Event_Cb)_elm_tooltip_obj_mouse_out_cb, tt);
744 evas_object_event_callback_add(eventarea, EVAS_CALLBACK_FREE,
745 _elm_tooltip_obj_free_cb, tt);
746
747 if (owner != eventarea)
748 evas_object_event_callback_add
749 (owner, EVAS_CALLBACK_FREE, _elm_tooltip_obj_free_cb, tt);
750
751 elm_widget_tooltip_add(tt->owner, tt);
752 }
753
754 tt->func = func;
755 tt->data = data;
756 tt->del_cb = del_cb;
757
758 if (!just_created) _elm_tooltip_reconfigure_job_start(tt);
759 return;
760
761 error:
762 if (del_cb) del_cb((void *)data, owner, NULL);
763}
764
765/**
766 * Force show tooltip of object
767 *
768 * @param obj Target object
769 *
770 * Force show the tooltip and disable hide on mouse_out.
771 * If another content is set as tooltip, the visible tooltip will hididen and
772 * showed again with new content.
773 * This can force show more than one tooltip at a time.
774 *
775 * @ingroup Tooltips
776 */
777EAPI void
778elm_object_tooltip_show(Evas_Object *obj)
779{
780 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
781 tt->visible_lock = EINA_TRUE;
782 _elm_tooltip_show(tt);
783}
784
785/**
786 * Force hide tooltip of object
787 *
788 * @param obj Target object
789 *
790 * Force hide the tooltip and (re)enable future mouse interations.
791 *
792 * @ingroup Tooltips
793 */
794EAPI void
795elm_object_tooltip_hide(Evas_Object *obj)
796{
797 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
798 tt->visible_lock = EINA_FALSE;
799 _elm_tooltip_hide_anim_start(tt);
800}
801
802/**
803 * Set the text to be shown in the tooltip object
804 *
805 * @param obj Target object
806 * @param text The text to set in the content
807 *
808 * Setup the text as tooltip to object. The object can have only one tooltip,
809 * so any previous tooltip data is removed.
810 * This method call internaly the elm_tooltip_content_cb_set().
811 *
812 * @ingroup Tooltips
813 */
814EAPI void
815elm_object_tooltip_text_set(Evas_Object *obj, const char *text)
816{
817 EINA_SAFETY_ON_NULL_RETURN(obj);
818 EINA_SAFETY_ON_NULL_RETURN(text);
819
820 text = eina_stringshare_add(text);
821 elm_object_tooltip_content_cb_set
822 (obj, _elm_tooltip_label_create, text, _elm_tooltip_label_del_cb);
823}
824
825/**
826 */
827EAPI void
828elm_object_tooltip_domain_translatable_text_set(Evas_Object *obj, const char *domain, const char *text)
829{
830 const char **data;
831 EINA_SAFETY_ON_NULL_RETURN(obj);
832 EINA_SAFETY_ON_NULL_RETURN(text);
833
834 data = malloc(2 * sizeof(char *));
835 if (!data) return;
836 data[0] = eina_stringshare_add(domain);
837 data[1] = eina_stringshare_add(text);
838 elm_object_tooltip_content_cb_set
839 (obj, _elm_tooltip_trans_label_create, data,
840 _elm_tooltip_trans_label_del_cb);
841}
842
843/**
844 * Set the content to be shown in the tooltip object
845 *
846 * Setup the tooltip to object. The object can have only one tooltip,
847 * so any previous tooltip data is removed. @p func(with @p data) will
848 * be called every time that need show the tooltip and it should
849 * return a valid Evas_Object. This object is then managed fully by
850 * tooltip system and is deleted when the tooltip is gone.
851 *
852 * @param obj the object being attached a tooltip.
853 * @param func the function used to create the tooltip contents.
854 * @param data what to provide to @a func as callback data/context.
855 * @param del_cb called when data is not needed anymore, either when
856 * another callback replaces @p func, the tooltip is unset with
857 * elm_object_tooltip_unset() or the owner object @a obj
858 * dies. This callback receives as the first parameter the
859 * given @a data, and @c event_info is NULL.
860 *
861 * @ingroup Tooltips
862 */
863EAPI void
864elm_object_tooltip_content_cb_set(Evas_Object *obj, Elm_Tooltip_Content_Cb func, const void *data, Evas_Smart_Cb del_cb)
865{
866 elm_object_sub_tooltip_content_cb_set(obj, obj, func, data, del_cb);
867}
868
869/**
870 * Unset tooltip from object
871 *
872 * @param obj Target object
873 *
874 * Remove tooltip from object. The callback provided as del_cb to
875 * elm_object_tooltip_content_cb_set() will be called to notify it is
876 * not used anymore.
877 *
878 * @see elm_object_tooltip_content_cb_set()
879 *
880 * @ingroup Tooltips
881 */
882EAPI void
883elm_object_tooltip_unset(Evas_Object *obj)
884{
885 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
886 _elm_tooltip_unset(tt);
887}
888
889/**
890 * Sets a different style for this object tooltip.
891 *
892 * @note before you set a style you should define a tooltip with
893 * elm_object_tooltip_content_cb_set() or
894 * elm_object_tooltip_text_set().
895 *
896 * @param obj an object with tooltip already set.
897 * @param style the theme style to use (default, transparent, ...)
898 */
899EAPI void
900elm_object_tooltip_style_set(Evas_Object *obj, const char *style)
901{
902 ELM_TOOLTIP_GET_OR_RETURN(tt, obj);
903 if (!eina_stringshare_replace(&tt->style, style)) return;
904 elm_tooltip_theme(tt);
905}
906
907/**
908 * Get the style for this object tooltip.
909 *
910 * @param obj an object with tooltip already set.
911 * @return style the theme style in use, defaults to "default". If the
912 * object does not have a tooltip set, then NULL is returned.
913 */
914EAPI const char *
915elm_object_tooltip_style_get(const Evas_Object *obj)
916{
917 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, NULL);
918 return tt->style ? tt->style : "default";
919}
920
921/**
922 * @brief Disable size restrictions on an object's tooltip
923 * @param obj The tooltip's anchor object
924 * @param disable If EINA_TRUE, size restrictions are disabled
925 * @return EINA_FALSE on failure, EINA_TRUE on success
926 *
927 * This function allows a tooltip to expand beyond its parent window's canvas.
928 * It will instead be limited only by the size of the display.
929 */
930EAPI Eina_Bool
931elm_object_tooltip_window_mode_set(Evas_Object *obj, Eina_Bool disable)
932{
933 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, EINA_FALSE);
934 return tt->free_size = disable;
935}
936
937/**
938 * @brief Retrieve size restriction state of an object's tooltip
939 * @param obj The tooltip's anchor object
940 * @return If EINA_TRUE, size restrictions are disabled
941 *
942 * This function returns whether a tooltip is allowed to expand beyond
943 * its parent window's canvas.
944 * It will instead be limited only by the size of the display.
945 */
946EAPI Eina_Bool
947elm_object_tooltip_window_mode_get(const Evas_Object *obj)
948{
949 ELM_TOOLTIP_GET_OR_RETURN(tt, obj, EINA_FALSE);
950 return tt->free_size;
951}
diff --git a/libraries/elementary/src/lib/elu_ews_wm.c b/libraries/elementary/src/lib/elu_ews_wm.c
new file mode 100644
index 0000000..15fdb65
--- /dev/null
+++ b/libraries/elementary/src/lib/elu_ews_wm.c
@@ -0,0 +1,545 @@
1#include <Elementary.h>
2#include "elm_priv.h"
3
4static Eina_Bool _ews_used = EINA_FALSE;
5static Eina_List *_ews_ev_handlers = NULL;
6static Eina_Hash *_ews_borders = NULL;
7static Eina_Hash *_ews_borders_geo = NULL;
8static Evas_Object *_ews_bg = NULL;
9static Ecore_Animator *_ews_border_mover = NULL;
10static Evas_Object *_ews_border_mover_obj = NULL;
11static Evas_Point _ews_border_mover_off = {0, 0};
12
13static void
14_elm_ews_border_usable_screen_geometry_get(int *x, int *y, int *w, int *h)
15{
16 Ecore_Evas *ee = ecore_evas_ews_ecore_evas_get();
17 ecore_evas_geometry_get(ee, NULL, NULL, w, h);
18 if (x) *x = 0;
19 if (y) *y = 0;
20 // TODO: when add a shelf for iconified, subtract its area here.
21}
22
23static void
24_elm_ews_wm_border_del(void *data)
25{
26 Evas_Object *deco = data;
27 evas_object_del(deco);
28
29 if (_ews_border_mover_obj == deco)
30 {
31 if (_ews_border_mover)
32 {
33 ecore_animator_del(_ews_border_mover);
34 _ews_border_mover = NULL;
35 }
36 _ews_border_mover_obj = NULL;
37 }
38}
39
40static Evas_Object *
41_elm_ews_wm_border_find(const Ecore_Evas *ee)
42{
43 return eina_hash_find(_ews_borders, &ee);
44}
45
46static Eina_Rectangle *
47_elm_ews_wm_border_geo_find(const Ecore_Evas *ee)
48{
49 return eina_hash_find(_ews_borders_geo, &ee);
50}
51
52static void
53_elm_ews_border_geo_apply(Ecore_Evas *ee, Evas_Object *o)
54{
55 int x, y, w, h;
56 ecore_evas_geometry_get(ee, &x, &y, &w, &h);
57 evas_object_move(o, x, y);
58 evas_object_resize(o, w, h);
59}
60
61static void
62_elm_ews_border_focus_apply(Ecore_Evas *ee, Evas_Object *o)
63{
64 const char *sig;
65 if (ecore_evas_focus_get(ee))
66 sig = "elm,state,focus,on";
67 else
68 sig = "elm,state,focus,off";
69 edje_object_signal_emit(o, sig, "elm");
70}
71
72static void
73_elm_ews_border_stack_apply(Ecore_Evas *ee, Evas_Object *o)
74{
75 Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee);
76 evas_object_stack_below(o, bs_o);
77}
78
79static void
80_elm_ews_border_iconified_apply(Ecore_Evas *ee, Evas_Object *o)
81{
82 const char *sig;
83 if (ecore_evas_iconified_get(ee))
84 sig = "elm,state,iconified,on";
85 else
86 sig = "elm,state,iconified,off";
87 edje_object_signal_emit(o, sig, "elm");
88
89 // TODO: add to some taskbar? and actually hide it?
90 DBG("EWS does not implement iconified yet");
91}
92
93static void
94_elm_ews_border_maximized_apply(Ecore_Evas *ee, Evas_Object *o)
95{
96 int x, y, w, h;
97 if (ecore_evas_maximized_get(ee))
98 {
99 Eina_Rectangle *r;
100 int ex, ey, ew, eh;
101
102 edje_object_signal_emit(o, "elm,state,maximized,on", "elm");
103 edje_object_message_signal_process(o);
104 ecore_evas_geometry_get(ee, &x, &y, &w, &h);
105
106 r = _elm_ews_wm_border_geo_find(ee);
107 if (!r)
108 {
109 r = malloc(sizeof(Eina_Rectangle));
110 eina_hash_add(_ews_borders_geo, &ee, r);
111 }
112
113 r->x = x;
114 r->y = y;
115 r->w = w;
116 r->h = h;
117 _elm_ews_border_usable_screen_geometry_get(&x, &y, &w, &h);
118 edje_object_parts_extends_calc(o, &ex, &ey, &ew, &eh);
119 x -= ex;
120 y -= ey;
121 w -= ew - r->w;
122 h -= eh - r->h;
123 }
124 else
125 {
126 Eina_Rectangle *r = _elm_ews_wm_border_geo_find(ee);
127 edje_object_signal_emit(o, "elm,state,maximized,off", "elm");
128
129 if (!r) ecore_evas_geometry_get(ee, &x, &y, &w, &h);
130 else
131 {
132 x = r->x;
133 y = r->y;
134 w = r->w;
135 h = r->h;
136 }
137 }
138
139 ecore_evas_move_resize(ee, x, y, w, h);
140 _elm_ews_border_geo_apply(ee, o);
141}
142
143static void
144_elm_ews_border_layer_apply(Ecore_Evas *ee, Evas_Object *o)
145{
146 Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee);
147 evas_object_layer_set(o, evas_object_layer_get(bs_o));
148 _elm_ews_border_stack_apply(ee, o);
149}
150
151static void
152_elm_ews_border_fullscreen_apply(Ecore_Evas *ee, Evas_Object *o)
153{
154 const char *sig;
155 if (ecore_evas_fullscreen_get(ee))
156 sig = "elm,state,fullscreen,on";
157 else
158 sig = "elm,state,fullscreen,off";
159 edje_object_signal_emit(o, sig, "elm");
160 _elm_ews_border_geo_apply(ee, o);
161}
162
163static void
164_elm_ews_border_config_apply(Ecore_Evas *ee, Evas_Object *o, Elm_Theme *th)
165{
166 const char *title, *name = NULL, *class = NULL, *style = NULL;
167 const char *sig;
168
169 if (ecore_evas_borderless_get(ee))
170 style = "borderless";
171
172 _elm_theme_set(th, o, "ews", "decoration", style ? style : "default");
173
174 if (ecore_evas_shaped_get(ee) || ecore_evas_alpha_get(ee) ||
175 ecore_evas_transparent_get(ee))
176 sig = "elm,state,alpha,on";
177 else
178 sig = "elm,state,alpha,off";
179 edje_object_signal_emit(o, sig, "elm");
180
181 title = ecore_evas_title_get(ee);
182 ecore_evas_name_class_get(ee, &name, &class);
183 edje_object_part_text_escaped_set(o, "elm.text.title", title);
184 edje_object_part_text_escaped_set(o, "elm.text.name", name);
185 edje_object_part_text_escaped_set(o, "elm.text.class", class);
186
187 _elm_ews_border_geo_apply(ee, o);
188 _elm_ews_border_focus_apply(ee, o);
189 _elm_ews_border_stack_apply(ee, o);
190 _elm_ews_border_iconified_apply(ee, o);
191 _elm_ews_border_maximized_apply(ee, o);
192 _elm_ews_border_layer_apply(ee, o);
193 _elm_ews_border_fullscreen_apply(ee, o);
194}
195
196static Eina_Bool
197_elm_ews_wm_border_theme_set(Ecore_Evas *ee, Evas_Object *o, Elm_Theme *th)
198{
199 _elm_ews_border_config_apply(ee, o, th);
200 return EINA_TRUE;
201}
202
203static void
204_elm_ews_border_sig_focus(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
205{
206 Ecore_Evas *ee = data;
207 ecore_evas_focus_set(ee, EINA_TRUE);
208}
209
210static void
211_elm_ews_border_sig_iconify(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
212{
213 Ecore_Evas *ee = data;
214 ecore_evas_iconified_set(ee, EINA_TRUE);
215}
216
217static void
218_elm_ews_border_sig_maximize(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
219{
220 Ecore_Evas *ee = data;
221 ecore_evas_maximized_set(ee, EINA_TRUE);
222}
223
224static void
225_elm_ews_border_sig_fullscreen(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
226{
227 Ecore_Evas *ee = data;
228 ecore_evas_fullscreen_set(ee, EINA_TRUE);
229}
230
231static void
232_elm_ews_border_sig_restore(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
233{
234 Ecore_Evas *ee = data;
235 ecore_evas_iconified_set(ee, EINA_FALSE);
236 ecore_evas_maximized_set(ee, EINA_FALSE);
237 ecore_evas_fullscreen_set(ee, EINA_FALSE);
238}
239
240static void
241_elm_ews_border_sig_close(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
242{
243 Ecore_Evas *ee = data;
244 ecore_evas_ews_delete_request(ee);
245}
246
247static void
248_elm_ews_border_sig_menu(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
249{
250 // TODO: show some menu?
251 ERR("EWS does not implement menu yet");
252 (void)data;
253}
254
255static Eina_Bool
256_elm_ews_border_mover(void *data)
257{
258 Ecore_Evas *ee = data;
259 Evas_Object *o = _elm_ews_wm_border_find(ee);
260 int x, y;
261
262 evas_pointer_output_xy_get(ecore_evas_ews_evas_get(), &x, &y);
263 x -= _ews_border_mover_off.x;
264 y -= _ews_border_mover_off.y;
265 ecore_evas_move(ee, x, y);
266 evas_object_move(o, x, y);
267
268 return EINA_TRUE;
269}
270
271static void
272_elm_ews_border_sig_move_start(void *data, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
273{
274 Ecore_Evas *ee = data;
275 Evas_Object *bs_o = ecore_evas_ews_backing_store_get(ee);
276 int x, y, ox, oy;
277
278 if (_ews_border_mover) ecore_animator_del(_ews_border_mover);
279
280 evas_pointer_output_xy_get(evas_object_evas_get(bs_o), &x, &y);
281 evas_object_geometry_get(bs_o, &ox, &oy, NULL, NULL);
282 _ews_border_mover_off.x = x - ox;
283 _ews_border_mover_off.y = y - oy;
284 _ews_border_mover_obj = bs_o;
285 _ews_border_mover = ecore_animator_add(_elm_ews_border_mover, ee);
286}
287
288static void
289_elm_ews_border_sig_move_stop(void *data __UNUSED__, Evas_Object *o __UNUSED__, const char *sig __UNUSED__, const char *source __UNUSED__)
290{
291 if (!_ews_border_mover) return;
292 ecore_animator_del(_ews_border_mover);
293 _ews_border_mover = NULL;
294 _ews_border_mover_obj = NULL;
295}
296
297static Eina_Bool
298_elm_ews_wm_add_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
299{
300 Ecore_Evas *ee = event_info;
301 Evas_Object *o = edje_object_add(ecore_evas_ews_evas_get());
302 Evas_Coord x, y, w, h, sw, sh;
303
304 edje_object_signal_callback_add
305 (o, "elm,action,focus", "elm", _elm_ews_border_sig_focus, ee);
306 edje_object_signal_callback_add
307 (o, "elm,action,iconify", "elm", _elm_ews_border_sig_iconify, ee);
308 edje_object_signal_callback_add
309 (o, "elm,action,maximize", "elm", _elm_ews_border_sig_maximize, ee);
310 edje_object_signal_callback_add
311 (o, "elm,action,fullscreen", "elm", _elm_ews_border_sig_fullscreen, ee);
312 edje_object_signal_callback_add
313 (o, "elm,action,restore", "elm", _elm_ews_border_sig_restore, ee);
314 edje_object_signal_callback_add
315 (o, "elm,action,close", "elm", _elm_ews_border_sig_close, ee);
316 edje_object_signal_callback_add
317 (o, "elm,action,menu", "elm", _elm_ews_border_sig_menu, ee);
318 edje_object_signal_callback_add
319 (o, "elm,action,move,start", "elm", _elm_ews_border_sig_move_start, ee);
320 edje_object_signal_callback_add
321 (o, "elm,action,move,stop", "elm", _elm_ews_border_sig_move_stop, ee);
322
323 eina_hash_add(_ews_borders, &ee, o);
324 _elm_ews_wm_border_theme_set(ee, o, NULL);
325
326 ecore_evas_screen_geometry_get(ee, NULL, NULL, &sw, &sh);
327 ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
328 x = (sw - w) / 2;
329 y = (sh - h) / 2;
330 ecore_evas_move(ee, x, y);
331 ecore_evas_focus_set(ee, EINA_TRUE);
332
333 return EINA_TRUE;
334}
335
336static Eina_Bool
337_elm_ews_wm_del_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
338{
339 Ecore_Evas *ee = event_info;
340 eina_hash_del(_ews_borders, &ee, NULL);
341 eina_hash_del(_ews_borders_geo, &ee, NULL);
342 return EINA_TRUE;
343}
344
345static Eina_Bool
346_elm_ews_wm_geo_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
347{
348 Ecore_Evas *ee = event_info;
349 Evas_Object *o = _elm_ews_wm_border_find(ee);
350 _elm_ews_border_geo_apply(ee, o);
351 return EINA_TRUE;
352}
353
354static Eina_Bool
355_elm_ews_wm_show_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
356{
357 Ecore_Evas *ee = event_info;
358 Evas_Object *o = _elm_ews_wm_border_find(ee);
359 evas_object_show(o);
360 return EINA_TRUE;
361}
362
363static Eina_Bool
364_elm_ews_wm_hide_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
365{
366 Ecore_Evas *ee = event_info;
367 Evas_Object *o = _elm_ews_wm_border_find(ee);
368 evas_object_hide(o);
369 return EINA_TRUE;
370}
371
372static Eina_Bool
373_elm_ews_wm_focus_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
374{
375 Ecore_Evas *ee = event_info;
376 Evas_Object *o = _elm_ews_wm_border_find(ee);
377 _elm_ews_border_focus_apply(ee, o);
378 return EINA_TRUE;
379}
380
381static Eina_Bool
382_elm_ews_wm_stack_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
383{
384 Ecore_Evas *ee = event_info;
385 Evas_Object *o = _elm_ews_wm_border_find(ee);
386 _elm_ews_border_stack_apply(ee, o);
387 return EINA_TRUE;
388}
389
390static Eina_Bool
391_elm_ews_wm_iconified_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
392{
393 Ecore_Evas *ee = event_info;
394 Evas_Object *o = _elm_ews_wm_border_find(ee);
395 _elm_ews_border_iconified_apply(ee, o);
396 return EINA_TRUE;
397}
398
399static Eina_Bool
400_elm_ews_wm_maximized_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
401{
402 Ecore_Evas *ee = event_info;
403 Evas_Object *o = _elm_ews_wm_border_find(ee);
404 _elm_ews_border_maximized_apply(ee, o);
405 return EINA_TRUE;
406}
407
408static Eina_Bool
409_elm_ews_wm_layer_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
410{
411 Ecore_Evas *ee = event_info;
412 Evas_Object *o = _elm_ews_wm_border_find(ee);
413 _elm_ews_border_layer_apply(ee, o);
414 return EINA_TRUE;
415}
416
417static Eina_Bool
418_elm_ews_wm_fullscreen_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
419{
420 Ecore_Evas *ee = event_info;
421 Evas_Object *o = _elm_ews_wm_border_find(ee);
422 _elm_ews_border_fullscreen_apply(ee, o);
423 return EINA_TRUE;
424}
425
426static Eina_Bool
427_elm_ews_wm_config_change_cb(void *data __UNUSED__, int type __UNUSED__, void *event_info)
428{
429 Ecore_Evas *ee = event_info;
430 Evas_Object *o = _elm_ews_wm_border_find(ee);
431 _elm_ews_border_config_apply(ee, o, NULL);
432 return EINA_TRUE;
433}
434
435void
436_elm_ews_wm_rescale(Elm_Theme *th, Eina_Bool use_theme)
437{
438 Eina_Iterator *it;
439 Eina_Hash_Tuple *tp = NULL;
440
441 if (!_ews_borders) return;
442 it = eina_hash_iterator_tuple_new(_ews_borders);
443 if (!use_theme)
444 {
445 EINA_ITERATOR_FOREACH(it, tp)
446 _elm_ews_wm_border_theme_set(*(void**)tp->key, tp->data, NULL);
447
448 if (_ews_bg)
449 _elm_theme_set(NULL, _ews_bg, "ews", "background", "default");
450 }
451 else
452 {
453 EINA_ITERATOR_FOREACH(it, tp)
454 _elm_ews_wm_border_theme_set(*(void**)tp->key, tp->data, th);
455
456 if (_ews_bg)
457 _elm_theme_set(th, _ews_bg, "ews", "background", "default");
458 }
459
460 eina_iterator_free(it);
461}
462
463int
464_elm_ews_wm_init(void)
465{
466 Evas *e;
467 Evas_Object *o;
468
469 if (strcmp(_elm_config->engine, ELM_EWS) != 0)
470 {
471 _ews_used = EINA_FALSE;
472 return EINA_TRUE;
473 }
474
475 e = ecore_evas_ews_evas_get();
476 if (!e) return EINA_FALSE;
477 o = edje_object_add(e);
478 if (!o) return EINA_FALSE;
479
480 if (!_elm_theme_set(NULL, o, "ews", "background", "default"))
481 {
482 ERR("Could not set background theme, fallback to rectangle");
483 evas_object_del(o);
484 _ews_bg = o = NULL;
485 }
486 else
487 _ews_bg = o;
488 ecore_evas_ews_background_set(o);
489
490
491#define ADD_EH(ev, cb) \
492 _ews_ev_handlers = eina_list_append \
493 (_ews_ev_handlers, ecore_event_handler_add(ev, cb, NULL))
494 ADD_EH(ECORE_EVAS_EWS_EVENT_ADD, _elm_ews_wm_add_cb);
495 ADD_EH(ECORE_EVAS_EWS_EVENT_DEL, _elm_ews_wm_del_cb);
496 ADD_EH(ECORE_EVAS_EWS_EVENT_RESIZE, _elm_ews_wm_geo_cb);
497 ADD_EH(ECORE_EVAS_EWS_EVENT_MOVE, _elm_ews_wm_geo_cb);
498 ADD_EH(ECORE_EVAS_EWS_EVENT_SHOW, _elm_ews_wm_show_cb);
499 ADD_EH(ECORE_EVAS_EWS_EVENT_HIDE, _elm_ews_wm_hide_cb);
500 ADD_EH(ECORE_EVAS_EWS_EVENT_FOCUS, _elm_ews_wm_focus_cb);
501 ADD_EH(ECORE_EVAS_EWS_EVENT_UNFOCUS, _elm_ews_wm_focus_cb);
502 ADD_EH(ECORE_EVAS_EWS_EVENT_RAISE, _elm_ews_wm_stack_cb);
503 ADD_EH(ECORE_EVAS_EWS_EVENT_LOWER, _elm_ews_wm_stack_cb);
504 ADD_EH(ECORE_EVAS_EWS_EVENT_ICONIFIED_CHANGE, _elm_ews_wm_iconified_change_cb);
505 ADD_EH(ECORE_EVAS_EWS_EVENT_MAXIMIZED_CHANGE, _elm_ews_wm_maximized_change_cb);
506 ADD_EH(ECORE_EVAS_EWS_EVENT_LAYER_CHANGE, _elm_ews_wm_layer_change_cb);
507 ADD_EH(ECORE_EVAS_EWS_EVENT_FULLSCREEN_CHANGE, _elm_ews_wm_fullscreen_change_cb);
508 ADD_EH(ECORE_EVAS_EWS_EVENT_CONFIG_CHANGE, _elm_ews_wm_config_change_cb);
509#undef ADD_EH
510
511 if (!_ews_borders)
512 _ews_borders = eina_hash_pointer_new(_elm_ews_wm_border_del);
513
514 if (!_ews_borders_geo)
515 _ews_borders_geo = eina_hash_pointer_new(free);
516
517 _ews_used = EINA_TRUE;
518 return EINA_TRUE;
519}
520
521void
522_elm_ews_wm_shutdown(void)
523{
524 Ecore_Event_Handler *eh;
525
526 if (_ews_border_mover)
527 {
528 ecore_animator_del(_ews_border_mover);
529 _ews_border_mover = NULL;
530 }
531 _ews_border_mover_obj = NULL;
532
533 EINA_LIST_FREE(_ews_ev_handlers, eh) ecore_event_handler_del(eh);
534 if (_ews_borders)
535 {
536 eina_hash_free(_ews_borders);
537 _ews_borders = NULL;
538 }
539 if (_ews_borders_geo)
540 {
541 eina_hash_free(_ews_borders_geo);
542 _ews_borders_geo = NULL;
543 }
544 _ews_bg = NULL;
545}