82ac2d7430647036c5ae254715752d2b6e9671b7
[framework/uifw/e17.git] / src / modules / everything / evry_view_tabs.c
1 #include "e_mod_main.h"
2
3
4 typedef struct _Tab Tab;
5
6 struct _Tab
7 {
8   Tab_View *tab_view;
9   Evry_Plugin *plugin;
10   Evas_Object *o_tab;
11
12   int cw, mw;
13 };
14
15 static void _tabs_update(Tab_View *v);
16 static void _plugin_select(Tab_View *v, Evry_Plugin *p);
17 static void _plugin_next(Tab_View *v);
18 static void _plugin_prev(Tab_View *v);
19
20 static Eina_Bool
21 _timer_cb(void *data)
22 {
23    Tab_View *v = data;
24
25    _tabs_update(v);
26
27    v->timer = NULL;
28    return ECORE_CALLBACK_CANCEL;
29 }
30
31 static void
32 _tab_cb_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
33 {
34    /* Evas_Event_Mouse_Down *ev = event_info; */
35 }
36
37 static void
38 _tab_cb_up(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
39 {
40    Evas_Event_Mouse_Up *ev = event_info;
41    Tab *tab = data;
42    Tab_View *v = tab->tab_view;
43
44    if (ev->button != 1)
45      return;
46
47    if (tab->plugin)
48      {
49         _plugin_select(v, tab->plugin);
50         v->view->update(v->view);
51      }
52    else
53      {
54         evry_browse_back(v->state->selector);
55      }
56 }
57 static void
58 _tabs_cb_wheel(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info)
59 {
60    Evas_Event_Mouse_Wheel *ev = event_info;
61    Tab_View *v = data;
62
63    if (ev->z > 0)
64      {
65         _plugin_next(v);
66         v->view->update(v->view);
67      }
68    else if (ev->z < 0)
69      {
70         _plugin_prev(v);
71         v->view->update(v->view);
72      }
73 }
74 static Tab *
75 _add_tab(Tab_View *v, Evry_Plugin *p)
76 {
77    Evas_Object *o;
78    Tab *tab = E_NEW(Tab, 1);
79    tab->plugin = p;
80    tab->tab_view = v;
81    o = edje_object_add(v->evas);
82    if (p)
83      {
84         e_theme_edje_object_set(o, "base/theme/modules/everything",
85               "e/modules/everything/tab_item");
86         edje_object_part_text_set(o, "e.text.label", EVRY_ITEM(p)->label);
87      }
88    else
89      {
90         e_theme_edje_object_set(o, "base/theme/modules/everything",
91               "e/modules/everything/tab_item/back");
92         edje_object_part_text_set(o, "e.text.label", _("Back"));
93      }
94
95    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_DOWN,
96                                   _tab_cb_down, tab);
97    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_UP,
98                                   _tab_cb_up, tab);
99    tab->o_tab = o;
100
101    edje_object_size_min_calc(o, &tab->cw, NULL);
102    edje_object_size_min_get(o,  &tab->mw, NULL);
103
104    v->tabs = eina_list_append(v->tabs, tab);
105
106    return tab;
107 }
108
109 static void
110 _tabs_update(Tab_View *v)
111 {
112    Eina_List *l, *ll, *plugins;
113    Evry_Plugin *p;
114    const Evry_State *s = v->state;
115    Tab *tab;
116    Evas_Coord w, x;
117    Evas_Object *o;
118    unsigned int cur = 0, i = 0;
119
120    if (s->delete_me)
121      return;
122    
123    edje_object_calc_force(v->o_tabs);
124    evas_object_geometry_get(v->o_tabs, &x, NULL, &w, NULL);
125
126    if (!w && !v->timer)
127      {
128         v->timer = ecore_timer_add(0.001, _timer_cb, v); 
129         return;
130      }
131
132    /* remove tabs for not active plugins */
133    e_box_freeze(v->o_tabs);
134
135    EINA_LIST_FOREACH(v->tabs, l, tab)
136      {
137         if (!tab->plugin)
138           continue;
139
140         e_box_unpack(tab->o_tab);
141         evas_object_hide(tab->o_tab);
142      }
143
144    if (s->selector->states->next)
145      {
146         cur++;
147         i++;
148
149         if (!(tab = eina_list_data_get(v->tabs)))
150           {
151              tab = _add_tab(v, NULL);
152
153              o = tab->o_tab;
154              evas_object_show(o);
155              e_box_pack_end(v->o_tabs, o);
156              e_box_pack_options_set(o, 1, 1, 0, 0, 0.0, 0.5, w/4, 10, w/3, 9999);
157           }
158      }
159
160    for(l = s->cur_plugins; l; l = l->next, cur++)
161      if (l->data == s->plugin) break;
162
163    if (cur > 2)
164      {
165         if ((cur + 1) == eina_list_count(s->cur_plugins))
166           plugins = eina_list_nth_list(s->cur_plugins, cur - 3);
167         else
168           plugins = eina_list_nth_list(s->cur_plugins, cur - 2);
169      }
170    else
171      {
172         plugins = s->cur_plugins;
173      }
174
175    /* show/update tabs of active plugins */
176    EINA_LIST_FOREACH(plugins, l, p)
177      {
178         EINA_LIST_FOREACH(v->tabs, ll, tab)
179           if (tab->plugin == p) break;
180
181         if (!tab && !(tab = _add_tab(v, p)))
182           continue;
183
184         o = tab->o_tab;
185         evas_object_show(o);
186         e_box_pack_end(v->o_tabs, o);
187         e_box_pack_options_set(o, 1, 1, 0, 0, 0.0, 0.5, w/4, 10, w/3, 9999);
188
189         if (s->plugin == p)
190           edje_object_signal_emit(o, "e,state,selected", "e");
191         else
192           edje_object_signal_emit(o, "e,state,unselected", "e");
193
194         if (++i > 3) break;
195      }
196
197    e_box_align_set(v->o_tabs, 0.0, 0.5);
198    e_box_thaw(v->o_tabs);
199 }
200
201
202 static void
203 _tabs_clear(Tab_View *v)
204 {
205    Eina_List *l;
206    Tab *tab;
207
208    e_box_freeze(v->o_tabs);
209    EINA_LIST_FOREACH(v->tabs, l, tab)
210      {
211         if (!tab->plugin)
212           continue;
213
214         e_box_unpack(tab->o_tab);
215         evas_object_hide(tab->o_tab);
216      }
217    e_box_thaw(v->o_tabs);
218 }
219
220 static void
221 _plugin_select(Tab_View *v, Evry_Plugin *p)
222 {
223    evry_plugin_select(p);
224
225    _tabs_update(v);
226 }
227
228 static void
229 _plugin_next(Tab_View *v)
230 {
231    Eina_List *l;
232    Evry_Plugin *p = NULL;
233    const Evry_State *s = v->state;
234
235    if (!s->plugin) return;
236
237    l = eina_list_data_find_list(s->cur_plugins, s->plugin);
238
239    if (l && l->next)
240      p = l->next->data;
241    else if (s->plugin != s->cur_plugins->data)
242      p = s->cur_plugins->data;
243
244    if (p) _plugin_select(v, p);
245 }
246
247 static void
248 _plugin_next_by_name(Tab_View *v, const char *key)
249 {
250    Eina_List *l;
251    Evry_Plugin *p, *first = NULL, *next = NULL;
252    int found = 0;
253    const Evry_State *s = v->state;
254
255    if (!s->plugin) return;
256
257    EINA_LIST_FOREACH(s->cur_plugins, l, p)
258      {
259         /* if (!p)
260          *   {
261          *      // FIXME how can this happen?
262          *      ERR("plugin == NULL");
263          *      continue;
264          *   } */
265
266         if (EVRY_ITEM(p)->label && (!strncasecmp(EVRY_ITEM(p)->label, key, 1)))
267           {
268              if (!first) first = p;
269
270              if (found && !next)
271                next = p;
272           }
273         if (p == s->plugin) found = 1;
274      }
275
276    if (next)
277      p = next;
278    else if (first != s->plugin)
279      p = first;
280    else
281      p = NULL;
282
283    if (p) _plugin_select(v, p);
284 }
285
286 static void
287 _plugin_prev(Tab_View *v)
288 {
289    Eina_List *l;
290    Evry_Plugin *p = NULL;
291    const Evry_State *s = v->state;
292
293    if (!s->plugin) return;
294
295    l = eina_list_data_find_list(s->cur_plugins, s->plugin);
296
297    if (l && l->prev)
298      p = l->prev->data;
299    else
300      {
301         l = eina_list_last(s->cur_plugins);
302         if (s->plugin != l->data)
303           p = l->data;
304      }
305
306    if (p) _plugin_select(v, p);
307 }
308
309
310 static int
311 _tabs_key_down(Tab_View *v, const Ecore_Event_Key *ev)
312 {
313    const char *key = ev->key;
314
315    if (!v->state || !v->state->cur_plugins) return 0;
316
317    if (ev->modifiers & ECORE_EVENT_MODIFIER_SHIFT)
318      {
319         if (!strcmp(key, "Next"))
320           {
321              _plugin_next(v);
322              return 1;
323           }
324         else if (!strcmp(key, "Prior"))
325           {
326              _plugin_prev(v);
327              return 1;
328           }
329      }
330    else if (ev->modifiers & ECORE_EVENT_MODIFIER_CTRL)
331      {
332         if (!strcmp(key, "Left"))
333           {
334              _plugin_prev(v);
335              return 1;
336           }
337         else if (!strcmp(key, "Right"))
338           {
339              _plugin_next(v);
340              return 1;
341           }
342         else if (ev->compose)
343           {
344              _plugin_next_by_name(v, key);
345              return 1;
346           }
347      }
348
349    return 0;
350 }
351
352
353 Tab_View *
354 evry_tab_view_new(Evry_View *view, const Evry_State *s, Evas *e)
355 {
356    Tab_View *v;
357    Evas_Object *o;
358
359    v = E_NEW(Tab_View, 1);
360    v->update   = &_tabs_update;
361    v->clear    = &_tabs_clear;
362    v->key_down = &_tabs_key_down;
363    v->view = view;
364    v->state = s;
365
366    v->evas = e;
367    o = e_box_add(e);
368    e_box_orientation_set(o, 1);
369    e_box_homogenous_set(o, 1);
370    evas_object_event_callback_add(o, EVAS_CALLBACK_MOUSE_WHEEL,
371                                   _tabs_cb_wheel, v);
372    v->o_tabs = o;
373
374    return v;
375 }
376
377 void
378 evry_tab_view_free(Tab_View *v)
379 {
380    Tab *tab;
381
382    EINA_LIST_FREE(v->tabs, tab)
383      {
384         e_box_unpack(tab->o_tab);
385         evas_object_del(tab->o_tab);
386         E_FREE(tab);
387      }
388
389    evas_object_del(v->o_tabs);
390
391    if (v->animator)
392      ecore_animator_del(v->animator);
393
394    if (v->timer)
395      ecore_timer_del(v->timer);
396
397    E_FREE(v);
398 }