Bundles / src / view /
view_sink.c
/*
* Copyright (c) 2016 Samsung Electronics Co., Ltd
*
* Licensed under the Flora License, Version 1.1 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://floralicense.org/license/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <app.h>
#include <efl_extension.h>
#include "$(appName).h"
#include "view/view_common.h"
#include "view_defines.h"
#include "view/view_source.h"
#include "view/view_list.h"
#include "view/view_sink.h"
#define FORMAT(type) "%s: "type"<align=right><type>Type: %s</type></align=right>"
typedef struct {
char *val_1;
char *val_2;
bool state;
} list_data_t;
static struct view_info {
Evas_Object *layout;
Evas_Object *list;
Elm_Genlist_Item_Class *itc_title;
Elm_Genlist_Item_Class *itc_data;
Elm_Genlist_Item_Class *itc_header;
Elm_Genlist_Item_Class *itc_header_data;
Elm_Object_Item *title;
} s_info = {
.layout = NULL,
.list = NULL,
.itc_title = NULL,
.itc_data = NULL,
.itc_header = NULL,
.itc_header_data = NULL,
.title = NULL,
};
static bool _create_list(void);
static Evas_Object *_item_title_get_cb(void *data, Evas_Object *obj, const char *part);
static Evas_Object *_item_data_get_cb(void *data, Evas_Object *obj, const char *part);
static Evas_Object *_item_header_get_cb(void *data, Evas_Object *obj, const char *part);
static Evas_Object *_item_header_data_get_cb(void *data, Evas_Object *obj, const char *part);
static void _tree_item_expanded(void *data, Evas_Object *obj, void *event_info);
static void _item_delete_cb(void *data, Evas_Object *obj);
/**
* @brief Function used to create the sink view.
* @param[in] parent The parent widget
* @return true on success or false on error.
*/
bool view_sink_create(Evas_Object *parent)
{
s_info.layout = view_create_layout(parent, EDJ_SINK_FILE_NAME, GROUP_SINK);
if (!s_info.layout)
return false;
if (!_create_list())
return false;
return true;
}
/**
* @brief Returns the sink view's layout widget.
* @return The layout widget.
*/
Evas_Object *view_sink_get(void)
{
return s_info.layout;
}
/**
* @brief Callback function to be used by the data module. Invoked when a new message is received.
* @param[in] index The index of the new message.
*/
void view_sink_new_message_cb(int index)
{
dlog_print(DLOG_INFO, LOG_TAG, "[%s:%d] Message received. Index: %d", __FILE__, __LINE__, index);
s_info.title = view_list_add_item(s_info.list, s_info.itc_title, ELM_GENLIST_ITEM_TREE, NULL, (void*)index, false, ELM_OBJECT_SELECT_MODE_DEFAULT, NULL, NULL);
}
/**
* @brief Internal function that creates a list object.
* @return true on success or false on fail.
*/
static bool _create_list(void)
{
s_info.list = view_list_create(s_info.layout);
if (!s_info.list) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.list == NULL", __FILE__, __LINE__);
return false;
}
s_info.itc_title = view_list_add_itc(_item_title_get_cb, NULL);
if (!s_info.itc_title) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.itc == NULL", __FILE__, __LINE__);
return false;
}
s_info.itc_data = view_list_add_itc(_item_data_get_cb, _item_delete_cb);
if (!s_info.itc_data) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.itc_sub == NULL", __FILE__, __LINE__);
return false;
}
s_info.itc_header = view_list_add_itc(_item_header_get_cb, NULL);
if (!s_info.itc_header) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.itc_sub == NULL", __FILE__, __LINE__);
return false;
}
s_info.itc_header_data = view_list_add_itc(_item_header_data_get_cb, view_list_del_item_cb);
if (!s_info.itc_header_data) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.itc_tree == NULL", __FILE__, __LINE__);
return false;
}
view_list_add_tree_callbacks(s_info.list, s_info.itc_title, s_info.itc_data, _tree_item_expanded, view_common_tree_item_contracted_cb);
if (!elm_layout_content_set(s_info.layout, PART_LIST, s_info.list)) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] Failed to set entry as a swallow %s", __FILE__, __LINE__, PART_LIST);
return false;
}
return true;
}
/**
* @brief Internal callback function added to an genlist's item class. It is invoked when a title item is realized.
* @param[in] data The user data.
* @param[in] obj A genlist object.
* @param[in] part The part name.
* @return A new layout to be embedded by the genlist's item.
*/
static Evas_Object *_item_title_get_cb(void *data, Evas_Object *obj, const char *part)
{
char buf[NAME_MAX] = {0,};
int index = (int)data;
int count = data_get_count(index);
Evas_Object *item_layout = view_create_layout(obj, EDJ_SINK_FILE_NAME, GROUP_TITLE);
if (!item_layout) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] item_layout == NULL", __FILE__, __LINE__);
return NULL;
}
snprintf(buf, NAME_MAX, "Bundle items: %d", count);
elm_layout_text_set(item_layout, PART_ITEM, buf);
return item_layout;
}
/**
* @brief Internal callback function added to an genlist's item class. It is invoked when a data item (containing the key, value and type) is realized.
* @param[in] data The user data.
* @param[in] obj A genlist object.
* @param[in] part The part name.
* @return A new layout to be embedded by the genlist's item.
*/
static Evas_Object *_item_data_get_cb(void *data, Evas_Object *obj, const char *part)
{
list_data_t *list_data = (list_data_t *)data;
char buf[NAME_MAX] = {0,};
Evas_Object *item_layout = view_create_layout(obj, EDJ_SINK_FILE_NAME, GROUP_ITEM);
if (!item_layout) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] item_layout == NULL", __FILE__, __LINE__);
return NULL;
}
snprintf(buf, NAME_MAX, "Type: %s", list_data->val_2);
elm_layout_text_set(item_layout, PART_ITEM_KEY_VAL, list_data->val_1);
elm_layout_text_set(item_layout, PART_ITEM_TYPE, buf);
if (list_data->state)
elm_layout_signal_emit(item_layout, SIGNAL_BUBBLES_HIDE, "");
return item_layout;
}
/**
* @brief Internal callback function added to an genlist's item class. It is invoked when a header item is realized.
* @param[in] data The user data.
* @param[in] obj A genlist object.
* @param[in] part The part name.
* @return A new layout to be embedded by the genlist's item.
*/
static Evas_Object *_item_header_get_cb(void *data, Evas_Object *obj, const char *part)
{
Evas_Object *item_layout = view_create_layout(obj, EDJ_SINK_FILE_NAME, GROUP_HEADER);
if (!item_layout) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] item_layout == NULL", __FILE__, __LINE__);
return NULL;
}
return item_layout;
}
/**
* @brief Internal callback function added to an genlist's item class. It is invoked when a header data item is realized.
* @param[in] data The user data.
* @param[in] obj A genlist object.
* @param[in] part The part name.
* @return A new layout to be embedded by the genlist's item.
*/
static Evas_Object *_item_header_data_get_cb(void *data, Evas_Object *obj, const char *part)
{
char *text = (char *)data;
char buf[NAME_MAX] = {0,};
char **tokens = NULL;
Evas_Object *item_layout = view_create_layout(obj, EDJ_SINK_FILE_NAME, GROUP_HEADER_DATA);
if (!item_layout) {
dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] item_layout == NULL", __FILE__, __LINE__);
return NULL;
}
tokens = eina_str_split(text, "\2", 2);
elm_layout_text_set(item_layout, PART_ITEM_KEY_VAL, tokens[0]);
snprintf(buf, NAME_MAX, "Type: %s", tokens[1]);
elm_layout_text_set(item_layout, PART_ITEM_TYPE, buf);
return item_layout;
}
/**
* @brief Internal function that adds header and data items to the genlist.
* @param[in] index The index of a message to use.
* @param[in] parent The parent item.
*/
static void _add_data_items(int index, Elm_Object_Item *parent)
{
Eina_List* l;
char* key;
list_data_t *data = NULL;
Eina_List *keys = data_get_keys(index);
int byte_val;
char buf[NAME_MAX];
char *string_val;
bool state = !data_key_exists(index, BUNDLE_HEADER_KEY); /* If header exists the first item won't display the bubbles */
EINA_LIST_FOREACH(keys, l, key) {
if (string_equal(BUNDLE_HEADER_KEY, key)) {
view_list_add_item(s_info.list, s_info.itc_header, ELM_GENLIST_ITEM_TREE, parent, (void*) index, true, ELM_OBJECT_SELECT_MODE_DEFAULT, NULL, NULL);
continue;
} else if (string_equal(BUNDLE_HEADER_DATA_KEY, key)) {
continue;
} else if (data_is_byte(index, key)) {
byte_val = data_get_byte(index, key);
snprintf(buf, NAME_MAX, "%s: %d", key, byte_val);
} else {
string_val = data_get_string(index, key);
snprintf(buf, NAME_MAX, "%s: %s", key, string_val);
}
data = calloc(1, sizeof(list_data_t));
data->val_1 = strdup(buf);
data->val_2 = strdup(data_get_type_text(index, key));
data->state = state;
view_list_add_item(s_info.list, s_info.itc_data, ELM_GENLIST_ITEM_NONE, parent, (void*)data, false, ELM_OBJECT_SELECT_MODE_NONE, NULL, NULL);
state = false;
}
EINA_LIST_FREE(keys, key)
free(key);
}
/**
* @brief Internal function that adds header data items.
* @param[in] index The index of a message to use.
* @param[in] parent The parent item.
*/
static void _add_header_items(int index, Elm_Object_Item *parent)
{
int len = 0;
int i;
const char **keys = data_get_string_array(index, BUNDLE_HEADER_DATA_KEY, &len);
for (i = 0; i < len; i++)
view_list_add_item(s_info.list, s_info.itc_header_data, ELM_GENLIST_ITEM_NONE, parent, (void*)strdup(keys[i]), false, ELM_OBJECT_SELECT_MODE_NONE, NULL, NULL);
}
/**
* @brief Internal callback function invoked when a TREE item is expanded
* @param[in] data The use data.
* @param[in] obj The genlist.
* @param[in] event_info The expanded item.
*/
static void _tree_item_expanded(void *data, Evas_Object *obj, void *event_info)
{
Elm_Object_Item *parent = (Elm_Object_Item *)event_info;
int index = (int)elm_object_item_data_get(parent);
Evas_Object *header = elm_object_item_part_content_get(parent, "elm.swallow.content");
elm_layout_signal_emit(header, SIGNAL_ARROW_STATE_CHANGE, "");
if (elm_genlist_item_item_class_get(parent) == s_info.itc_title)
_add_data_items(index, parent);
else if (elm_genlist_item_item_class_get(parent) == s_info.itc_header)
_add_header_items(index, parent);
}
/**
* @brief Internal callback function invoked when a data item is removed.
* @param[in] data The user data.
* @param[in] obj The genlist.
*/
static void _item_delete_cb(void *data, Evas_Object *obj)
{
list_data_t *it_data = (list_data_t *)data;
if (!it_data)
return;
free(it_data->val_1);
free(it_data->val_2);
free(it_data);
}