move elementary to trunk base. out of TMP/st.
[framework/uifw/elementary.git] / src / lib / elm_table.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3
4 /**
5  * @defgroup Table Table
6  *
7  * Arranges widgets in a table where items can also span multiple
8  * columns or rows - even overlap (and then be raised or lowered
9  * accordingly to adjust stacking if they do overlap).
10  */
11
12 typedef struct _Widget_Data Widget_Data;
13
14 struct _Widget_Data
15 {
16    Evas_Object *tbl;
17 };
18
19 static const char *widtype = NULL;
20 static void _del_hook(Evas_Object *obj);
21 static void _sizing_eval(Evas_Object *obj);
22 static void _changed_size_hints(void *data, Evas *e, Evas_Object *obj, void *event_info);
23 static void _sub_del(void *data, Evas_Object *obj, void *event_info);
24
25 static void
26 _del_pre_hook(Evas_Object *obj)
27 {
28    Widget_Data *wd = elm_widget_data_get(obj);
29    if (!wd) return;
30    evas_object_event_callback_del_full
31      (wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _changed_size_hints, obj);
32    evas_object_del(wd->tbl);
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    free(wd);
41 }
42
43 static Eina_Bool
44 _elm_table_focus_next_hook(const Evas_Object *obj, Elm_Focus_Direction dir, Evas_Object **next)
45 {
46    Widget_Data *wd = elm_widget_data_get(obj);
47    const Eina_List *items;
48    void *(*list_data_get) (const Eina_List *list);
49    Eina_List *(*list_free) (Eina_List *list);
50
51    if ((!wd) || (!wd->tbl))
52      return EINA_FALSE;
53
54    /* Focus chain */
55    /* TODO: Change this to use other chain */
56    if ((items = elm_widget_focus_custom_chain_get(obj)))
57      {
58         list_data_get = eina_list_data_get;
59         list_free = NULL;
60      }
61    else
62      {
63         items = evas_object_table_children_get(wd->tbl);
64         list_data_get = eina_list_data_get;
65         list_free = eina_list_free;
66
67         if (!items) return EINA_FALSE;
68      }
69
70    Eina_Bool ret = elm_widget_focus_list_next_get(obj, items, list_data_get,
71                                                    dir, next);
72
73    if (list_free)
74      list_free((Eina_List *)items);
75
76    return ret;
77 }
78
79 static void
80 _sizing_eval(Evas_Object *obj)
81 {
82    Widget_Data *wd = elm_widget_data_get(obj);
83    Evas_Coord minw = -1, minh = -1, maxw = -1, maxh = -1;
84    Evas_Coord w, h;
85    if (!wd) return;
86    evas_object_size_hint_min_get(wd->tbl, &minw, &minh);
87    evas_object_size_hint_max_get(wd->tbl, &maxw, &maxh);
88    evas_object_size_hint_min_set(obj, minw, minh);
89    evas_object_size_hint_max_set(obj, maxw, maxh);
90    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
91    if (w < minw) w = minw;
92    if (h < minh) h = minh;
93    if ((maxw >= 0) && (w > maxw)) w = maxw;
94    if ((maxh >= 0) && (h > maxh)) h = maxh;
95    evas_object_resize(obj, w, h);
96 }
97
98 static void
99 _changed_size_hints(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
100 {
101    _sizing_eval(data);
102 }
103
104 static void
105 _sub_del(void *data __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
106 {
107    _sizing_eval(obj);
108 }
109
110 /**
111  * Add a new table to the parent
112  *
113  * @param parent The parent object
114  * @return The new object or NULL if it cannot be created
115  *
116  * @ingroup Table
117  */
118 EAPI Evas_Object *
119 elm_table_add(Evas_Object *parent)
120 {
121    Evas_Object *obj;
122    Evas *e;
123    Widget_Data *wd;
124
125    EINA_SAFETY_ON_NULL_RETURN_VAL(parent, NULL);
126
127    wd = ELM_NEW(Widget_Data);
128    e = evas_object_evas_get(parent);
129    if (!e) return NULL;
130    obj = elm_widget_add(e);
131    ELM_SET_WIDTYPE(widtype, "table");
132    elm_widget_type_set(obj, "table");
133    elm_widget_sub_object_add(parent, obj);
134    elm_widget_data_set(obj, wd);
135    elm_widget_del_hook_set(obj, _del_hook);
136    elm_widget_del_pre_hook_set(obj, _del_pre_hook);
137    elm_widget_focus_next_hook_set(obj, _elm_table_focus_next_hook);
138    elm_widget_can_focus_set(obj, EINA_FALSE);
139    elm_widget_highlight_ignore_set(obj, EINA_FALSE);
140
141    wd->tbl = evas_object_table_add(e);
142    evas_object_event_callback_add(wd->tbl, EVAS_CALLBACK_CHANGED_SIZE_HINTS,
143                                   _changed_size_hints, obj);
144    elm_widget_resize_object_set(obj, wd->tbl);
145
146    evas_object_smart_callback_add(obj, "sub-object-del", _sub_del, obj);
147
148    return obj;
149 }
150
151 /**
152  * Set the homogenous layout in the table
153  *
154  * @param obj The layout object
155  * @param homogenous A boolean to set (or no) layout homogenous
156  * in the table
157  * (1 = homogenous,  0 = no homogenous)
158  *
159  * @ingroup Table
160  */
161 EAPI void
162 elm_table_homogenous_set(Evas_Object *obj, Eina_Bool homogenous)
163 {
164    ELM_CHECK_WIDTYPE(obj, widtype);
165    Widget_Data *wd = elm_widget_data_get(obj);
166    if (!wd) return;
167    evas_object_table_homogeneous_set(wd->tbl, homogenous);
168 }
169
170 /**
171  * Get the current table homogenous mode.
172  *
173  * @param obj The table object
174  * @return a boolean to set (or no) layout homogenous in the table
175  * (1 = homogenous,  0 = no homogenous)
176  *
177  * @ingroup Table
178  */
179 EAPI Eina_Bool
180 elm_table_homogenous_get(const Evas_Object *obj)
181 {
182    ELM_CHECK_WIDTYPE(obj, widtype) EINA_FALSE;
183    Widget_Data *wd = elm_widget_data_get(obj);
184    if (!wd) return EINA_FALSE;
185    return evas_object_table_homogeneous_get(wd->tbl);
186 }
187
188 /**
189  * Set padding between cells.
190  *
191  * @param obj The layout object.
192  * @param horizontal set the horizontal padding.
193  * @param vertical set the vertical padding.
194  *
195  * @ingroup Table
196  */
197 EAPI void
198 elm_table_padding_set(Evas_Object *obj, Evas_Coord horizontal, Evas_Coord vertical)
199 {
200    ELM_CHECK_WIDTYPE(obj, widtype);
201    Widget_Data *wd = elm_widget_data_get(obj);
202    if (!wd) return;
203    evas_object_table_padding_set(wd->tbl, horizontal, vertical);
204 }
205
206 /**
207  * Get padding between cells.
208  *
209  * @param obj The layout object.
210  * @param horizontal set the horizontal padding.
211  * @param vertical set the vertical padding.
212  *
213  * @ingroup Table
214  */
215 EAPI void
216 elm_table_padding_get(const Evas_Object *obj, Evas_Coord *horizontal, Evas_Coord *vertical)
217 {
218    ELM_CHECK_WIDTYPE(obj, widtype);
219    Widget_Data *wd = elm_widget_data_get(obj);
220    if (!wd) return;
221    evas_object_table_padding_get(wd->tbl, horizontal, vertical);
222 }
223
224 /**
225  * Add a subobject on the table with the coordinates passed
226  *
227  * @param obj The table object
228  * @param subobj The subobject to be added to the table
229  * @param x Coordinate to X axis
230  * @param y Coordinate to Y axis
231  * @param w Horizontal length
232  * @param h Vertical length
233  *
234  * @ingroup Table
235  */
236 EAPI void
237 elm_table_pack(Evas_Object *obj, Evas_Object *subobj, int x, int y, int w, int h)
238 {
239    ELM_CHECK_WIDTYPE(obj, widtype);
240    Widget_Data *wd = elm_widget_data_get(obj);
241    if (!wd) return;
242    elm_widget_sub_object_add(obj, subobj);
243    evas_object_table_pack(wd->tbl, subobj, x, y, w, h);
244 }
245
246 /**
247  * Remove child from table.
248  *
249  * @param obj The table object
250  * @param subobj The subobject
251  *
252  * @ingroup Table
253  */
254 EAPI void
255 elm_table_unpack(Evas_Object *obj, Evas_Object *subobj)
256 {
257    ELM_CHECK_WIDTYPE(obj, widtype);
258    Widget_Data *wd = elm_widget_data_get(obj);
259    if (!wd) return;
260    elm_widget_sub_object_del(obj, subobj);
261    evas_object_table_unpack(wd->tbl, subobj);
262 }
263
264 /**
265  * Faster way to remove all child objects from a table object.
266  *
267  * @param obj The table object
268  * @param clear If true, it will delete just removed children
269  *
270  * @ingroup Table
271  */
272 EAPI void
273 elm_table_clear(Evas_Object *obj, Eina_Bool clear)
274 {
275    ELM_CHECK_WIDTYPE(obj, widtype);
276    Widget_Data *wd = elm_widget_data_get(obj);
277    if (!wd) return;
278    evas_object_table_clear(wd->tbl, clear);
279 }