2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 #include <app_control.h>
19 #include <Elementary.h>
22 #include "attach_panel.h"
23 #include "attach_panel_internal.h"
24 #include "attach_bundle.h"
26 #include "content_list.h"
33 static const char *const FILE_LAYOUT_EDJ = EDJEDIR"/layout.edj";
34 static const char *const PRIVATE_DATA_KEY_GRID_LIST = "p_g_lt";
35 static const char *const PRIVATE_DATA_KEY_GIC = "p_gic";
36 static const char *const PRIVATE_DATA_KEY_LIST_INDEX = "p_lt_ix";
37 static const char *const PRIVATE_DATA_KEY_ICON_WIDTH = "p_ic_w";
38 static const char *const PRIVATE_DATA_KEY_ICON_HEIGHT = "p_ic_h";
39 static const char *const PRIVATE_DATA_KEY_ITEM_WIDTH = "p_it_w";
40 static const char *const PRIVATE_DATA_KEY_ITEM_HEIGHT = "p_it_h";
41 static const char *const PRIVATE_DATA_KEY_ANIMATOR = "p_tm";
42 static const char *const DEFAULT_ICON = "/usr/share/icons/A01-1_icon_Menu.png";
46 Eina_Bool _grid_can_flick(attach_panel_h attach_panel)
48 content_s *current_content_info = NULL;
49 int content_h, grid_h;
51 if (attach_panel->rotate) {
52 if (ATTACH_PANEL_STATE_FULL != attach_panel->attach_panel_land_state) {
53 _D("panel is not full state(land mode)");
57 if (ATTACH_PANEL_STATE_FULL != attach_panel->attach_panel_port_state) {
58 _D("panel is not full state(port mode)");
59 evas_object_data_set(attach_panel->grid, DATA_KEY_EDGE_TOP, (void *) 1);
64 current_content_info = eina_list_nth(attach_panel->content_list, attach_panel->cur_page_no);
65 retv_if(!current_content_info, EINA_TRUE);
67 if (attach_panel->grid != current_content_info->content) {
68 _D("current page is ug page");
72 elm_scroller_child_size_get(attach_panel->grid, NULL, &content_h);
73 evas_object_geometry_get(attach_panel->grid, NULL, NULL, NULL, &grid_h);
75 if (content_h < grid_h) {
76 _D("scrolling is not exist(grid size : %d, content size : %d", grid_h, content_h);
80 if (!evas_object_data_del(attach_panel->grid, DATA_KEY_EDGE_TOP)) {
81 _D("grid can not reach the edge top");
90 static char *__text_get(void *data, Evas_Object *obj, const char *part)
92 content_s *info = data;
93 innate_content_s *innate_content_info = NULL;
97 innate_content_info = info->innate_content_info;
98 retv_if(!innate_content_info, NULL);
99 if (!strcmp(part, "elm.text")) {
100 buf = elm_entry_utf8_to_markup(D_(innate_content_info->name));
109 static Evas_Object *__add_icon(Evas_Object *parent, const char *file)
111 const char *real_icon_file = NULL;
112 Evas_Object *icon = NULL;
113 Evas_Object *icon_layout = NULL;
116 real_icon_file = file;
117 if (access(real_icon_file, R_OK) != 0) {
118 _E("Failed to access an icon(%s)", real_icon_file);
119 real_icon_file = DEFAULT_ICON;
122 icon = elm_icon_add(parent);
123 retv_if(!icon, NULL);
125 if (elm_image_file_set(icon, real_icon_file, NULL) == EINA_FALSE) {
126 _E("Icon file is not accessible (%s)", real_icon_file);
127 evas_object_del(icon);
131 w = (int) evas_object_data_get(parent, PRIVATE_DATA_KEY_ICON_WIDTH);
132 h = (int) evas_object_data_get(parent, PRIVATE_DATA_KEY_ICON_HEIGHT);
133 evas_object_size_hint_min_set(icon, w, h);
135 elm_image_preload_disabled_set(icon, EINA_TRUE);
136 elm_image_smooth_set(icon, EINA_TRUE);
137 elm_image_no_scale_set(icon, EINA_FALSE);
138 evas_object_show(icon);
140 icon_layout = elm_layout_add(parent);
141 retv_if(!icon_layout, NULL);
143 elm_layout_file_set(icon_layout, FILE_LAYOUT_EDJ, "grid,icon");
144 evas_object_size_hint_weight_set(icon_layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
145 evas_object_size_hint_align_set(icon_layout, EVAS_HINT_FILL, EVAS_HINT_FILL);
146 evas_object_show(icon_layout);
148 elm_object_part_content_set(icon_layout, "icon", icon);
155 static Evas_Object *__content_get(void *data, Evas_Object *obj, const char *part)
157 content_s *info = data;
158 innate_content_s *innate_content_info = NULL;
160 retv_if(!info, NULL);
161 innate_content_info = info->innate_content_info;
162 retv_if(!innate_content_info, NULL);
164 if (!strcmp(part, "elm.swallow.end")) {
165 Evas_Object *bg = evas_object_rectangle_add(evas_object_evas_get(obj));
169 w = (int) evas_object_data_get(obj, PRIVATE_DATA_KEY_ITEM_WIDTH);
170 h = (int) evas_object_data_get(obj, PRIVATE_DATA_KEY_ITEM_HEIGHT);
172 evas_object_size_hint_min_set(bg, w, h);
173 evas_object_color_set(bg, 0, 0, 0, 0);
174 evas_object_show(bg);
176 } else if (!strcmp(part, "elm.swallow.icon")) {
177 retv_if(!innate_content_info->icon, NULL);
178 return __add_icon(obj, innate_content_info->icon);
179 } else if (!strcmp(part, "selected")) {
187 static void __del(void *data, Evas_Object *obj)
189 ret_if(NULL == data);
194 static void __reply_cb(app_control_h request, app_control_h reply, app_control_result_e result, void *user_data)
196 content_s *content_info = user_data;
197 char **select = NULL;
200 int ret = APP_CONTROL_ERROR_NONE;
202 ret_if(!content_info);
203 ret_if(!content_info->attach_panel);
205 /* This is just for protocol log */
206 _D("relay callback is called");
207 ret = app_control_get_extra_data_array(reply, "http://tizen.org/appcontrol/data/selected", &select, &length);
208 if (APP_CONTROL_ERROR_NONE == ret && select) {
209 for (i = 0; i < length; i++) {
210 _D("selected is %s[%d]", select[i], i);
214 ret = app_control_get_extra_data_array(reply, "http://tizen.org/appcontrol/data/path", &select, &length);
215 if (APP_CONTROL_ERROR_NONE == ret && select) {
216 for (i = 0; i < length; i++) {
217 _D("path is %s[%d]", select[i], i);
221 if (content_info->attach_panel->result_cb) {
222 content_info->attach_panel->result_cb(content_info->attach_panel
223 , content_info->innate_content_info->content_category
226 , content_info->attach_panel->result_data);
228 if (ATTACH_PANEL_STATE_FULL == _gesture_get_state()) {
229 /* This is same with attach_panel_hide() */
230 _content_list_set_pause(content_info->attach_panel->content_list, ATTACH_PANEL_CONTENT_CATEGORY_UG);
231 _gesture_hide(content_info->attach_panel);
234 _D("content_info->attach_panel->result_cb is NULL");
240 static void __launch_app(content_s *content_info)
242 app_control_h app_control = NULL;
243 innate_content_s *innate_content_info = NULL;
244 char value[BUF_SIZE] = {0, };
247 ret_if(!content_info);
249 innate_content_info = content_info->innate_content_info;
250 ret_if(!innate_content_info);
252 ret = app_control_create(&app_control);
253 ret_if(APP_CONTROL_ERROR_NONE != ret);
255 if (content_info->innate_content_info->operation) {
256 ret = app_control_set_operation(app_control, content_info->innate_content_info->operation);
257 if (APP_CONTROL_ERROR_NONE != ret)
258 _E("Fail to set operation");
261 if (content_info->innate_content_info->mode) {
262 snprintf(value, sizeof(value), "%d", content_info->innate_content_info->mode);
263 ret = app_control_add_extra_data(app_control, "http://tizen.org/appcontrol/data/mode", value);
264 if (APP_CONTROL_ERROR_NONE != ret)
265 _E("Fail to add 'http://tizen.org/appcontrol/data/mode'");
268 if (content_info->innate_content_info->type) {
269 ret = app_control_add_extra_data(app_control, "http://tizen.org/appcontrol/data/type", content_info->innate_content_info->type);
270 if (APP_CONTROL_ERROR_NONE != ret)
271 _E("Fail to add 'http://tizen.org/appcontrol/data/type'");
274 if (content_info->innate_content_info->item_type) {
275 ret = app_control_add_extra_data(app_control, "http://tizen.org/appcontrol/data/item_type", content_info->innate_content_info->item_type);
276 if (APP_CONTROL_ERROR_NONE != ret)
277 _E("Fail to add 'http://tizen.org/appcontrol/data/item_type'");
280 if (content_info->innate_content_info->selection_mode) {
281 ret = app_control_add_extra_data(app_control, APP_CONTROL_DATA_SELECTION_MODE, content_info->innate_content_info->selection_mode);
282 if (APP_CONTROL_ERROR_NONE != ret)
283 _E("Fail to add APP_CONTROL_DATA_SELECTION_MODE");
286 if (content_info->innate_content_info->mime) {
287 ret = app_control_set_mime(app_control, content_info->innate_content_info->mime);
288 if (APP_CONTROL_ERROR_NONE != ret)
289 _E("Fail to set mime");
292 if (content_info->innate_content_info->max) {
293 snprintf(value, sizeof(value), "%d", content_info->innate_content_info->max);
294 ret = app_control_add_extra_data(app_control, "http://tizen.org/appcontrol/data/max", value);
295 if (APP_CONTROL_ERROR_NONE != ret)
296 _E("Fail to add 'http://tizen.org/appcontrol/data/max'");
299 if (content_info->extra_data) {
300 _D("app control add the extra data for app");
301 _bundle_add_to_app_control(content_info->extra_data, app_control);
304 ret = app_control_add_extra_data(app_control, AUL_SVC_K_RUA_STAT_CALLER, "attach-panel");
305 if (APP_CONTROL_ERROR_NONE != ret)
306 _E("Fail to add 'AUL_SVC_K_RUA_STAT_CALLER'");
308 ret = app_control_add_extra_data(app_control, AUL_SVC_K_RUA_STAT_TAG, content_info->innate_content_info->appid);
309 if (APP_CONTROL_ERROR_NONE != ret)
310 _E("Fail to add 'AUL_SVC_K_RUA_STAT_TAG'");
312 ret = app_control_add_extra_data(app_control, "__CALLER_PANEL__", "attach-panel");
313 if (APP_CONTROL_ERROR_NONE != ret)
314 _E("Fail to add '__CALLER_PANEL__'");
316 ret = app_control_set_launch_mode(app_control, APP_CONTROL_LAUNCH_MODE_GROUP);
317 if (APP_CONTROL_ERROR_NONE != ret)
318 _E("Fail to set launch mode");
320 ret = app_control_send_launch_request(app_control, __reply_cb, content_info);
321 if (APP_CONTROL_ERROR_NONE != ret)
322 _E("Fail to send launch request");
324 app_control_destroy(app_control);
329 static void __item_selected(void *data, Evas_Object *obj, void *event_info)
331 content_s *info = data;
332 innate_content_s *innate_content_info = NULL;
333 Elm_Object_Item *selected_item = NULL;
336 innate_content_info = info->innate_content_info;
337 ret_if(!innate_content_info);
339 selected_item = elm_gengrid_selected_item_get(obj);
340 ret_if(!selected_item);
341 elm_gengrid_item_selected_set(selected_item, EINA_FALSE);
343 _D("Selected an item[%s]", innate_content_info->operation);
350 Eina_Bool __animator_cb(void *data)
352 Evas_Object *grid = data;
353 Elm_Gengrid_Item_Class *gic = NULL;
354 Eina_List *list = NULL;
355 content_s *info = NULL;
360 retv_if(!grid, ECORE_CALLBACK_CANCEL);
362 list = evas_object_data_get(grid, PRIVATE_DATA_KEY_GRID_LIST);
363 retv_if(!list, ECORE_CALLBACK_CANCEL);
365 gic = evas_object_data_get(grid, PRIVATE_DATA_KEY_GIC);
366 retv_if(!gic, ECORE_CALLBACK_CANCEL);
368 index = (int) evas_object_data_get(grid, PRIVATE_DATA_KEY_LIST_INDEX);
370 count = eina_list_count(list);
371 if (index == count) goto OUT;
372 info = eina_list_nth(list, index);
373 if (info && info->innate_content_info) {
374 if (!info->innate_content_info->is_ug) {
375 elm_gengrid_item_append(grid, gic, info, __item_selected, info);
379 if (index == count) goto OUT;
380 evas_object_data_set(grid, PRIVATE_DATA_KEY_LIST_INDEX, (void *) index);
382 return ECORE_CALLBACK_RENEW;
385 _D("Loading apps is done");
387 Elm_Object_Item *first_it = elm_gengrid_first_item_get(grid);
389 elm_gengrid_item_bring_in(first_it, ELM_GENGRID_ITEM_SCROLLTO_TOP);
391 evas_object_data_del(grid, PRIVATE_DATA_KEY_LIST_INDEX);
392 evas_object_data_del(grid, PRIVATE_DATA_KEY_ANIMATOR);
394 return ECORE_CALLBACK_CANCEL;
399 void _grid_refresh(Evas_Object *grid)
401 Ecore_Animator *anim = NULL;
405 elm_gengrid_clear(grid);
407 anim = evas_object_data_del(grid, PRIVATE_DATA_KEY_ANIMATOR);
409 ecore_animator_del(anim);
411 anim = ecore_animator_add(__animator_cb, grid);
414 evas_object_data_set(grid, PRIVATE_DATA_KEY_ANIMATOR, anim);
419 static void __edge_top_cb(void *data, Evas_Object *grid, void *event_info)
422 _D("grid reach the edge top");
423 evas_object_data_set(grid, DATA_KEY_EDGE_TOP, (void *) 1);
428 static void __scroll_cb(void *data, Evas_Object *grid, void *event_info)
431 evas_object_data_del(grid, DATA_KEY_EDGE_TOP);
436 static void __lang_changed_cb(void *data, Evas_Object *grid, void *event_info)
439 elm_gengrid_realized_items_update(grid);
444 Evas_Object *_grid_create(Evas_Object *page, attach_panel_h attach_panel)
446 Evas_Object *grid = NULL;
447 Elm_Gengrid_Item_Class *gic = NULL;
449 int item_w = 0, item_h = 0, icon_size = 0;
452 retv_if(!attach_panel, NULL);
454 grid = elm_gengrid_add(page);
455 goto_if(!grid, ERROR);
457 evas_object_size_hint_weight_set(grid, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
458 evas_object_size_hint_align_set(grid, EVAS_HINT_FILL, EVAS_HINT_FILL);
460 evas_object_geometry_get(attach_panel->conformant, NULL, NULL, &w, &h);
463 item_w = w / GRID_ROW_COUNT;
465 item_w = h / GRID_ROW_COUNT;
467 item_h = item_w * GRID_ITEM_HEIGHT_REL;
468 icon_size = item_h * GRID_ICON_SIZE_REL;
469 _D("item_size : %d, %d, icon_size : %d", item_w, item_h, icon_size);
471 evas_object_data_set(grid, PRIVATE_DATA_KEY_ITEM_WIDTH, (void *) item_w);
472 evas_object_data_set(grid, PRIVATE_DATA_KEY_ITEM_HEIGHT, (void *) item_h);
473 evas_object_data_set(grid, PRIVATE_DATA_KEY_ICON_WIDTH, (void *) icon_size);
474 evas_object_data_set(grid, PRIVATE_DATA_KEY_ICON_HEIGHT, (void *) icon_size);
476 elm_gengrid_item_size_set(grid, item_w, item_h);
477 elm_gengrid_align_set(grid, 0.0, 0.0);
478 elm_gengrid_horizontal_set(grid, EINA_FALSE);
479 elm_gengrid_multi_select_set(grid, EINA_FALSE);
480 elm_object_style_set(grid, "popup");
482 gic = elm_gengrid_item_class_new();
483 goto_if(!gic, ERROR);
484 gic->func.text_get = __text_get;
485 gic->func.content_get = __content_get;
486 gic->func.state_get = NULL;
487 gic->func.del = __del;
488 gic->item_style = "default";
490 evas_object_data_set(grid, PRIVATE_DATA_KEY_GRID_LIST, attach_panel->content_list);
491 evas_object_data_set(grid, PRIVATE_DATA_KEY_GIC, gic);
492 evas_object_data_set(grid, PRIVATE_DATA_KEY_LIST_INDEX, NULL);
493 evas_object_data_set(grid, DATA_KEY_EDGE_TOP, (void *)1);
494 evas_object_smart_callback_add(grid, "edge,top", __edge_top_cb, NULL);
495 evas_object_smart_callback_add(grid, "scroll", __scroll_cb, NULL);
496 evas_object_smart_callback_add(grid, "language,changed", __lang_changed_cb, NULL);
498 elm_scroller_movement_block_set(grid, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);
500 evas_object_show(grid);
511 void _grid_destroy(Evas_Object *grid)
515 Ecore_Animator *animator = NULL;
517 evas_object_data_del(grid, PRIVATE_DATA_KEY_GRID_LIST);
518 evas_object_data_del(grid, PRIVATE_DATA_KEY_LIST_INDEX);
519 evas_object_data_del(grid, PRIVATE_DATA_KEY_ICON_WIDTH);
520 evas_object_data_del(grid, PRIVATE_DATA_KEY_ICON_HEIGHT);
521 evas_object_data_del(grid, PRIVATE_DATA_KEY_ITEM_WIDTH);
522 evas_object_data_del(grid, PRIVATE_DATA_KEY_ITEM_HEIGHT);
523 evas_object_data_del(grid, DATA_KEY_EDGE_TOP);
525 evas_object_data_del(grid, PRIVATE_DATA_KEY_GIC);
527 animator = evas_object_data_del(grid, PRIVATE_DATA_KEY_ANIMATOR);
529 ecore_animator_del(animator);
533 evas_object_del(grid);
538 Elm_Object_Item *_grid_append_item(Evas_Object *grid, content_s *content_info)
540 Elm_Gengrid_Item_Class *gic = NULL;
541 Elm_Object_Item *item = NULL;
543 retv_if(!grid, NULL);
544 retv_if(!content_info, NULL);
546 gic = evas_object_data_get(grid, PRIVATE_DATA_KEY_GIC);
549 item = elm_gengrid_item_append(grid, gic, content_info, __item_selected, content_info);
550 retv_if(!item, NULL);
551 _D("grid append item : %s", content_info->innate_content_info->name);
552 content_info->grid_item = item;
559 void _grid_remove_item(Evas_Object *grid, content_s *content_info)
561 Elm_Object_Item *item = NULL;
564 ret_if(!content_info);
566 item = content_info->grid_item;
568 elm_object_item_del(item);
569 content_info->grid_item = NULL;
574 int _grid_count_item(Evas_Object *grid)
580 count = elm_gengrid_items_count(grid);