EFL migration revision 67547
[framework/uifw/elementary.git] / tests / src / lib / elm_colorpalette.c
1 #include <Elementary.h>
2 #include "elm_priv.h"
3 #include <Ecore.h>
4
5 #define MAX_NUM_COLORS 30
6
7 typedef struct _Colorpalette_Item Colorpalette_Item;
8 typedef struct _Widget_Data Widget_Data;
9
10 struct _Colorpalette_Item
11 {
12    Evas_Object *obj;
13    Evas_Object *lo;
14    Evas_Object *cr;
15    unsigned int r, g, b;
16 };
17
18 struct _Widget_Data
19 {
20    Evas_Object *base;
21    Evas_Object *tab;
22    Elm_Colorpalette_Color *color;
23    Eina_List *items;
24    unsigned int row, col;
25    unsigned int num;
26 };
27
28 static const char *widtype = NULL;
29 static void _del_hook(Evas_Object *obj);
30 static void _theme_hook(Evas_Object *obj);
31 static void _sizing_eval(Evas_Object *obj);
32 static void _colorpalette_object_resize(void *data, Evas *e, Evas_Object *obj, void *event_info);
33 static void _color_select_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
34 static void _color_release_cb(void *data, Evas *e, Evas_Object *obj, void *event_info);
35 static void _color_table_delete(Evas_Object *obj);
36 static void _color_table_update(Evas_Object *obj, unsigned int row, unsigned int col, unsigned int color_num, Elm_Colorpalette_Color *color);
37
38 static void
39 _del_hook(Evas_Object *obj)
40 {
41    Widget_Data *wd = elm_widget_data_get(obj);
42    if (!wd) return;
43    _color_table_delete(obj);
44    if (wd->color)
45      {
46         free(wd->color);
47      }
48    free(wd);
49 }
50
51 static void
52 _theme_hook(Evas_Object *obj)
53 {
54    Widget_Data *wd = elm_widget_data_get(obj);
55    _elm_theme_object_set(obj, wd->base, "colorpalette", "base", elm_widget_style_get(obj));
56    _color_table_update(obj, wd->row, wd->col, wd->num, wd->color);
57    _sizing_eval(obj);
58 }
59
60 static void
61 _sizing_eval(Evas_Object *obj)
62 {
63    Widget_Data *wd = NULL;
64    Colorpalette_Item *item = NULL;
65    Evas_Coord tab_w = 0, tab_h = 0;
66    Evas_Coord pad_x = 0, pad_y = 0;
67    Evas_Coord rect_w = 0, rect_h = 0;
68    Evas_Coord minw = -1, minh = -1;
69
70    wd = elm_widget_data_get((Evas_Object *)obj);
71    elm_coords_finger_size_adjust(1, &minw, 1, &minh);
72    edje_object_size_min_restricted_calc(wd->base, &minw, &minh, minw, minh);
73    evas_object_size_hint_min_set(obj, minw, minh);
74    evas_object_size_hint_max_set(obj, -1, -1);
75
76    edje_object_part_geometry_get(wd->base,"bg" ,NULL, NULL, &tab_w, &tab_h);
77    if (wd->items)
78      item = wd->items->data;
79    edje_object_part_geometry_get(elm_layout_edje_get(item->lo),"bg" ,NULL, NULL, &rect_w, &rect_h);
80    if (wd->col - 1) /*value cannot be 0 else divide by zero error will cause floating point exception*/
81      pad_x = (tab_w - (rect_w * wd->col)) / (wd->col - 1);
82    if (wd->row - 1) /*value cannot be 0 else divide by zero error will cause floating point exception*/
83      pad_y = (tab_h - (rect_h * wd->row)) / (wd->row - 1);
84    elm_table_padding_set(wd->tab, pad_x, pad_y);
85    elm_table_homogeneous_set(wd->tab, EINA_TRUE);
86 }
87
88 static void _colorpalette_object_resize(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
89 {
90    _sizing_eval(data);
91 }
92
93 static void _color_select_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
94 {
95    Colorpalette_Item *item = (Colorpalette_Item *) data;
96    edje_object_signal_emit(elm_layout_edje_get(item->lo), "focus_visible", "elm");
97 }
98
99 static void _color_release_cb(void *data, Evas *e __UNUSED__, Evas_Object *obj __UNUSED__, void *event_info __UNUSED__)
100 {
101    Elm_Colorpalette_Color *color;
102    Colorpalette_Item *item = (Colorpalette_Item *) data;
103    color = ELM_NEW(Elm_Colorpalette_Color);
104    if (!color) return;
105    color->r = item->r;
106    color->g = item->g;
107    color->b = item->b;
108    edje_object_signal_emit(elm_layout_edje_get(item->lo), "focus_invisible", "elm");
109    evas_object_smart_callback_call(item->obj, "clicked", color);
110 }
111
112 static void _color_table_delete(Evas_Object *obj)
113 {
114    Widget_Data *wd = NULL;
115    Colorpalette_Item *item;
116    wd = elm_widget_data_get(obj);
117
118    if (wd->items)
119      {
120         EINA_LIST_FREE(wd->items, item)
121           {
122              if (item->lo)
123                {
124                   evas_object_del(item->lo);
125                   item->lo = NULL;
126                }
127              if (item->cr)
128                {
129                   evas_object_del(item->cr);
130                   item->cr = NULL;
131                }
132              free(item);
133           }
134      }
135    if (wd->tab) evas_object_del(wd->tab);
136 }
137
138 static void _color_table_update(Evas_Object *obj, unsigned int row, unsigned int col, unsigned int color_num, Elm_Colorpalette_Color *color)
139 {
140    Widget_Data *wd = elm_widget_data_get(obj);
141    Colorpalette_Item *item;
142    Evas_Object *lo;
143    Evas_Object *cr;
144    unsigned int i, j, count;
145
146    _color_table_delete(obj);
147    count = 0;
148    wd->row = row;
149    wd->col = col;
150    wd->num = color_num;
151
152    wd->tab = elm_table_add(obj);
153    evas_object_size_hint_weight_set(wd->tab, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
154    evas_object_size_hint_align_set(wd->tab, EVAS_HINT_FILL, EVAS_HINT_FILL);
155    edje_object_part_swallow(wd->base, "palette", wd->tab);
156
157    for ( i = 0 ; i < row ; i++)
158      {
159         for ( j = 0 ; j < col ; j++ )
160           {
161              item = ELM_NEW(Colorpalette_Item);
162              if (item)
163                {
164                   lo = elm_layout_add(obj);
165                   elm_layout_theme_set(lo, "colorpalette", "base", "bg");
166                   evas_object_size_hint_weight_set(lo, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
167                   evas_object_size_hint_align_set(lo, EVAS_HINT_FILL, EVAS_HINT_FILL);
168                   evas_object_show(lo);
169                   elm_table_pack(wd->tab, lo, (int)j, (int)i, 1, 1);
170                   item->obj = obj;
171                   item->lo = lo;
172                   if (count < color_num)
173                     {
174                        cr =  edje_object_add(evas_object_evas_get(obj));
175                        _elm_theme_object_set(obj, cr, "colorpalette", "base", "color");
176                        evas_object_color_set(cr, color[count].r, color[count].g, color[count].b, 255);
177                        evas_object_size_hint_weight_set(cr, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
178                        evas_object_size_hint_align_set(cr, EVAS_HINT_FILL, EVAS_HINT_FILL);
179                        evas_object_event_callback_add(cr, EVAS_CALLBACK_MOUSE_DOWN, _color_select_cb, item);
180                        evas_object_event_callback_add(cr, EVAS_CALLBACK_MOUSE_UP, _color_release_cb, item);
181                        evas_object_show(cr);
182                        edje_object_part_swallow(elm_layout_edje_get(lo), "color_rect", cr);
183                        item->cr = cr;
184                        item->r = color[count].r;
185                        item->g = color[count].g;
186                        item->b = color[count].b;
187                     }
188                   wd->items = eina_list_append(wd->items, item);
189                   count ++;
190                }
191           }
192      }
193 }
194
195 static int
196 _hex_string_get(char ch)
197 {
198    if ((ch >= '0') && (ch <= '9')) return (ch - '0');
199    else if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10);
200    else if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10);
201    return 0;
202 }
203
204 static void
205 _color_parse(const char *str, unsigned char *r, unsigned char *g, unsigned char *b)
206 {
207    int slen;
208
209    slen = strlen(str);
210    *r = *g = *b = 0;
211
212    if (slen == 7) /* #RRGGBB */
213      {
214         *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
215         *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
216         *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
217      }
218    *r = (*r * 0xff) / 255;
219    *g = (*g * 0xff) / 255;
220    *b = (*b * 0xff) / 255;
221 }
222
223 EAPI Evas_Object *elm_colorpalette_add(Evas_Object *parent)
224 {
225    Evas_Object *obj = NULL;
226    Widget_Data *wd = NULL;
227    Evas *e;
228    Eina_List *colors;
229    const Eina_List *l;
230    const char *color_code;
231    const char *rowstr, *colstr, *color_numstr;
232    int color_num = 10;
233    int row = 2;
234    int col = 5;
235    int index = 0;
236
237    ELM_WIDGET_STANDARD_SETUP(wd, Widget_Data, parent, e, obj, NULL);
238
239    ELM_SET_WIDTYPE(widtype, "colorpalette");
240    elm_widget_type_set(obj, "colorpalette");
241    elm_widget_sub_object_add(parent, obj);
242    elm_widget_data_set(obj, wd);
243    elm_widget_del_hook_set(obj, _del_hook);
244    elm_widget_theme_hook_set(obj, _theme_hook);
245
246    wd->base = edje_object_add(e);
247    _elm_theme_object_set(obj, wd->base, "colorpalette", "base", "default");
248    elm_widget_resize_object_set(obj, wd->base);
249
250    color_numstr = edje_object_data_get(wd->base, "color_num");
251    if (color_numstr) color_num = atoi(color_numstr); /* Need to get this value
252    from edc inorder to allocate memory in advance: Think of a better way*/
253    rowstr = edje_object_data_get(wd->base, "row");
254    if (rowstr) row = atoi(rowstr);
255    colstr = edje_object_data_get(wd->base, "col");
256    if (colstr) col = atoi(colstr);
257    wd->color = (Elm_Colorpalette_Color*) calloc (color_num, sizeof(Elm_Colorpalette_Color));
258    colors = elm_widget_stringlist_get(edje_object_data_get(wd->base, "colors"));
259    EINA_LIST_FOREACH(colors, l, color_code)
260      {
261         unsigned char r, g, b;
262         /*Optimized color parsing algorithm*/
263         _color_parse(color_code, &r, &g, &b);
264         /*TODO: Make color storing structure and item also take unsigned char*/
265         wd->color[index].r = (unsigned int)r;
266         wd->color[index].g = (unsigned int)g;
267         wd->color[index].b = (unsigned int)b;
268         index++;
269      }
270    elm_widget_stringlist_free(colors);
271    _color_table_update(obj, row, col, color_num, wd->color);
272    evas_object_event_callback_add(wd->base, EVAS_CALLBACK_RESIZE, _colorpalette_object_resize, obj);
273    _sizing_eval(obj);
274    return obj;
275 }
276
277
278 EAPI void elm_colorpalette_color_set(Evas_Object *obj, int color_num, Elm_Colorpalette_Color *color)
279 {
280    ELM_CHECK_WIDTYPE(obj, widtype);
281    Widget_Data *wd = elm_widget_data_get(obj);
282    int i;
283
284    if (color_num > MAX_NUM_COLORS) return;
285    if (!wd) return;
286
287    if (wd->color)
288      {
289         free(wd->color);
290         wd->color = NULL;
291      }
292    wd->color = (Elm_Colorpalette_Color*) calloc (color_num, sizeof(Elm_Colorpalette_Color));
293    for (i = 0; i < color_num; i++)
294      {
295         wd->color[i].r = color[i].r;
296         wd->color[i].g = color[i].g;
297         wd->color[i].b = color[i].b;
298      }
299    _color_table_update(obj, wd->row, wd->col, color_num, wd->color);
300    _sizing_eval(obj);
301 }
302
303 EAPI void elm_colorpalette_row_column_set(Evas_Object *obj, int row, int col)
304 {
305    ELM_CHECK_WIDTYPE(obj, widtype);
306    Widget_Data *wd = elm_widget_data_get(obj);
307    if (!wd) return;
308    /*Row can be incomplete with atleast one color*/
309    if(((row-1)*col) > MAX_NUM_COLORS) return;
310    _color_table_update(obj, row, col, wd->num, wd->color);
311    _sizing_eval(obj);
312 }
313