Bundles / src /

view.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_defines.h"
#include "view.h"
#include "view/view_common.h"
#include "view/view_source.h"
#include "view/view_sink.h"

#define CHAR_BUFFER_SIZE 256

static struct view_info {
	Evas_Object *win;
	Evas_Object *conform;
	Evas_Object *scroller;
	Evas_Object *layout;
} s_info = {
	.win = NULL,
	.conform = NULL,
	.scroller = NULL,
	.layout = NULL,
};

static void _delete_win_request_cb(void *data, Evas_Object *obj, void *event_info);
static bool _create_main_view(void);
static void _switch_view_cb(void *data, Evas_Object *obj, const char *emission, const char *source);
static bool _create_scroller(void);
static void _back_button_clicked_cb(void *data, Evas_Object *obj, void *event_info);

/**
 * @brief Creates essential objects: window, conformant and layout.
 * @param[in] user_data User data.
 * @return EINA_TRUE on success or EINA_FALSE on error.
 */
Eina_Bool view_create(void *user_data)
{
	/* Create the window */
	s_info.win = view_create_win(PACKAGE);
	if (s_info.win == NULL) {
		dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a window.");
		return EINA_FALSE;
	}

	/* Create the conformant */
	s_info.conform = view_create_conformant(s_info.win);
	if (s_info.conform == NULL)
		return EINA_FALSE;

	if (!_create_scroller()) {
		dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] Function _create_scroller() failed", __FILE__, __LINE__);
		return EINA_FALSE;
	}

	if (!_create_main_view())
		return EINA_FALSE;

	if (!view_source_create(s_info.layout))
		return EINA_FALSE;

	if (!view_sink_create(s_info.layout))
		return EINA_FALSE;

	elm_layout_content_set(s_info.layout, PART_VIEW, view_source_get());

	evas_object_show(s_info.win);
	return EINA_TRUE;
}

/**
 * @brief Creates a basic window named package
 * @param[in] pkg_name Name of the window
 * @return The function returns window object if it was created successfully,
 * otherwise 'NULL' is returned.
 */
Evas_Object *view_create_win(const char *pkg_name)
{
	Evas_Object *win = NULL;

	/*
	 * Window
	 * Create and initialize elm_win.
	 * elm_win is mandatory to manipulate the window.
	 */
	win = elm_win_util_standard_add(pkg_name, pkg_name);
	elm_win_conformant_set(win, EINA_TRUE);
	elm_win_indicator_mode_set(win, ELM_WIN_INDICATOR_SHOW);
	elm_win_indicator_opacity_set(win, ELM_WIN_INDICATOR_OPAQUE);
	elm_win_autodel_set(win, EINA_TRUE);

	evas_object_smart_callback_add(win, "delete,request", _delete_win_request_cb, NULL);
	eext_object_event_callback_add(win, EEXT_CALLBACK_BACK, _back_button_clicked_cb, NULL);


	return win;
}

/**
 * @brief Creates a conformant object for parent object.
 * @param[in] parent The parent object for conformant object.
 * @return The function returns conformant object if it was created successfully,
 * otherwise 'NULL' is returned.
 */
Evas_Object *view_create_conformant(Evas_Object *parent)
{
	Evas_Object *conform = NULL;

	if (!parent) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Wrong input arguments.");
		return NULL;
	}

	conform = elm_conformant_add(parent);
	if (!conform) {
		dlog_print(DLOG_ERROR, LOG_TAG, "Function elm_conformant_add() failed.");
		return NULL;
	}

	evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
	elm_win_resize_object_add(parent, conform);
	elm_object_signal_emit(conform, "elm,state,indicator,overlap", "elm");
	evas_object_show(conform);

	return conform;
}

/**
 * @brief Internal function that creates a scroller and ads it to the conformant.
 * @return true on success or false on fail.
 */
static bool _create_scroller(void)
{
	s_info.scroller = elm_scroller_add(s_info.conform);
	if (!s_info.scroller) {
		dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.scroller == NULL", __FILE__, __LINE__);
		return false;
	}

	elm_scroller_bounce_set(s_info.scroller, EINA_FALSE, EINA_TRUE);
	elm_scroller_policy_set(s_info.scroller, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
	elm_scroller_movement_block_set(s_info.scroller, ELM_SCROLLER_MOVEMENT_BLOCK_VERTICAL);

	elm_object_content_set(s_info.conform, s_info.scroller);
	return true;
}

/**
 * @brief Internal function that creates the main view layout.
 * @return true on success or false on fail.
 */
static bool _create_main_view(void)
{
	s_info.layout = view_create_layout(s_info.conform, EDJ_MAIN_FILE_NAME, GROUP_MAIN);
	if (!s_info.layout) {
		dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] s_info.layout == NULL", __FILE__, __LINE__);
		return false;
	}

	elm_layout_signal_callback_add(s_info.layout, SIGNAL_SWITCH_SOURCE_VIEW, "", _switch_view_cb, (void *)false);
	elm_layout_signal_callback_add(s_info.layout, SIGNAL_SWITCH_SINK_VIEW, "", _switch_view_cb, (void *)true);
	evas_object_size_hint_weight_set(s_info.layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);

	elm_object_content_set(s_info.scroller, s_info.layout);
	return true;
}

/**
 * @brief Destroys window and frees its resources.
 */
void view_destroy(void)
{
	if (s_info.win == NULL)
		return;

	view_source_finalize();
	evas_object_del(s_info.win);
}

/**
 * @brief Internal callback function invoked when the main window needs to be destroyed.
 * @param[in] data The user data passed to the evas_object_smart_callback_add() function.
 * @param[in] obj The object invoking this callback function.
 * @param[in] event_info The structure containing the information on this event.
 */
static void _delete_win_request_cb(void *data, Evas_Object *obj, void *event_info)
{
	ui_app_exit();
}

/**
 * @brief Internal callback function invoked when the user clicks on one of the top buttons. It is used to switch the displayed view.
 * @param[in] data The user data (true - switch to sink view, false switch to source view).
 * @param[in] obj The main layout.
 * @param[in] emission The emitted signal.
 * @param[in] source The signal's source.
 */
static void _switch_view_cb(void *data, Evas_Object *obj, const char *emission, const char *source)
{
	bool to_sink = (bool)data;

	Evas_Object *content = elm_layout_content_get(s_info.layout, PART_VIEW);
	Evas_Object *switch_to = NULL;

	if (content) {
		elm_layout_content_unset(s_info.layout, PART_VIEW);
		evas_object_hide(content);
	}

	if (to_sink)
		switch_to = view_sink_get();
	else
		switch_to = view_source_get();

	elm_layout_content_set(s_info.layout, PART_VIEW, switch_to);
}

/**
 * @brief Internal callback function invoked when the back button is pressed. It is used to minimalize the application's window.
 * @param[in] data User data
 * @param[in] obj The window object.
 * @param[in] event_info Event information.
 */
static void _back_button_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
	elm_win_lower(s_info.win);
}