[access] call a callback function with information
[framework/uifw/elementary.git] / src / lib / els_pan.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 #define SMART_NAME "elm_pan"
5 #define API_ENTRY Smart_Data *sd = NULL; if ((!obj) || (!(sd = evas_object_smart_data_get(obj))) || (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;
7 typedef struct _Smart_Data Smart_Data;
8
9 struct _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 */
20 static void _smart_child_del_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
21 static void _smart_child_resize_hook(void *data, Evas *e, Evas_Object *obj, void *event_info);
22
23 static void _smart_reconfigure(Smart_Data *sd);
24 static void _smart_add(Evas_Object *obj);
25 static void _smart_del(Evas_Object *obj);
26 static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
27 static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h);
28 static void _smart_show(Evas_Object *obj);
29 static void _smart_hide(Evas_Object *obj);
30 static void _smart_color_set(Evas_Object *obj, int r, int g, int b, int a);
31 static void _smart_clip_set(Evas_Object *obj, Evas_Object * clip);
32 static void _smart_clip_unset(Evas_Object *obj);
33 static void _smart_init(void);
34
35 /* local subsystem globals */
36 static Evas_Smart *_smart = NULL;
37
38 /* externally accessible functions */
39 Evas_Object *
40 _elm_smart_pan_add(Evas *evas)
41 {
42    _smart_init();
43    return evas_object_smart_add(evas, _smart);
44 }
45
46 void
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
81 Evas_Object *
82 _elm_smart_pan_child_get(Evas_Object *obj)
83 {
84    API_ENTRY return NULL;
85    return sd->child_obj;
86 }
87
88 void
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
103 void
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
111 void
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
127 void
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
137 void
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
145 void
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
157 void
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 */
166 static 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
176 static 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
193 static 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
217 static 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
234 static void
235 _smart_del(Evas_Object *obj)
236 {
237    INTERNAL_ENTRY;
238    _elm_smart_pan_child_set(obj, NULL);
239    free(sd);
240 }
241
242 static 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
251 static 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
261 static 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
269 static 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
277 static 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
285 static 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
293 static 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
303 static 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