Tizen 2.1 release
[platform/core/uifw/e17.git] / src / modules / tiling / e_mod_config.c
1 #include "e_mod_tiling.h"
2
3 /* HACK: Needed to get subobjs of the widget. Is there a better way? */
4 typedef struct _E_Widget_Smart_Data E_Widget_Smart_Data;
5
6 struct _E_Widget_Smart_Data
7 {
8    Evas_Object *parent_obj;
9    Evas_Coord   x, y, w, h;
10    Evas_Coord   minw, minh;
11    Eina_List   *subobjs;
12 };
13
14 /* Some defines to make coding with the e_widget_* easier for
15  * configuration panel */
16 #define RADIO(title, value, radiogroup) \
17   e_widget_radio_add(evas, _(title), value, radiogroup)
18 #define LIST_ADD(list, object) \
19   e_widget_list_object_append(list, object, 1, 1, 0.5)
20
21 struct _Config_vdesk *
22 get_vdesk(Eina_List *vdesks,
23           int x,
24           int y,
25           unsigned int zone_num)
26 {
27     Eina_List *l;
28     for (l = vdesks; l; l = l->next) {
29         struct _Config_vdesk *vd = l->data;
30
31         if (!vd)
32             continue;
33         if (vd->nb_stacks < 0 || vd->nb_stacks > TILING_MAX_STACKS)
34             vd->nb_stacks = 0;
35         if (vd->x == x && vd->y == y && vd->zone_num == zone_num)
36             return vd;
37     }
38
39     return NULL;
40 }
41
42 /*
43  * Fills the E_Config_Dialog-struct with the data currently in use
44  *
45  */
46 static void *
47 _create_data(E_Config_Dialog *cfd __UNUSED__)
48 {
49     E_Config_Dialog_Data *cfdata;
50     Eina_List *l;
51
52     cfdata = E_NEW(E_Config_Dialog_Data, 1);
53
54     /* Because we save a lot of lines here by using memcpy,
55      * the structs have to be ordered the same */
56     memcpy(cfdata, tiling_g.config, sizeof(Config));
57     cfdata->config.keyhints = strdup(tiling_g.config->keyhints);
58
59     /* Handle things which can't be easily memcpy'd */
60     cfdata->config.vdesks = NULL;
61
62     for (l = tiling_g.config->vdesks; l; l = l->next) {
63         struct _Config_vdesk *vd = l->data,
64                              *newvd;
65
66         if (!vd)
67             continue;
68
69         newvd = E_NEW(struct _Config_vdesk, 1);
70         newvd->x = vd->x;
71         newvd->y = vd->y;
72         newvd->zone_num = vd->zone_num;
73         newvd->nb_stacks = vd->nb_stacks;
74         newvd->use_rows = vd->use_rows;
75
76         EINA_LIST_APPEND(cfdata->config.vdesks, newvd);
77     }
78
79     return cfdata;
80 }
81
82 static void
83 _free_data(E_Config_Dialog      *cfd __UNUSED__,
84            E_Config_Dialog_Data *cfdata)
85 {
86     eina_list_free(cfdata->config.vdesks);
87     free(cfdata->config.keyhints);
88     free(cfdata);
89 }
90
91 static void
92 _fill_zone_config(E_Zone               *zone,
93                   E_Config_Dialog_Data *cfdata)
94 {
95     Evas *evas;
96     int i;
97
98     evas = cfdata->evas;
99
100     /* Clear old entries first */
101     evas_object_del(cfdata->o_desklist);
102
103     cfdata->o_desklist = e_widget_list_add(evas, 1, 0);
104
105     for (i = 0; i < zone->desk_y_count * zone->desk_x_count; i++) {
106         E_Desk *desk = zone->desks[i];
107         struct _Config_vdesk *vd;
108         Evas_Object *list, *slider, *radio;
109         E_Radio_Group *rg;
110
111         if (!desk)
112             continue;
113
114         vd = get_vdesk(cfdata->config.vdesks, desk->x, desk->y, zone->num);
115         if (!vd) {
116             vd = E_NEW(struct _Config_vdesk, 1);
117             vd->x = desk->x;
118             vd->y = desk->y;
119             vd->zone_num = zone->num;
120             vd->nb_stacks = 0;
121             vd->use_rows = 0;
122
123             EINA_LIST_APPEND(cfdata->config.vdesks, vd);
124         }
125
126         list = e_widget_list_add(evas, false, true);
127
128         LIST_ADD(list, e_widget_label_add(evas, desk->name));
129         slider = e_widget_slider_add(evas, 1, 0, _("%1.0f"),
130                                      0.0, 8.0, 1.0, 0, NULL,
131                                      &vd->nb_stacks, 150);
132         LIST_ADD(list, slider);
133
134         rg = e_widget_radio_group_new(&vd->use_rows);
135         radio = e_widget_radio_add(evas, _("columns"), 0, rg);
136         LIST_ADD(list, radio);
137         radio = e_widget_radio_add(evas, _("rows"), 1, rg);
138         LIST_ADD(list, radio);
139
140         LIST_ADD(cfdata->o_desklist, list);
141     }
142
143     /* Get the correct sizes of desklist and scrollframe */
144     LIST_ADD(cfdata->osf, cfdata->o_desklist);
145 }
146
147 static void
148 _cb_zone_change(void        *data,
149                 Evas_Object *obj __UNUSED__)
150 {
151     int n;
152     E_Config_Dialog_Data *cfdata = data;
153     E_Zone *zone;
154
155     if (!cfdata || !cfdata->o_zonelist)
156         return;
157
158     n = e_widget_ilist_selected_get(cfdata->o_zonelist);
159     zone = e_widget_ilist_nth_data_get(cfdata->o_zonelist, n);
160     if (!zone)
161         return;
162     _fill_zone_config(zone, cfdata);
163 }
164
165 static Evas_Object *
166 _basic_create_widgets(E_Config_Dialog      *cfd __UNUSED__,
167                       Evas                 *evas,
168                       E_Config_Dialog_Data *cfdata)
169 {
170     Evas_Object *o, *oc, *of;
171     E_Container *con;
172     E_Zone *zone;
173     Eina_List *l;
174
175     con = e_container_current_get(e_manager_current_get());
176
177     o = e_widget_list_add(evas, 0, 0);
178
179     /* General settings */
180     of = e_widget_framelist_add(evas, _("General"), 0);
181     e_widget_framelist_object_append(of,
182       e_widget_check_add(evas, _("Tile dialog windows as well"),
183                          &cfdata->config.tile_dialogs));
184     e_widget_framelist_object_append(of,
185       e_widget_check_add(evas, _("Show window titles"),
186                          &cfdata->config.show_titles));
187     oc = e_widget_list_add(evas, false, true);
188     e_widget_list_object_append(oc,
189       e_widget_label_add(evas, _("Key hints")), 1, 0, 0.5);
190     e_widget_list_object_append(oc,
191       e_widget_entry_add(evas, &cfdata->config.keyhints, NULL, NULL, NULL),
192       1, 1, 0.5);
193     e_widget_framelist_object_append(of, oc);
194
195     LIST_ADD(o, of);
196
197     /* Virtual desktop settings */
198     of = e_widget_framelist_add(evas, _("Virtual Desktops"), 0);
199     e_widget_label_add(evas,
200                        _("Number of columns used to tile per desk"
201                           " (0 → tiling disabled):"));
202     cfdata->osf = e_widget_list_add(evas, 0, 1);
203
204     /* Zone list */
205     cfdata->o_zonelist = e_widget_ilist_add(evas, 0, 0, NULL);
206     e_widget_ilist_multi_select_set(cfdata->o_zonelist, false);
207     e_widget_size_min_set(cfdata->o_zonelist, 100, 100);
208     e_widget_on_change_hook_set(cfdata->o_zonelist, _cb_zone_change, cfdata);
209     for (l = con->zones; l; l = l->next) {
210         if (!(zone = l->data))
211             continue;
212         e_widget_ilist_append(cfdata->o_zonelist, NULL, zone->name, NULL, zone, NULL);
213     }
214     e_widget_ilist_go(cfdata->o_zonelist);
215     e_widget_ilist_thaw(cfdata->o_zonelist);
216
217     LIST_ADD(cfdata->osf, cfdata->o_zonelist);
218
219     /* List of individual tiling modes */
220     cfdata->evas = evas;
221
222     _fill_zone_config(eina_list_data_get(con->zones), cfdata);
223
224     e_widget_ilist_selected_set(cfdata->o_zonelist, 0);
225
226     e_widget_framelist_object_append(of, cfdata->osf);
227
228     LIST_ADD(o, of);
229
230     return o;
231 }
232
233 static int
234 _basic_apply_data(E_Config_Dialog      *cfd __UNUSED__,
235                   E_Config_Dialog_Data *cfdata)
236 {
237     struct _Config_vdesk *vd;
238     Eina_List *l;
239
240     tiling_g.config->tile_dialogs = cfdata->config.tile_dialogs;
241     tiling_g.config->show_titles = cfdata->config.show_titles;
242     if (strcmp(tiling_g.config->keyhints, cfdata->config.keyhints)) {
243         free(tiling_g.config->keyhints);
244         if (!cfdata->config.keyhints || !*cfdata->config.keyhints) {
245             tiling_g.config->keyhints = strdup(tiling_g.default_keyhints);
246         } else {
247             char *c = cfdata->config.keyhints;
248             int len = strlen(cfdata->config.keyhints);
249
250             /* Remove duplicates */
251             while (*c) {
252                 char *f = c + 1;
253
254                 while ((f = strchr(f, *c))) {
255                     *f = cfdata->config.keyhints[--len];
256                     cfdata->config.keyhints[len] = '\0';
257                 }
258                 c++;
259             }
260             tiling_g.config->keyhints = strdup(cfdata->config.keyhints);
261         }
262     }
263
264     /* Check if the layout for one of the vdesks has changed */
265     for (l = tiling_g.config->vdesks; l; l = l->next) {
266         struct _Config_vdesk *newvd;
267
268         vd = l->data;
269
270         if (!vd)
271             continue;
272         if (!(newvd = get_vdesk(cfdata->config.vdesks,
273                                 vd->x, vd->y, vd->zone_num))) {
274             change_desk_conf(vd);
275             continue;
276         }
277
278         if (newvd->nb_stacks != vd->nb_stacks
279         ||  newvd->use_rows != vd->use_rows) {
280             DBG("number of columns for (%d, %d, %d) changed from %d|%d"
281                 " to %d|%d",
282                 vd->x, vd->y, vd->zone_num,
283                 vd->nb_stacks, vd->use_rows,
284                 newvd->nb_stacks, newvd->use_rows);
285             change_desk_conf(newvd);
286             free(vd);
287             l->data = NULL;
288         }
289     }
290
291     for (l = cfdata->config.vdesks; l; l = l->next) {
292         vd = l->data;
293
294         if (!vd)
295             continue;
296         if (!get_vdesk(tiling_g.config->vdesks,
297                        vd->x, vd->y, vd->zone_num)) {
298             change_desk_conf(vd);
299             continue;
300         }
301     }
302
303     EINA_LIST_FREE(tiling_g.config->vdesks, vd) {
304         free(vd);
305     }
306     tiling_g.config->vdesks = NULL;
307
308     for (l = cfdata->config.vdesks; l; l = l->next) {
309         struct _Config_vdesk *newvd;
310
311         vd = l->data;
312         if (!vd)
313             continue;
314
315         newvd = E_NEW(struct _Config_vdesk, 1);
316         newvd->x = vd->x;
317         newvd->y = vd->y;
318         newvd->zone_num = vd->zone_num;
319         newvd->nb_stacks = vd->nb_stacks;
320         newvd->use_rows = vd->use_rows;
321
322         EINA_LIST_APPEND(tiling_g.config->vdesks, newvd);
323     }
324
325     e_tiling_update_conf();
326
327     e_config_save_queue();
328
329     return EINA_TRUE;
330 }
331
332 E_Config_Dialog *
333 e_int_config_tiling_module(E_Container *con,
334                            const char  *params __UNUSED__)
335 {
336     E_Config_Dialog *cfd;
337     E_Config_Dialog_View *v;
338     char buf[PATH_MAX];
339
340     if (e_config_dialog_find("E", "windows/tiling"))
341         return NULL;
342
343     v = E_NEW(E_Config_Dialog_View, 1);
344
345     v->create_cfdata = _create_data;
346     v->free_cfdata = _free_data;
347     v->basic.apply_cfdata = _basic_apply_data;
348     v->basic.create_widgets = _basic_create_widgets;
349
350     snprintf(buf, sizeof(buf), "%s/e-module-tiling.edj",
351              e_module_dir_get(tiling_g.module));
352     cfd = e_config_dialog_new(con,
353                               _("Tiling Configuration"),
354                               "E", "windows/tiling",
355                               buf, 0, v, NULL);
356     return cfd;
357 }