diff options
author | gs86.lee <gs86.lee@samsung.com> | 2016-05-31 14:24:11 +0900 |
---|---|---|
committer | gs86.lee <gs86.lee@samsung.com> | 2016-06-07 11:13:26 +0900 |
commit | 662964eec9e77f0528818c5fdbb693cafb0751a1 (patch) | |
tree | 54fff8d79e0000db0b0a0dbbcb8c28b2eb17d329 | |
parent | 3dba2190f1453c9280b2197fb2c720a8ee107a32 (diff) | |
download | classic-watch-662964eec9e77f0528818c5fdbb693cafb0751a1.tar.gz classic-watch-662964eec9e77f0528818c5fdbb693cafb0751a1.tar.bz2 classic-watch-662964eec9e77f0528818c5fdbb693cafb0751a1.zip |
Merge tizen2.3.1 classic-watch(native sample application)submit/tizen_wearable/20160608.003954accepted/tizen/wearable/20160608.084606
Change-Id: Icc28ebb7ddda4149ce95ec3adfcc85f76a93b607
32 files changed, 2142 insertions, 0 deletions
@@ -0,0 +1 @@ +Geunsun Lee<gs86.lee@samsung.com> diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..acdaea8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,89 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(classic-watch C) + +SET(SRCS + src/main.c + src/view.c + src/data.c +) + +SET(VENDOR "tizen") +SET(PACKAGE ${PROJECT_NAME}) +SET(PKGNAME "org.${VENDOR}.${PACKAGE}") +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(BINDIR "${PREFIX}/bin") +SET(RESDIR "${PREFIX}/res") +SET(ICONDIR "${RESDIR}/icons") +SET(FONTDIR "${RESDIR}/font") +SET(DATADIR "/opt/usr/apps/org.${VENDOR}.${PACKAGE}/data") +SET(LOCALEDIR "${RESDIR}/locale") +SET(IMAGEDIR "${RESDIR}/images") +SET(EDJDIR "${RESDIR}/edje") +SET(SHAREDICONDIR "${PREFIX}/shared/res") + +IF("${ARCH}" STREQUAL "arm") + OPTION(USE_ARM "Use Arm" ON) + ADD_DEFINITIONS("-DARM_TYPE") +ELSEIF("${ARCH}" STREQUAL "emulator") + OPTION(USE_EMULATOR "Use Emulator" ON) + ADD_DEFINITIONS("-DEMULATOR_TYPE") +ENDIF() + +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "") +MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + capi-appfw-watch-application + capi-system-system-settings + appcore-efl + ecore + evas + edje + dlog + efl-extension + elementary +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +SET(CMAKE_C_FLAGS_RELEASE "-O2") + +FIND_PROGRAM(UNAME NAMES uname) +EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") + +ADD_DEFINITIONS("-DVENDOR=\"${VENDOR}\"") +ADD_DEFINITIONS("-DPACKAGE=\"${PACKAGE}\"") +ADD_DEFINITIONS("-DPACKAGE_NAME=\"${PKGNAME}\"") +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") +ADD_DEFINITIONS("-DRESDIR=\"${RESDIR}\"") +ADD_DEFINITIONS("-DDATADIR=\"${DATADIR}\"") +ADD_DEFINITIONS("-DLOCALEDIR=\"${LOCALEDIR}\"") +ADD_DEFINITIONS("-DICON_DIR=\"${ICONDIR}\"") +ADD_DEFINITIONS("-DIMAGEDIR=\"${IMAGEDIR}\"") +ADD_DEFINITIONS("-DEDJDIR=\"${EDJDIR}\"") + +#SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") +SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--as-needed") + +ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} -lm -pie) + +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${BINDIR}) + +# application xml +INSTALL(FILES ${CMAKE_BINARY_DIR}/${PKGNAME}.xml DESTINATION /usr/share/packages) + +INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PKGNAME}.png DESTINATION ${ICONDIR}) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/${PKGNAME}.png DESTINATION ${SHAREDICONDIR}) + +# res +ADD_SUBDIRECTORY(res) diff --git a/LICENSE.Flora b/LICENSE.Flora new file mode 100755 index 0000000..a05b01c --- /dev/null +++ b/LICENSE.Flora @@ -0,0 +1,83 @@ +Flora License + +Version 1.1, April, 2013 + +http://floralicense.org/license + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +"Tizen Certified Platform" shall mean a software platform that complies with the standards set forth in the Tizen Compliance Specification and passes the Tizen Compliance Tests as defined from time to time by the Tizen Technical Steering Group and certified by the Tizen Association or its designated agent. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work solely as incorporated into a Tizen Certified Platform, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work solely as incorporated into a Tizen Certified Platform to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof pursuant to the copyright license above, in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + +You must give any other recipients of the Work or Derivative Works a copy of this License; and +You must cause any modified files to carry prominent notices stating that You changed the files; and +You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and +If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License and your own copyright statement or terms and conditions do not conflict the conditions stated in this License including section 3. +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Flora License to your work + +To apply the Flora License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + + + 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. @@ -0,0 +1 @@ +Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. diff --git a/include/classic-watch.h b/include/classic-watch.h new file mode 100644 index 0000000..e5eda98 --- /dev/null +++ b/include/classic-watch.h @@ -0,0 +1,60 @@ +/* + * 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. + */ + +#if !defined(_CLASSIC_WATCH_H) +#define _CLASSIC_WATCH_H + +#if !defined(PACKAGE) +#define PACKAGE "org.tizen.classic-watch" +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "CLASSIC_WATCH" + +/* Angle */ +#define HOUR_ANGLE 30 +#define MIN_ANGLE 6 +#define SEC_ANGLE 6 +#define MONTH_ANGLE 30 +#define WEEKDAY_ANGLE 51 + +/* Layout */ +#define BASE_WIDTH 360 +#define BASE_HEIGHT 360 + +#define MODULE_MOONPHASE_SIZE 240 +#define MODULE_DAY_NUM_SIZE 52 +#define MODULE_DAY_NUM_RIGHT_PADDING 22 +#define MODULE_MONTH_SIZE 128 +#define MODULE_WEEKDAY_SIZE MODULE_MONTH_SIZE + +#define HANDS_SEC_WIDTH 30 +#define HANDS_SEC_HEIGHT 360 +#define HANDS_MIN_WIDTH 30 +#define HANDS_MIN_HEIGHT 360 +#define HANDS_HOUR_WIDTH 30 +#define HANDS_HOUR_HEIGHT 360 +#define HANDS_MODULE_CALENDAR_WIDTH 20 +#define HANDS_MODULE_CALENDAR_HEIGHT 128 + +#define HANDS_SEC_SHADOW_PADDING 9 +#define HANDS_MIN_SHADOW_PADDING 4 +#define HANDS_HOUR_SHADOW_PADDING 4 +#define HANDS_MODULE_CALENDAR_PADDING 4 + +#endif diff --git a/include/data.h b/include/data.h new file mode 100644 index 0000000..e3f3963 --- /dev/null +++ b/include/data.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +#if !defined(_DATA_H) +#define _DATA_H + +typedef enum { + PARTS_TYPE_HANDS_SEC = 0, + PARTS_TYPE_HANDS_MIN = 1, + PARTS_TYPE_HANDS_HOUR = 2, + PARTS_TYPE_HANDS_MODULE_MONTH = 3, + PARTS_TYPE_HANDS_MODULE_WEEKDAY = 4, + PARTS_TYPE_HANDS_SEC_SHADOW = 5, + PARTS_TYPE_HANDS_MIN_SHADOW = 6, + PARTS_TYPE_HANDS_HOUR_SHADOW = 7, + PARTS_TYPE_HANDS_MODULE_MONTH_SHADOW = 8, + PARTS_TYPE_HANDS_MODULE_WEEKDAY_SHADOW = 9, + PARTS_TYPE_MAX, +} parts_type_e; + +/* + * Initialize the data component + */ +void data_initialize(void); + +/* + * Finalize the data component + */ +void data_finalize(void); + +void data_get_resource_path(const char *file_in, char *file_path_out, int file_path_max); +int data_get_plus_angle(int minute); +char *data_get_parts_image_path(parts_type_e type); +void data_get_parts_position(parts_type_e type, int *x, int *y); +int data_get_parts_width_size(parts_type_e type); +int data_get_parts_height_size(parts_type_e type); + +int data_get_juliandate(int day, int month, int year); +float data_get_moonphase(int day, int month, int year); + +#endif diff --git a/include/view.h b/include/view.h new file mode 100644 index 0000000..a7ad944 --- /dev/null +++ b/include/view.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#if !defined(_VIEW_H) +#define _VIEW_H + +#define EDJ_FILE "edje/classic-watch.edj" + +void view_set_module_moonphase_layout(Evas_Object *layout); +void view_set_module_day_layout(Evas_Object *layout); +void view_set_module_month_layout(Evas_Object *layout); +void view_set_module_weekday_layout(Evas_Object *layout); +Evas_Object *view_get_bg(void); +Evas_Object *view_get_module_day_layout(void); +Evas_Object *view_get_module_month_layout(void); +Evas_Object *view_get_module_weekday_layout(void); +Evas_Object *view_get_module_moonphase_layout(void); + +/* + * Create a view + */ +void view_set_text(Evas_Object *parent, const char *part_name, const char *text); +void view_rotate_hand(Evas_Object *hand, double degree, Evas_Coord cx, Evas_Coord cy); +void view_rotate_moonphase(float degree); +Evas_Object *view_create_layout(Evas_Object *parent, const char *file_path, const char *group_name, void *user_data); +Evas_Object *view_create_bg(Evas_Object *win, const char *image_path, int width, int height); +void view_set_module_property(Evas_Object *layout, int x, int y, int w, int h); +Evas_Object *view_create_module_layout(Evas_Object *parent, const char *file_path, const char *group_name); +void view_set_opacity_to_parts(Evas_Object *parts); +Evas_Object *view_create_parts(Evas_Object *parent, const char *image_path, int x, int y, int w, int h); + +void view_create_base_gui(int width, int height); +void view_destroy_base_gui(void); + +#endif diff --git a/org.tizen.classic-watch.manifest b/org.tizen.classic-watch.manifest new file mode 100755 index 0000000..97e8c31 --- /dev/null +++ b/org.tizen.classic-watch.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_"/> + </request> +</manifest> diff --git a/org.tizen.classic-watch.png b/org.tizen.classic-watch.png Binary files differnew file mode 100755 index 0000000..ec29946 --- /dev/null +++ b/org.tizen.classic-watch.png diff --git a/org.tizen.classic-watch.xml b/org.tizen.classic-watch.xml new file mode 100755 index 0000000..f6af384 --- /dev/null +++ b/org.tizen.classic-watch.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns="http://tizen.org/ns/packages" package="org.tizen.classic-watch" version="0.0.1" install-location="internal-only" api-version="2.3.1"> + <profile name="wearable" /> + <watch-application appid="org.tizen.classic-watch" exec="/usr/apps/org.tizen.classic-watch/bin/classic-watch" ambient-support="true"> + <category name="org.tizen.wmanager.WATCH_CLOCK"></category> + <metadata key="clocktype" value="function"></metadata> + <label>Classic watch</label> + <icon>org.tizen.classic-watch.png</icon> + </watch-application> +</manifest> diff --git a/packaging/org.tizen.classic-watch.spec b/packaging/org.tizen.classic-watch.spec new file mode 100644 index 0000000..c5ee36f --- /dev/null +++ b/packaging/org.tizen.classic-watch.spec @@ -0,0 +1,79 @@ +Name: org.tizen.classic-watch +Summary: classic-watch application (EFL) +Version: 0.0.1 +Release: 0 +Group: Applications/Wearable App +License: Flora-1.1 +Source0: %{name}-%{version}.tar.gz +BuildRequires: pkgconfig(appcore-efl) +BuildRequires: pkgconfig(capi-appfw-watch-application) +BuildRequires: pkgconfig(capi-system-system-settings) +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(elementary) +BuildRequires: pkgconfig(efl-extension) + +BuildRequires: cmake +BuildRequires: edje-bin +BuildRequires: embryo-bin +BuildRequires: gettext-devel +BuildRequires: hash-signer + +%ifarch %{arm} +%define ARCH arm +%else +%define ARCH emulator +%endif + +%description +classic-watch. + +%prep +%setup -q + +%define PREFIX /usr/apps/org.tizen.classic-watch +%define DATADIR /usr/apps/%{name}/data + +%build +%if 0%{?tizen_build_binary_release_type_eng} +export CFLAGS="$CFLAGS -DTIZEN_ENGINEER_MODE" +export CXXFLAGS="$CXXFLAGS -DTIZEN_ENGINEER_MODE" +export FFLAGS="$FFLAGS -DTIZEN_ENGINEER_MODE" +%endif + +RPM_OPT=`echo $CFLAGS|sed 's/-Wp,-D_FORTIFY_SOURCE=2//'` +export CFLAGS=$RPM_OPT + +cmake -DCMAKE_INSTALL_PREFIX="%{PREFIX}" -DARCH="%{ARCH}" \ + -DENABLE_DIGITAL_OPERATOR_GEAR3=YES \ + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +%post +GOPTION="-g 5000 -f" +SOPTION="-s litewhome" + +INHOUSE_ID="5000" +make_data_directory() +{ + I="%{DATADIR}" + if [ ! -d $I ]; then + mkdir -p $I + fi + chmod 775 $I + chown :$INHOUSE_ID $I +} +make_data_directory + +%files +%manifest org.tizen.classic-watch.manifest +%defattr(-,root,root,-) +%{PREFIX}/* +%{PREFIX}/bin/* +%{PREFIX}/res/* +/usr/share/packages/org.tizen.classic-watch.xml +/usr/apps/org.tizen.classic-watch/shared/res/org.tizen.classic-watch.png + diff --git a/res/CMakeLists.txt b/res/CMakeLists.txt new file mode 100755 index 0000000..c518bd8 --- /dev/null +++ b/res/CMakeLists.txt @@ -0,0 +1,13 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +# install edj +ADD_CUSTOM_TARGET(classic-watch.edj + COMMAND edje_cc -id ${CMAKE_CURRENT_SOURCE_DIR}/edje/images + ${CMAKE_CURRENT_SOURCE_DIR}/edje/classic-watch.edc classic-watch.edj + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/edje/classic-watch.edc +) +ADD_DEPENDENCIES(${PROJECT_NAME} classic-watch.edj) +INSTALL(FILES classic-watch.edj DESTINATION ${EDJDIR}) + +# install images +INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/images/ DESTINATION ${IMAGEDIR} FILES_MATCHING PATTERN "*.png") diff --git a/res/edje/classic-watch.edc b/res/edje/classic-watch.edc new file mode 100644 index 0000000..4d7945a --- /dev/null +++ b/res/edje/classic-watch.edc @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + */ + +collections { + group { name: "layout_module_day"; + images { + image: "lux_3_day_num_bg.png" COMP; + } + parts { + part { name: "img.bg"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.0 0.0; } + rel2 { relative: 1.0 1.0; } + min: 52 52; + max: 52 52; + image { normal: "lux_3_day_num_bg.png"; } + } + } + part { name: "txt.day.num"; + type: TEXT; + description { state: "default" 0.0; + rel1 { relative: 0.5 0.5; to: "img.bg"; } + rel2 { relative: 0.5 0.5; to: "img.bg"; } + align: 0.5 0.5; + color: 51 51 51 255; + text { + font: "Tizen:style=Regular"; + size: 24; + min: 1 1; + ellipsis: -1; + text: "7"; + } + } + } + } //parts end + } //group end + group { name: "layout_module_month"; + images { + image: "lux_3_calendar_module_month.png" COMP; + } + parts { + part { name: "img.bg"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.0 0.0; } + rel2 { relative: 1.0 1.0; } + min: 128 128; + max: 128 128; + image { normal: "lux_3_calendar_module_month.png"; } + } + } + } //parts end + } //group end + group { name: "layout_module_weekday"; + images { + image: "lux_3_calendar_module_day.png" COMP; + } + parts { + part { name: "img.bg"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.0 0.0; } + rel2 { relative: 1.0 1.0; } + min: 128 128; + max: 128 128; + image { normal: "lux_3_calendar_module_day.png"; } + } + } + } //parts end + } //group end + group { name: "layout_module_moonphase"; + images { + image: "lux_3_module_calendar_phase_cover_01.png" COMP; + image: "lux_3_module_calendar_phase_nightsky.png" COMP; + image: "lux_3_module_calendar_phase_nightsky_02.png" COMP; + image: "lux_3_module_calendar_phase_windowframe.png" COMP; + } + parts { + part { name: "bg.center"; + type: SPACER; + description { state: "default" 0.0; + rel1 { relative: 0.5 0.5; } + rel2 { relative: 0.5 0.5; } + } + } + part { name: "img.nightsky"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.0 0.0; } + rel2 { relative: 1.0 1.0; } + min: 240 240; + max: 240 240; + image { normal: "lux_3_module_calendar_phase_nightsky.png"; } + } + } + part { name: "img.nightsky_02"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.5 0.5; to: "img.nightsky"; } + rel2 { relative: 0.5 0.5; to: "img.nightsky"; } + align: 0.5 0.5; + min: 240 240; + max: 240 240; + image { normal: "lux_3_module_calendar_phase_nightsky_02.png"; } + map { + on: 1; + rotation { + x: 0.0; + y: 0.0; + z: 0.0; + } + } + } + } + part { name: "img.cover"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.0 0.0; } + rel2 { relative: 1.0 1.0; } + min: 240 240; + max: 240 240; + image { normal: "lux_3_module_calendar_phase_cover_01.png"; } + } + } + part { name: "img.windowframe"; + type: IMAGE; + description { state: "default" 0.0; + rel1 { relative: 0.0 0.0; } + rel2 { relative: 1.0 1.0; } + min: 240 240; + max: 240 240; + image { normal: "lux_3_module_calendar_phase_windowframe.png"; } + } + } + } //parts end + programs { + script { + public message(Msg_Type:type, id, ...) { + if ((type == MSG_FLOAT) && (id == 1)) { + new Float:angle = getfarg(2); + custom_state(PART:"img.nightsky_02", "default", 0.0); + set_state_val(PART:"img.nightsky_02", STATE_MAP_ROT_Z, angle); + set_state(PART:"img.nightsky_02", "custom", 0.0); + } + } + } + } //programs end + } //group end +} //collections end diff --git a/res/edje/images/lux_3_calendar_module_day.png b/res/edje/images/lux_3_calendar_module_day.png Binary files differnew file mode 100644 index 0000000..9b4b7e9 --- /dev/null +++ b/res/edje/images/lux_3_calendar_module_day.png diff --git a/res/edje/images/lux_3_calendar_module_month.png b/res/edje/images/lux_3_calendar_module_month.png Binary files differnew file mode 100644 index 0000000..628162a --- /dev/null +++ b/res/edje/images/lux_3_calendar_module_month.png diff --git a/res/edje/images/lux_3_day_num_bg.png b/res/edje/images/lux_3_day_num_bg.png Binary files differnew file mode 100644 index 0000000..a9e9482 --- /dev/null +++ b/res/edje/images/lux_3_day_num_bg.png diff --git a/res/edje/images/lux_3_module_calendar_phase_cover_01.png b/res/edje/images/lux_3_module_calendar_phase_cover_01.png Binary files differnew file mode 100644 index 0000000..20e1cde --- /dev/null +++ b/res/edje/images/lux_3_module_calendar_phase_cover_01.png diff --git a/res/edje/images/lux_3_module_calendar_phase_nightsky.png b/res/edje/images/lux_3_module_calendar_phase_nightsky.png Binary files differnew file mode 100644 index 0000000..c22a199 --- /dev/null +++ b/res/edje/images/lux_3_module_calendar_phase_nightsky.png diff --git a/res/edje/images/lux_3_module_calendar_phase_nightsky_02.png b/res/edje/images/lux_3_module_calendar_phase_nightsky_02.png Binary files differnew file mode 100644 index 0000000..4555637 --- /dev/null +++ b/res/edje/images/lux_3_module_calendar_phase_nightsky_02.png diff --git a/res/edje/images/lux_3_module_calendar_phase_windowframe.png b/res/edje/images/lux_3_module_calendar_phase_windowframe.png Binary files differnew file mode 100644 index 0000000..e896ed4 --- /dev/null +++ b/res/edje/images/lux_3_module_calendar_phase_windowframe.png diff --git a/res/images/lux_3_bg_01.png b/res/images/lux_3_bg_01.png Binary files differnew file mode 100644 index 0000000..f314a98 --- /dev/null +++ b/res/images/lux_3_bg_01.png diff --git a/res/images/lux_3_hands_hr.png b/res/images/lux_3_hands_hr.png Binary files differnew file mode 100644 index 0000000..c1eced5 --- /dev/null +++ b/res/images/lux_3_hands_hr.png diff --git a/res/images/lux_3_hands_hr_shadow.png b/res/images/lux_3_hands_hr_shadow.png Binary files differnew file mode 100644 index 0000000..781dd71 --- /dev/null +++ b/res/images/lux_3_hands_hr_shadow.png diff --git a/res/images/lux_3_hands_min.png b/res/images/lux_3_hands_min.png Binary files differnew file mode 100644 index 0000000..f8ab5e0 --- /dev/null +++ b/res/images/lux_3_hands_min.png diff --git a/res/images/lux_3_hands_min_shadow.png b/res/images/lux_3_hands_min_shadow.png Binary files differnew file mode 100644 index 0000000..a94ce18 --- /dev/null +++ b/res/images/lux_3_hands_min_shadow.png diff --git a/res/images/lux_3_hands_module_calendar.png b/res/images/lux_3_hands_module_calendar.png Binary files differnew file mode 100644 index 0000000..a95a631 --- /dev/null +++ b/res/images/lux_3_hands_module_calendar.png diff --git a/res/images/lux_3_hands_module_calendar_shadow.png b/res/images/lux_3_hands_module_calendar_shadow.png Binary files differnew file mode 100644 index 0000000..b7c1ef7 --- /dev/null +++ b/res/images/lux_3_hands_module_calendar_shadow.png diff --git a/res/images/lux_3_hands_sec.png b/res/images/lux_3_hands_sec.png Binary files differnew file mode 100644 index 0000000..b9cfdfb --- /dev/null +++ b/res/images/lux_3_hands_sec.png diff --git a/res/images/lux_3_hands_sec_shadow.png b/res/images/lux_3_hands_sec_shadow.png Binary files differnew file mode 100644 index 0000000..de8b802 --- /dev/null +++ b/res/images/lux_3_hands_sec_shadow.png diff --git a/src/data.c b/src/data.c new file mode 100644 index 0000000..fbc736c --- /dev/null +++ b/src/data.c @@ -0,0 +1,547 @@ +/* + * 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_common.h> +#include <Elementary.h> +#include <efl_extension.h> +#include <dlog.h> + +#include "classic-watch.h" +#include "data.h" + +#define RES_PATH "/usr/apps/org.tizen.classic-watch/res/" + +#define IMAGE_HANDS_SEC "images/lux_3_hands_sec.png" +#define IMAGE_HANDS_MIN "images/lux_3_hands_min.png" +#define IMAGE_HANDS_HOUR "images/lux_3_hands_hr.png" +#define IMAGE_HANDS_MODULE_CALENDAR "images/lux_3_hands_module_calendar.png" +#define IMAGE_HANDS_SEC_SHADOW "images/lux_3_hands_sec_shadow.png" +#define IMAGE_HANDS_MIN_SHADOW "images/lux_3_hands_min_shadow.png" +#define IMAGE_HANDS_HOUR_SHADOW "images/lux_3_hands_hr_shadow.png" +#define IMAGE_HANDS_MODULE_CALENDAR_SHADOW "images/lux_3_hands_module_calendar_shadow.png" + +#define MINIMUM_DAY_DIFFERENCE 32 + +typedef struct _date_info { + int year; + int month; + int day; +} date_info_s; + +/** + * Moon phase stamp of next five years. + * Sets only phase stamp. + */ +date_info_s moon_phase_data[5][52] = { + /* + * 2016 data set. + * first phase stamp is "Last Quarter". + */ + { + { 2015, 12, 25}, + { 2016, 1, 2 }, { 2016, 1, 10 }, { 2016, 1, 16 }, { 2016, 1, 24 }, + { 2016, 2, 1 }, { 2016, 2, 8 }, { 2016, 2, 15 }, { 2016, 2, 22 }, + { 2016, 3, 1 }, { 2016, 3, 9 }, { 2016, 3, 15 }, { 2016, 3, 23 }, { 2016, 3, 31 }, + { 2016, 4, 7 }, { 2016, 4, 14 }, { 2016, 4, 22 }, { 2016, 4, 30 }, + { 2016, 5, 6 }, { 2016, 5, 13 }, { 2016, 5, 21 }, { 2016, 5, 29 }, + { 2016, 6, 5 }, { 2016, 6, 12 }, { 2016, 6, 20 }, { 2016, 6, 27 }, + { 2016, 7, 4 }, { 2016, 7, 12 }, { 2016, 7, 19 }, { 2016, 7, 26 }, + { 2016, 8, 2 }, { 2016, 8, 10 }, { 2016, 8, 18 }, { 2016, 8, 25 }, + { 2016, 9, 1 }, { 2016, 9, 9 }, { 2016, 9, 16 }, { 2016, 9, 23 }, + { 2016, 10, 1 }, { 2016, 10, 9 }, { 2016, 10, 16 }, { 2016, 10, 22 }, { 2016, 10, 30 }, + { 2016, 11, 7 }, { 2016, 11, 14 }, { 2016, 11, 21 }, { 2016, 11, 29 }, + { 2016, 12, 7 }, { 2016, 12, 14 }, { 2016, 12, 21 }, { 2016, 12, 29 }, + { 2017, 1, 5} + }, + + /* + * 2017 data set. + * first phase stamp is "First Quarter". + */ + { + { 2016, 12, 29 }, + { 2017, 1, 5 }, { 2017, 1, 12 }, { 2017, 1, 19 }, { 2017, 1, 28 }, + { 2017, 2, 4 }, { 2017, 2, 11 }, { 2017, 2, 18 }, { 2017, 2, 26 }, + { 2017, 3, 5 }, { 2017, 3, 12 }, { 2017, 3, 20 }, { 2017, 3, 28 }, + { 2017, 4, 3 }, { 2017, 4, 11 }, { 2017, 4, 19 }, { 2017, 4, 26 }, + { 2017, 5, 3 }, { 2017, 5, 10 }, { 2017, 5, 19 }, { 2017, 5, 25 }, + { 2017, 6, 1 }, { 2017, 6, 9 }, { 2017, 6, 17 }, { 2017, 6, 24 }, + { 2017, 7, 1 }, { 2017, 7, 9 }, { 2017, 7, 16 }, { 2017, 7, 23 }, { 2017, 7, 30 }, + { 2017, 8, 7 }, { 2017, 8, 15 }, { 2017, 8, 21 }, { 2017, 8, 29 }, + { 2017, 9, 6 }, { 2017, 9, 13 }, { 2017, 9, 20 }, { 2017, 9, 28 }, + { 2017, 10, 5 }, { 2017, 10, 12 }, { 2017, 10, 19 }, { 2017, 10, 27 }, + { 2017, 11, 4 }, { 2017, 11, 10 }, { 2017, 11, 18 }, { 2017, 11, 26 }, + { 2017, 12, 3 }, { 2017, 12, 10 }, { 2017, 12, 18 }, { 2017, 12, 26 }, + { 2018, 1, 2 }, { 2018, 1, 8 } + }, + + /* + * 2018 data set. + * first phase stamp is "Full Moon". + */ + { + { 2017, 12, 26 }, + { 2018, 1, 2 }, { 2018, 1, 8 }, { 2018, 1, 17 }, { 2018, 1, 24 }, { 2018, 1, 31 }, + { 2018, 2, 7 }, { 2018, 2, 15 }, { 2018, 2, 23 }, + { 2018, 3, 2 }, { 2018, 3, 9 }, { 2018, 3, 17 }, { 2018, 3, 24 }, { 2018, 3, 31 }, + { 2018, 4, 8 }, { 2018, 4, 16 }, { 2018, 4, 22 }, { 2018, 4, 30 }, + { 2018, 5, 8 }, { 2018, 5, 15 }, { 2018, 5, 22 }, { 2018, 5, 29 }, + { 2018, 6, 6 }, { 2018, 6, 13 }, { 2018, 6, 20 }, { 2018, 6, 28 }, + { 2018, 7, 6 }, { 2018, 7, 13 }, { 2018, 7, 19 }, { 2018, 7, 27 }, + { 2018, 8, 4 }, { 2018, 8, 11 }, { 2018, 8, 18 }, { 2018, 8, 26 }, + { 2018, 9, 3 }, { 2018, 9, 9 }, { 2018, 9, 16}, { 2018, 9, 25 }, + { 2018, 10, 2 }, { 2018, 10, 9 }, { 2018, 10, 16 }, { 2018, 10, 24 }, { 2018, 10, 31 }, + { 2018, 11, 7 }, { 2018, 11, 15 }, { 2018, 11, 23 }, { 2018, 11, 30 }, + { 2018, 12, 7 }, { 2018, 12, 15 }, { 2018, 12, 22 }, { 2018, 12, 29 }, + { 2019, 1, 6 } + }, + + /* + * 2019 data set. + * first phase stamp is "New Moon". + */ + { + { 2018, 12, 29 }, + { 2019, 1, 6 }, { 2019, 1, 14 }, { 2019, 1, 21 }, { 2019, 1, 27 }, + { 2019, 2, 4 }, { 2019, 2, 12 }, { 2019, 2, 19 }, { 2019, 2, 26 }, + { 2019, 3, 6 }, { 2019, 3, 14 }, { 2019, 3, 21 }, { 2019, 3, 28 }, + { 2019, 4, 5 }, { 2019, 4, 12 }, { 2019, 4, 19 }, { 2019, 4, 26 }, + { 2019, 5, 4 }, { 2019, 5, 12 }, { 2019, 5, 18 }, { 2019, 5, 26 }, + { 2019, 6, 3 }, { 2019, 6, 10 }, { 2019, 6, 17 }, { 2019, 6, 25 }, + { 2019, 7, 2 }, { 2019, 7, 9 }, { 2019, 7, 16 }, { 2019, 7, 25 }, + { 2019, 8, 1 }, { 2019, 8, 7 }, { 2019, 8, 15 }, { 2019, 8, 23 }, { 2019, 8, 30 }, + { 2019, 9, 6 }, { 2019, 9, 14 }, { 2019, 9, 22 }, { 2019, 9, 28}, + { 2019, 10, 5 }, { 2019, 10, 13 }, { 2019, 10, 21 }, { 2019, 10, 28 }, + { 2019, 11, 4 }, { 2019, 11, 12 }, { 2019, 11, 19 }, { 2019, 11, 26 }, + { 2019, 12, 4 }, { 2019, 12, 12 }, { 2019, 12, 19 }, { 2019, 12, 26 }, + { 2020, 1, 3 }, { 2020, 1, 10 } + }, + + /* + * 2020 data set. + * first phase stamp is "First Quarter". + */ + { + { 2019, 12, 26 }, + { 2020, 1, 3 }, { 2020, 1, 10 }, { 2020, 1, 17 }, { 2020, 1, 24 }, + { 2020, 2, 2 }, { 2020, 2, 9 }, { 2020, 2, 15 }, { 2020, 2, 23 }, + { 2020, 3, 2 }, { 2020, 3, 9 }, { 2020, 3, 16 }, { 2020, 3, 24 }, + { 2020, 4, 1 }, { 2020, 4, 8 }, { 2020, 4, 14 }, { 2020, 4, 23 }, { 2020, 4, 30 }, + { 2020, 5, 7 }, { 2020, 5, 14 }, { 2020, 5, 22 }, { 2020, 5, 30 }, + { 2020, 6, 5 }, { 2020, 6, 13 }, { 2020, 6, 21 }, { 2020, 6, 28 }, + { 2020, 7, 5 }, { 2020, 7, 12 }, { 2020, 7, 20 }, { 2020, 7, 27 }, + { 2020, 8, 3 }, { 2020, 8, 11 }, { 2020, 8, 19 }, { 2020, 8, 25 }, + { 2020, 9, 2 }, { 2020, 9, 10 }, { 2020, 9, 17 }, { 2020, 9, 24 }, + { 2020, 10, 1 }, { 2020, 10, 10 }, { 2020, 10, 16 }, { 2020, 10, 23 }, { 2020, 10, 31 }, + { 2020, 11, 8 }, { 2020, 11, 15 }, { 2020, 11, 22 }, { 2020, 11, 30 }, + { 2020, 12, 8 }, { 2020, 12, 14 }, { 2020, 12, 21 }, { 2020, 12, 30 }, + { 2021, 1, 6} + }, +}; + +/** + * For each year, set first stamp. (2016 ~ 2020) + * 0 : New Moon + * 1 : First Quarter + * 2 : Full Moon + * 3 : Last Quarter + */ +static int moon_phase_first_angle[5] = { 3, 1, 2, 0, 1 }; + +/** + * @brief Get path of resource. + * @param[in] file_in File name + * @param[out] file_path_out The point to which save full path of the resource + * @param[in] file_path_max Size of file name include path + */ +void data_get_resource_path(const char *file_in, char *file_path_out, int file_path_max) +{ + snprintf(file_path_out, file_path_max, "%s%s", RES_PATH, file_in); +} + +/** + * @brief Initialization function for data module. + */ +void data_initialize(void) +{ + /* + * If you need to initialize managing data, + * please use this function. + */ +} + +/** + * @brief Finalization function for data module. + */ +void data_finalize(void) +{ + /* + * If you need to finalize managing data, + * please use this function. + */ +} + +/** + * @brief Get plus angle for the hour hand. + * @param[in] minute Current minute + */ +int data_get_plus_angle(int minute) +{ + int angle = 0; + + if (minute >= 0 && minute < 12) { + angle = 0; + } if (minute >= 12 && minute < 24) { + angle = 6; + } else if (minute >= 24 && minute < 36) { + angle = 12; + } else if (minute >= 36 && minute < 48) { + angle = 18; + } else if (minute >= 48 && minute < 60) { + angle = 24; + } + + return angle; +} + +/** + * @brief Get a image path of the part. + * @param[in] type The part type + */ +char *data_get_parts_image_path(parts_type_e type) +{ + char image_path[PATH_MAX] = { 0, }; + char *resource_image = NULL; + + switch (type) { + case PARTS_TYPE_HANDS_SEC: + resource_image = IMAGE_HANDS_SEC; + break; + case PARTS_TYPE_HANDS_MIN: + resource_image = IMAGE_HANDS_MIN; + break; + case PARTS_TYPE_HANDS_HOUR: + resource_image = IMAGE_HANDS_HOUR; + break; + case PARTS_TYPE_HANDS_MODULE_MONTH: + case PARTS_TYPE_HANDS_MODULE_WEEKDAY: + resource_image = IMAGE_HANDS_MODULE_CALENDAR; + break; + case PARTS_TYPE_HANDS_SEC_SHADOW: + resource_image = IMAGE_HANDS_SEC_SHADOW; + break; + case PARTS_TYPE_HANDS_MIN_SHADOW: + resource_image = IMAGE_HANDS_MIN_SHADOW; + break; + case PARTS_TYPE_HANDS_HOUR_SHADOW: + resource_image = IMAGE_HANDS_HOUR_SHADOW; + break; + case PARTS_TYPE_HANDS_MODULE_MONTH_SHADOW: + case PARTS_TYPE_HANDS_MODULE_WEEKDAY_SHADOW: + resource_image = IMAGE_HANDS_MODULE_CALENDAR_SHADOW; + break; + default: + dlog_print(DLOG_ERROR, LOG_TAG, "type error : %d", type); + return NULL; + } + + data_get_resource_path(resource_image, image_path, sizeof(image_path)); + + return strdup(image_path); +} + +/** + * @brief Get a position of the part. + * @param[in] type The part type + * @param[out] x The pointer to an integer in which to store the X coordinate of the part + * @param[out] y The pointer to an integer in which to store the Y coordinate of the part + */ +void data_get_parts_position(parts_type_e type, int *x, int *y) +{ + switch (type) { + case PARTS_TYPE_HANDS_SEC: + *x = (BASE_WIDTH / 2) - (HANDS_SEC_WIDTH / 2); + *y = 0; + break; + case PARTS_TYPE_HANDS_MIN: + *x = (BASE_WIDTH / 2) - (HANDS_MIN_WIDTH / 2); + *y = 0; + break; + case PARTS_TYPE_HANDS_HOUR: + *x = (BASE_WIDTH / 2) - (HANDS_HOUR_WIDTH / 2); + *y = 0; + break; + case PARTS_TYPE_HANDS_MODULE_MONTH: + *x = (BASE_WIDTH / 2) - HANDS_MODULE_CALENDAR_WIDTH - 54; + *y = 175; + break; + case PARTS_TYPE_HANDS_MODULE_WEEKDAY: + *x = (BASE_WIDTH / 2) + 54; + *y = 175; + break; + case PARTS_TYPE_HANDS_SEC_SHADOW: + *x = (BASE_WIDTH / 2) - (HANDS_SEC_WIDTH / 2); + *y = HANDS_SEC_SHADOW_PADDING; + break; + case PARTS_TYPE_HANDS_MIN_SHADOW: + *x = (BASE_WIDTH / 2) - (HANDS_MIN_WIDTH / 2); + *y = HANDS_MIN_SHADOW_PADDING; + break; + case PARTS_TYPE_HANDS_HOUR_SHADOW: + *x = (BASE_WIDTH / 2) - (HANDS_HOUR_WIDTH / 2); + *y = HANDS_HOUR_SHADOW_PADDING; + break; + case PARTS_TYPE_HANDS_MODULE_MONTH_SHADOW: + *x = (BASE_WIDTH / 2) - HANDS_MODULE_CALENDAR_WIDTH - 54; + *y = 175 + HANDS_MODULE_CALENDAR_PADDING; + break; + case PARTS_TYPE_HANDS_MODULE_WEEKDAY_SHADOW: + *x = (BASE_WIDTH / 2) + 54; + *y = 175 + HANDS_MODULE_CALENDAR_PADDING; + break; + default: + dlog_print(DLOG_ERROR, LOG_TAG, "type error : %d", type); + break; + } + +} + +/** + * @brief Get a width size of the part. + * @param[in] type The part type + */ +int data_get_parts_width_size(parts_type_e type) +{ + int parts_width = 0; + + switch (type) { + case PARTS_TYPE_HANDS_SEC: + case PARTS_TYPE_HANDS_SEC_SHADOW: + parts_width = HANDS_SEC_WIDTH; + break; + case PARTS_TYPE_HANDS_MIN: + case PARTS_TYPE_HANDS_MIN_SHADOW: + parts_width = HANDS_MIN_WIDTH; + break; + case PARTS_TYPE_HANDS_HOUR: + case PARTS_TYPE_HANDS_HOUR_SHADOW: + parts_width = HANDS_HOUR_WIDTH; + break; + case PARTS_TYPE_HANDS_MODULE_MONTH: + case PARTS_TYPE_HANDS_MODULE_MONTH_SHADOW: + case PARTS_TYPE_HANDS_MODULE_WEEKDAY: + case PARTS_TYPE_HANDS_MODULE_WEEKDAY_SHADOW: + parts_width = HANDS_MODULE_CALENDAR_WIDTH; + break; + default: + dlog_print(DLOG_ERROR, LOG_TAG, "type error : %d", type); + break; + } + + return parts_width; +} + +/** + * @brief Get a height size of the part. + * @param[in] type The part type + */ +int data_get_parts_height_size(parts_type_e type) +{ + int parts_height = 0; + + switch (type) { + case PARTS_TYPE_HANDS_SEC: + case PARTS_TYPE_HANDS_SEC_SHADOW: + parts_height = HANDS_SEC_HEIGHT; + break; + case PARTS_TYPE_HANDS_MIN: + case PARTS_TYPE_HANDS_MIN_SHADOW: + parts_height = HANDS_MIN_HEIGHT; + break; + case PARTS_TYPE_HANDS_HOUR: + case PARTS_TYPE_HANDS_HOUR_SHADOW: + parts_height = HANDS_HOUR_HEIGHT; + break; + case PARTS_TYPE_HANDS_MODULE_MONTH: + case PARTS_TYPE_HANDS_MODULE_MONTH_SHADOW: + case PARTS_TYPE_HANDS_MODULE_WEEKDAY: + case PARTS_TYPE_HANDS_MODULE_WEEKDAY_SHADOW: + parts_height = HANDS_MODULE_CALENDAR_HEIGHT; + break; + default: + dlog_print(DLOG_ERROR, LOG_TAG, "type error : %d", type); + break; + } + + return parts_height; +} + +/** + * @brief Check whether a leap year. + * @pram[in] year The year number + */ +static Eina_Bool _check_leap_year(int year) +{ + Eina_Bool ret = EINA_FALSE; + + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) { + ret = EINA_TRUE; + } else { + ret = EINA_FALSE; + } + + return ret; +} + +/** + * @brief Calculates total days. + * @pram[in] day The day number + * @pram[in] month The month number + * @pram[in] year The year number + */ +static int _get_total_days(int day, int month, int year) +{ + Eina_Bool is_leap_year = EINA_FALSE; + int months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + int i = 0; + long total = 0L; + + total = (year - 1) * 365L + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400; + + is_leap_year = _check_leap_year(year); + if (is_leap_year) { + months[1]++; + } + + for (i = 0; i < month - 1; i++) { + total += months[i]; + } + + total += day; + + return total; +} + +/** + * @brief Calculates rotating angle for moon phase. + * @pram[in] day The day number + * @pram[in] month The month number + * @pram[in] year The year number + * @pram[in] start_stamp The structure of date info + * @pram[in] last_stamp The structure of date info + * @pram[in] current_stamp_num The first moon phase type of this month + */ +static float _calculate_angle(int day, int month, int year, date_info_s start_stamp, date_info_s last_stamp, int current_stamp_num) +{ + Eina_Bool is_leap_year = EINA_FALSE; + float angle = 0.0f; + int months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + int start_year_month_day = 0; + int denomi_stamp = 0, number_stamp = 0; + + is_leap_year = _check_leap_year(year); + if (is_leap_year) { + months[1]++; + } + + start_year_month_day = months[start_stamp.month]; + + denomi_stamp = _get_total_days(last_stamp.day, last_stamp.month, last_stamp.year) - _get_total_days(start_stamp.day, start_stamp.month, start_stamp.year) + 1; + number_stamp = _get_total_days(day, month, year) - _get_total_days(start_stamp.day, start_stamp.month, start_stamp.year); + + if (denomi_stamp > MINIMUM_DAY_DIFFERENCE) { + denomi_stamp = (start_year_month_day - start_stamp.day) + 1 + last_stamp.day; + } + + if (number_stamp > MINIMUM_DAY_DIFFERENCE) { + number_stamp = (start_year_month_day - start_stamp.day) + 1 + day; + } + + if (start_stamp.year == last_stamp.year && + start_stamp.month == last_stamp.month && + start_stamp.day == last_stamp.day) { + angle = 45 * current_stamp_num; + } else { + angle = ((float) ((float) number_stamp / (float) denomi_stamp) * 45) + 45 * current_stamp_num; + } + + return angle; +} + +/** + * @brief Get angle of moon phase. + * @pram[in] day The day number + * @pram[in] month The month number + * @pram[in] year The year number + */ +float data_get_moonphase(int day, int month, int year) +{ + date_info_s start_stamp; + date_info_s last_stamp; + float angle = 0.0f; + int year_idx = 0; + int current_stamp_num = 0; + int i = 0; + + /* + * This watch sample provide moon phase from 2016 to 2020. + */ + if (year < 2016 || year > 2020) { + return 0; + } + + year_idx = year - 2016; + + /* + * Find stamp using current date. + */ + for (i = 0; i < 52; i++) { + if (moon_phase_data[year_idx][i].year == year && + moon_phase_data[year_idx][i].month == month && + moon_phase_data[year_idx][i].day == day) { + /* + * If stamp date equal to current date, set current stamp to that stamp. + */ + start_stamp.year = last_stamp.year = moon_phase_data[year_idx][i].year; + start_stamp.month = last_stamp.month = moon_phase_data[year_idx][i].month; + start_stamp.day = last_stamp.day = moon_phase_data[year_idx][i].day; + + current_stamp_num = (moon_phase_first_angle[year_idx] + i - 1) % 4; + break; + } else if (((moon_phase_data[year_idx][i].year == year) && + (moon_phase_data[year_idx][i].month > month || (moon_phase_data[year_idx][i].month == month && moon_phase_data[year_idx][i].day > day))) || + moon_phase_data[year_idx][i].year > year) { + + /* + * If that's not it, find the median stamp. + */ + start_stamp.year = moon_phase_data[year_idx][i - 1].year; + start_stamp.month = moon_phase_data[year_idx][i - 1].month; + start_stamp.day = moon_phase_data[year_idx][i - 1].day; + + last_stamp.year = moon_phase_data[year_idx][i].year; + last_stamp.month = moon_phase_data[year_idx][i].month; + last_stamp.day = moon_phase_data[year_idx][i].day; + + current_stamp_num = (moon_phase_first_angle[year_idx] + i + 2) % 4; + break; + } + } + + angle = _calculate_angle(day, month, year, start_stamp, last_stamp, current_stamp_num); + + return (angle + 60.0); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e0cbc36 --- /dev/null +++ b/src/main.c @@ -0,0 +1,575 @@ +/* + * 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 <tizen.h> +#include <app.h> +#include <watch_app.h> +#include <watch_app_efl.h> +#include <system_settings.h> +#include <efl_extension.h> +#include <dlog.h> + +#include "classic-watch.h" +#include "view.h" +#include "data.h" + +#define IMAGE_BG "images/lux_3_bg_01.png" + +static struct main_info { + int cur_min; + int cur_day; + int cur_month; + int cur_weekday; + float cur_moonphase; +} s_info = { + .cur_min = 0, + .cur_day = 0, + .cur_month = 0, + .cur_weekday = 0, + .cur_moonphase = 0.0f, +}; + +static void _set_time(int hour, int min, int sec); +static void _set_date(int day, int month, int day_of_week); +static void _set_moonphase(int day, int month, int year); +static Evas_Object *_create_parts(parts_type_e type); +static void _create_base_gui(int width, int height); + +/** + * @brief The system language changed event callback function. + * @param[in] event_info The system event information + * @param[in] user_data The user data passed from the add event handler function + */ +void lang_changed(app_event_info_h event_info, void* user_data) +{ + /* + * Takes necessary actions when language setting is changed + */ + char *locale = NULL; + + system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &locale); + if (locale == NULL) + return; + + elm_language_set(locale); + free(locale); + + return; +} + +/** + * @brief The region format changed event callback function. + * @param[in] event_info The system event information + * @param[in] user_data The user data passed from the add event handler function + */ +void region_changed(app_event_info_h event_info, void* user_data) +{ + /* + * Takes necessary actions when region setting is changed + */ +} + +/** + * @brief The low battery event callback function. + * @param[in] event_info The system event information + * @param[in] user_data The user data passed from the add event handler function + */ +void low_battery(app_event_info_h event_info, void* user_data) +{ + /* + * Takes necessary actions when system is running on low battery + */ +} + +/** + * @brief The low memory event callback function. + * @param[in] event_info The system event information + * @param[in] user_data The user data passed from the add event handler function + */ +void low_memory(app_event_info_h event_info, void* user_data) +{ + /* + * Takes necessary actions when system is running on low memory + */ + watch_app_exit(); +} + +/** + * @brief The device orientation changed event callback function. + * @param[in] event_info The system event information + * @param[in] user_data The user data passed from the add event handler function + */ +void device_orientation(app_event_info_h event_info, void* user_data) +{ + /* + * Takes necessary actions when device orientation is changed + */ +} + +/** + * @brief Called when the application starts. + * @param[in] width The width of the window of idle screen that will show the watch UI + * @param[in] height The height of the window of idle screen that will show the watch UI + * @param[in] user_data The user data passed from the callback registration function + */ +static bool app_create(int width, int height, void* user_data) +{ + /* + * Hook to take necessary actions before main event loop starts + * Initialize UI resources and application's data + */ + + app_event_handler_h handlers[5] = { NULL, }; + + /* + * Register callbacks for each system event + */ + if (watch_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, lang_changed, NULL) != APP_ERROR_NONE) + dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler () is failed"); + + if (watch_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, region_changed, NULL) != APP_ERROR_NONE) + dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler () is failed"); + + if (watch_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, low_battery, NULL) != APP_ERROR_NONE) + dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler () is failed"); + + if (watch_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, low_memory, NULL) != APP_ERROR_NONE) + dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler () is failed"); + + if (watch_app_add_event_handler(&handlers[APP_EVENT_DEVICE_ORIENTATION_CHANGED], APP_EVENT_DEVICE_ORIENTATION_CHANGED, device_orientation, NULL) != APP_ERROR_NONE) + dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler () is failed"); + + dlog_print(DLOG_DEBUG, LOG_TAG, "%s", __func__); + + /* + * Create base GUI + */ + _create_base_gui(width, height); + + return true; +} + +/** + * @brief Called when another application sends a launch request to the application. + * @param[in] width The width of the window of idle screen that will show the watch UI + * @param[in] height The height of the window of idle screen that will show the watch UI + * @param[in] user_data The user data passed from the callback registration function + */ +static void app_control(app_control_h app_control, void *user_data) +{ + /* + * Handle the launch request. + */ +} + +/** + * @brief Called when the application is completely obscured by another application and becomes invisible. + * @param[in] user_data The user data passed from the callback registration function + */ +static void app_pause(void *user_data) +{ + /* + * Take necessary actions when application becomes invisible. + */ +} + +/** + * @brief Called when the application becomes visible. + * @param[in] user_data The user data passed from the callback registration function + */ +static void app_resume(void *user_data) +{ + /* + * Take necessary actions when application becomes visible. + */ +} + +/** + * @brief Called when the application's main loop exits. + * @param[in] user_data The user data passed from the callback registration function + */ +static void app_terminate(void *user_data) +{ + view_destroy_base_gui(); +} + +/** + * @brief Called at each second. This callback is not called while the app is paused or the device is in ambient mode. + * @param[in] watch_time The watch time handle. watch_time will not be available after returning this callback. It will be freed by the framework. + * @param[in] user_data The user data to be passed to the callback functions + */ +void app_time_tick(watch_time_h watch_time, void* user_data) +{ + int hour = 0; + int min = 0; + int sec = 0; + int year = 0; + int month = 0; + int day = 0; + int day_of_week = 0; + + watch_time_get_hour(watch_time, &hour); + watch_time_get_minute(watch_time, &min); + watch_time_get_second(watch_time, &sec); + watch_time_get_day(watch_time, &day); + watch_time_get_month(watch_time, &month); + watch_time_get_year(watch_time, &year); + watch_time_get_day_of_week(watch_time, &day_of_week); + + _set_time(hour, min, sec); + _set_date(day, month, day_of_week); + _set_moonphase(day, month, year); +} + +/** + * @brief Called at each minute when the device in the ambient mode. + * @param[in] watch_time The watch time handle. watch_time will not be available after returning this callback. It will be freed by the framework + * @param[in] user_data The user data to be passed to the callback functions + */ +void app_ambient_tick(watch_time_h watch_time, void* user_data) +{ +} + +/** + * @brief Called when the device enters or exits the ambient mode. + * @param[in] ambient_mode If @c true the device enters the ambient mode, otherwise @c false + * @param[in] user_data The user data to be passed to the callback functions + */ +void app_ambient_changed(bool ambient_mode, void* user_data) +{ + if (ambient_mode) { + /* + * Prepare to enter the ambient mode + */ + } else { + /* + * Prepare to exit the ambient mode + */ + } +} + +/** + * @brief Main function of the application. + */ +int main(int argc, char *argv[]) +{ + int ret = 0; + + watch_app_lifecycle_callback_s event_callback = { 0, }; + + event_callback.create = app_create; + event_callback.terminate = app_terminate; + event_callback.pause = app_pause; + event_callback.resume = app_resume; + event_callback.app_control = app_control; + event_callback.time_tick = app_time_tick; + event_callback.ambient_tick = app_ambient_tick; + event_callback.ambient_changed = app_ambient_changed; + + ret = watch_app_main(argc, argv, &event_callback, NULL); + if (ret != APP_ERROR_NONE) + dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_main() is failed. err = %d", ret); + + return ret; +} + +/** + * @brief Set time at the watch. + * @pram[in] hour The hour number + * @pram[in] min The min number + * @pram[in] sec The sec number + */ +static void _set_time(int hour, int min, int sec) +{ + Evas_Object *bg = NULL; + Evas_Object *hands = NULL; + Evas_Object *hands_shadow = NULL; + double degree = 0.0f; + + bg = view_get_bg(); + if (bg == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] Failed to get bg", __func__, __LINE__); + return; + } + + /* + * Rotate hands at the watch + */ + degree = sec * SEC_ANGLE; + hands = evas_object_data_get(bg, "__HANDS_SEC__"); + view_rotate_hand(hands, degree, (BASE_WIDTH / 2), (BASE_HEIGHT / 2)); + hands_shadow = evas_object_data_get(bg, "__HANDS_SEC_SHADOW__"); + view_rotate_hand(hands_shadow, degree, (BASE_WIDTH / 2), (BASE_HEIGHT / 2) + HANDS_SEC_SHADOW_PADDING); + + if (s_info.cur_min != min) { + degree = min * MIN_ANGLE; + hands = evas_object_data_get(bg, "__HANDS_MIN__"); + view_rotate_hand(hands, degree, (BASE_WIDTH / 2), (BASE_HEIGHT / 2)); + hands_shadow = evas_object_data_get(bg, "__HANDS_MIN_SHADOW__"); + view_rotate_hand(hands_shadow, degree, (BASE_WIDTH / 2), (BASE_HEIGHT / 2) + HANDS_MIN_SHADOW_PADDING); + s_info.cur_min = min; + + degree = (hour * HOUR_ANGLE) + data_get_plus_angle(min); + hands = evas_object_data_get(bg, "__HANDS_HOUR__"); + view_rotate_hand(hands, degree, (BASE_WIDTH / 2), (BASE_HEIGHT / 2)); + hands_shadow = evas_object_data_get(bg, "__HANDS_HOUR_SHADOW__"); + view_rotate_hand(hands_shadow, degree, (BASE_WIDTH / 2), (BASE_HEIGHT / 2) + HANDS_HOUR_SHADOW_PADDING); + } +} + +/** + * @brief Set date at the watch. + * @pram[in] day The day number + * @pram[in] month The month number + * @pram[in] day_of_week The day of week number + */ +static void _set_date(int day, int month, int day_of_week) +{ + Evas_Object *bg = NULL; + Evas_Object *module_day_layout = NULL; + Evas_Object *hands = NULL; + Evas_Object *hands_shadow = NULL; + double degree = 0.0f; + char txt_day_num[32] = { 0, }; + + /* + * Set day at the watch + */ + if (s_info.cur_day != day) { + module_day_layout = view_get_module_day_layout(); + snprintf(txt_day_num, sizeof(txt_day_num), "%d", day); + view_set_text(module_day_layout, "txt.day.num", txt_day_num); + s_info.cur_day = day; + } + + bg = view_get_bg(); + if (bg == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "[%s:%d] Failed to get bg", __func__, __LINE__); + return; + } + + /* + * Rotate hands at the watch + */ + if (s_info.cur_month != month) { + degree = month * MONTH_ANGLE; + hands = evas_object_data_get(bg, "__HANDS_MODULE_MONTH__"); + view_rotate_hand(hands, degree, (BASE_WIDTH / 2) - (HANDS_MODULE_CALENDAR_WIDTH / 2) - 54, 175 + (HANDS_MODULE_CALENDAR_HEIGHT / 2)); + hands_shadow = evas_object_data_get(bg, "__HANDS_MODULE_MONTH_SHADOW__"); + view_rotate_hand(hands_shadow, degree, (BASE_WIDTH / 2) - (HANDS_MODULE_CALENDAR_WIDTH / 2) - 54, 175 + (HANDS_MODULE_CALENDAR_HEIGHT / 2) + HANDS_MODULE_CALENDAR_PADDING); + s_info.cur_month = month; + } + + if (s_info.cur_weekday != day_of_week) { + degree = (day_of_week - 1) * WEEKDAY_ANGLE; + hands = evas_object_data_get(bg, "__HANDS_MODULE_WEEKDAY__"); + view_rotate_hand(hands, degree, (BASE_WIDTH / 2) + (HANDS_MODULE_CALENDAR_WIDTH / 2) + 54, 175 + (HANDS_MODULE_CALENDAR_HEIGHT / 2)); + hands_shadow = evas_object_data_get(bg, "__HANDS_MODULE_WEEKDAY_SHADOW__"); + view_rotate_hand(hands_shadow, degree, (BASE_WIDTH / 2) + (HANDS_MODULE_CALENDAR_WIDTH / 2) + 54, 175 + (HANDS_MODULE_CALENDAR_HEIGHT / 2) + HANDS_MODULE_CALENDAR_PADDING); + s_info.cur_weekday = day_of_week; + } +} + +/** + * @brief Set moon phase at the watch. + * @pram[in] day The day number + * @pram[in] month The month number + * @pram[in] year The year number + */ +static void _set_moonphase(int day, int month, int year) +{ + float angle = 0.0f; + + angle = data_get_moonphase(day, month, year); + if (s_info.cur_moonphase == angle) { + return; + } + s_info.cur_moonphase = angle; + + dlog_print(DLOG_INFO, LOG_TAG, "Moon phase degree : %.2f", angle); + + view_rotate_moonphase(angle); +} + +/** + * @brief Create parts of watch. + * @param[in] type Parts type + */ +static Evas_Object *_create_parts(parts_type_e type) +{ + Evas_Object *parts = NULL; + Evas_Object *bg = NULL; + char *parts_image_path = NULL; + int x = 0, y = 0, w = 0, h = 0; + + /* + * Get the BG + */ + bg = view_get_bg(); + + /* + * Get the information about the part + */ + parts_image_path = data_get_parts_image_path(type); + data_get_parts_position(type, &x, &y); + w = data_get_parts_width_size(type); + h = data_get_parts_height_size(type); + + /* + * Create the part object + */ + parts = view_create_parts(bg, parts_image_path, x, y, w, h); + if (parts == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create parts : %d", type); + } + + free(parts_image_path); + + /* + * Set opacity to shadow hands + */ + if (type == PARTS_TYPE_HANDS_HOUR_SHADOW || + type == PARTS_TYPE_HANDS_MIN_SHADOW || + type == PARTS_TYPE_HANDS_SEC_SHADOW) { + view_set_opacity_to_parts(parts); + } + + return parts; +} + +/** + * @brief Create base GUI for the watch. + * @param[in] width The width size of the watch + * @param[in] height The height size of the watch + */ +static void _create_base_gui(int width, int height) +{ + Evas_Object *win = NULL; + Evas_Object *bg = NULL; + Evas_Object *module_moonphase_layout = NULL; + Evas_Object *module_day_layout = NULL; + Evas_Object *module_month_layout = NULL; + Evas_Object *module_weekday_layout = NULL; + Evas_Object *hands_sec = NULL; + Evas_Object *hands_min = NULL; + Evas_Object *hands_hour = NULL; + Evas_Object *hands_module_month = NULL; + Evas_Object *hands_module_weekday = NULL; + Evas_Object *hands_sec_shadow = NULL; + Evas_Object *hands_min_shadow = NULL; + Evas_Object *hands_hour_shadow = NULL; + Evas_Object *hands_module_month_shadow = NULL; + Evas_Object *hands_module_weekday_shadow = NULL; + char bg_path[PATH_MAX] = { 0, }; + char edj_path[PATH_MAX] = { 0, }; + int ret = 0; + + /* + * Get window object + */ + ret = watch_app_get_elm_win(&win); + if (ret != APP_ERROR_NONE) { + dlog_print(DLOG_ERROR, LOG_TAG, "failed to get window. err = %d", ret); + return; + } + evas_object_resize(win, width, height); + evas_object_show(win); + + /* + * Get background image file path + */ + data_get_resource_path(IMAGE_BG, bg_path, sizeof(bg_path)); + dlog_print(DLOG_ERROR, LOG_TAG, "bg_path : %s", bg_path); + + /* + * Create BG + */ + bg = view_create_bg(win, bg_path, width, height); + if (bg == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create a bg"); + return; + } + + /* + * Get edje file path + */ + data_get_resource_path(EDJ_FILE, edj_path, sizeof(edj_path)); + dlog_print(DLOG_ERROR, LOG_TAG, "edj_path : %s", edj_path); + + /* + * Create layout to display moon phase at the watch + */ + module_moonphase_layout = view_create_module_layout(bg, edj_path, "layout_module_moonphase"); + if (module_moonphase_layout) { + view_set_module_property(module_moonphase_layout, 60, 60, MODULE_MOONPHASE_SIZE, MODULE_MOONPHASE_SIZE); + view_set_module_moonphase_layout(module_moonphase_layout); + } + + /* + * Create layout to display day number at the watch + */ + module_day_layout = view_create_module_layout(bg, edj_path, "layout_module_day"); + if (module_day_layout) { + view_set_module_property(module_day_layout, BASE_WIDTH - MODULE_DAY_NUM_SIZE - MODULE_DAY_NUM_RIGHT_PADDING, (BASE_HEIGHT / 2) - (MODULE_DAY_NUM_SIZE / 2), MODULE_DAY_NUM_SIZE, MODULE_DAY_NUM_SIZE); + view_set_module_day_layout(module_day_layout); + } + + /* + * Create layout to display calendar module(month) + */ + module_month_layout = view_create_module_layout(bg, edj_path, "layout_module_month"); + if (module_month_layout) { + view_set_module_property(module_month_layout, 52, 175, MODULE_MONTH_SIZE, MODULE_MONTH_SIZE); + view_set_module_month_layout(module_month_layout); + } + + /* + * Create layout to display calendar module(day) + */ + module_weekday_layout = view_create_module_layout(bg, edj_path, "layout_module_weekday"); + if (module_weekday_layout) { + view_set_module_property(module_weekday_layout, 52 + MODULE_MONTH_SIZE, 175, MODULE_WEEKDAY_SIZE, MODULE_WEEKDAY_SIZE); + view_set_module_weekday_layout(module_weekday_layout); + } + + /* + * Create hands & shadow hands to display at the watch + */ + hands_module_month_shadow = _create_parts(PARTS_TYPE_HANDS_MODULE_MONTH_SHADOW); + evas_object_data_set(bg, "__HANDS_MODULE_MONTH_SHADOW__", hands_module_month_shadow); + hands_module_month = _create_parts(PARTS_TYPE_HANDS_MODULE_MONTH); + evas_object_data_set(bg, "__HANDS_MODULE_MONTH__", hands_module_month); + + hands_module_weekday_shadow = _create_parts(PARTS_TYPE_HANDS_MODULE_WEEKDAY_SHADOW); + evas_object_data_set(bg, "__HANDS_MODULE_WEEKDAY_SHADOW__", hands_module_weekday_shadow); + hands_module_weekday = _create_parts(PARTS_TYPE_HANDS_MODULE_WEEKDAY); + evas_object_data_set(bg, "__HANDS_MODULE_WEEKDAY__", hands_module_weekday); + + hands_sec_shadow = _create_parts(PARTS_TYPE_HANDS_SEC_SHADOW); + evas_object_data_set(bg, "__HANDS_SEC_SHADOW__", hands_sec_shadow); + hands_sec = _create_parts(PARTS_TYPE_HANDS_SEC); + evas_object_data_set(bg, "__HANDS_SEC__", hands_sec); + + hands_min_shadow = _create_parts(PARTS_TYPE_HANDS_MIN_SHADOW); + evas_object_data_set(bg, "__HANDS_MIN_SHADOW__", hands_min_shadow); + hands_min = _create_parts(PARTS_TYPE_HANDS_MIN); + evas_object_data_set(bg, "__HANDS_MIN__", hands_min); + + hands_hour_shadow = _create_parts(PARTS_TYPE_HANDS_HOUR_SHADOW); + evas_object_data_set(bg, "__HANDS_HOUR_SHADOW__", hands_hour_shadow); + hands_hour = _create_parts(PARTS_TYPE_HANDS_HOUR); + evas_object_data_set(bg, "__HANDS_HOUR__", hands_hour); +} diff --git a/src/view.c b/src/view.c new file mode 100644 index 0000000..a117681 --- /dev/null +++ b/src/view.c @@ -0,0 +1,414 @@ +/* + * 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 <Elementary.h> +#include <efl_extension.h> +#include <app.h> +#include <dlog.h> + +#include "classic-watch.h" +#include "view.h" + +static struct view_info { + Evas_Object *bg; + Evas_Object *module_moonphase_layout; + Evas_Object *module_day_layout; + Evas_Object *module_month_layout; + Evas_Object *module_weekday_layout; +} s_info = { + .bg = NULL, + .module_moonphase_layout = NULL, + .module_day_layout = NULL, + .module_month_layout = NULL, + .module_weekday_layout = NULL, +}; + +/** + * @brief Set the module moon phase layout. + */ +void view_set_module_moonphase_layout(Evas_Object *layout) +{ + if (layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "layout is NULL"); + return; + } + + s_info.module_moonphase_layout = layout; +} + +/** + * @brief Set the module day layout. + */ +void view_set_module_day_layout(Evas_Object *layout) +{ + if (layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "layout is NULL"); + return; + } + + s_info.module_day_layout = layout; +} + +/** + * @brief Set the module month layout. + */ +void view_set_module_month_layout(Evas_Object *layout) +{ + if (layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "layout is NULL"); + return; + } + + s_info.module_month_layout = layout; +} + +/** + * @brief Set the module month layout. + */ +void view_set_module_weekday_layout(Evas_Object *layout) +{ + if (layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "layout is NULL"); + return; + } + + s_info.module_weekday_layout = layout; +} + +/** + * @brief Get the bg object. + */ +Evas_Object *view_get_bg(void) +{ + return s_info.bg; +} + +/** + * @brief Get the module moon phase layout. + */ +Evas_Object *view_get_module_moonphase_layout(void) +{ + return s_info.module_moonphase_layout; +} + +/** + * @brief Get the module day layout. + */ +Evas_Object *view_get_module_day_layout(void) +{ + return s_info.module_day_layout; +} + +/** + * @brief Get the module month layout. + */ +Evas_Object *view_get_module_month_layout(void) +{ + return s_info.module_month_layout; +} + +/** + * @brief Get the module weekday layout. + */ +Evas_Object *view_get_module_weekday_layout(void) +{ + return s_info.module_weekday_layout; +} + +/** + * @brief Set text to the part. + * @param[in] parent Object has part to which you want to set text + * @param[in] part_name Part name to which you want to set the text + * @param[in] text Text you want to set to the part + */ +void view_set_text(Evas_Object *parent, const char *part_name, const char *text) +{ + if (parent == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "parent is NULL."); + return; + } + + /* Set text of target part object */ + elm_object_part_text_set(parent, part_name, text); +} + +/** + * @brief Rotate hands of the watch. + * @param[in] hand The hand you want to rotate + * @param[in] degree The degree you want to rotate + * @param[in] cx The rotation's center horizontal position + * @param[in] cy The rotation's center vertical position + */ +void view_rotate_hand(Evas_Object *hand, double degree, Evas_Coord cx, Evas_Coord cy) +{ + Evas_Map *m = NULL; + + if (hand == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "hand is NULL"); + return; + } + + m = evas_map_new(4); + evas_map_util_points_populate_from_object(m, hand); + evas_map_util_rotate(m, degree, cx, cy); + evas_object_map_set(hand, m); + evas_object_map_enable_set(hand, EINA_TRUE); + evas_map_free(m); +} + +/** + * @brief Rotate hands of the watch. + * @param[in] degree The degree you want to rotate + */ +void view_rotate_moonphase(float degree) +{ + Evas_Object *module_moonphase_layout = NULL; + Evas_Object *edj_obj = NULL; + Edje_Message_Float msg; + + module_moonphase_layout = view_get_module_moonphase_layout(); + if (module_moonphase_layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get moon phase layout"); + return; + } + + edj_obj = elm_layout_edje_get(module_moonphase_layout); + if (edj_obj == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get edje object"); + return; + } + + msg.val = degree; + + edje_object_message_send(edj_obj, EDJE_MESSAGE_FLOAT, 1, &msg); +} + +/** + * @breif Create a bg object for the watch + * @param[in] win The window object + * @param[in] image_path The image path for bg + * @param[in] width The width size of bg + * @param[in] height The height size of bg + */ +Evas_Object *view_create_bg(Evas_Object *win, const char *image_path, int width, int height) +{ + Evas_Object *bg = NULL; + Eina_Bool ret = EINA_FALSE; + + if (win == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "window is NULL"); + return NULL; + } + + bg = elm_bg_add(win); + if (bg == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to add bg"); + return NULL; + } + + ret = elm_bg_file_set(bg, image_path, NULL); + if (ret != EINA_TRUE) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to set the background image"); + evas_object_del(bg); + return NULL; + } + + elm_bg_option_set(bg, ELM_BG_OPTION_CENTER); + + evas_object_move(bg, 0, 0); + evas_object_resize(bg, width, height); + evas_object_show(bg); + + s_info.bg = bg; + + return bg; +} + +/** + * @brief Make a layout to target parent object with edje file. + * @param[in] parent The object to which you want to add this layout + * @param[in] file_path File path of EDJ file will be used + * @param[in] group_name Name of group in EDJ you want to set to + * @param[in] user_data The user data to be passed to the callback functions + */ +Evas_Object *view_create_layout(Evas_Object *parent, const char *file_path, const char *group_name, void *user_data) +{ + Evas_Object *layout = NULL; + + if (parent == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "parent is NULL."); + return NULL; + } + + /* + * Create layout by EDC(edje file) + */ + layout = elm_layout_add(parent); + elm_layout_file_set(layout, file_path, group_name); + + /* + * Layout size setting + */ + evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + + evas_object_show(layout); + + return layout; +} + +/** + * @brief Set property for module layout. + * @param[in] layout The object to which you want to set + * @param[in] x The X coordinate of the module layout + * @param[in] y The Y coordinate of the module layout + * @param[in] w The width size of the module layout + * @param[in] h The height size of the module layout + */ +void view_set_module_property(Evas_Object *layout, int x, int y, int w, int h) +{ + if (layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "layout is NULL"); + return; + } + + evas_object_move(layout, x, y); + evas_object_resize(layout, w, h); +} + +/** + * @brief Create day num layout for the watch. + * @param[in] parent The object to which you want to add this layout + * @param[in] file_path File path of EDJ file will be used + * @param[in] group_name Group name of EDJ group will be used + */ +Evas_Object *view_create_module_layout(Evas_Object *parent, const char *file_path, const char *group_name) +{ + Evas_Object *layout = NULL; + + if (parent == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "parent is NULL"); + return NULL; + } + + if (file_path == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "file path is NULL"); + return NULL; + } + + if (group_name == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "group name is NULL"); + return NULL; + } + + layout = view_create_layout(parent, file_path, group_name, NULL); + if (layout == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to create module layout"); + return NULL; + } + + evas_object_show(layout); + + return layout; +} + +/** + * @brief Set opacity to parts of watch. + * @param[in] parts The parts of watch + */ +void view_set_opacity_to_parts(Evas_Object *parts) +{ + if (parts == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to set opacity to parts"); + return; + } + + evas_object_color_set(parts, 255, 255, 255, 255 * 0.5); +} + +/** + * @brief Create a part for the watch. + * @param[in] parent The object to which you want to add this object + * @param[in] image_path The path of the image file you want to set + * @param[in] x The X coordinate of the part + * @param[in] y The Y coordinate of the part + * @param[in] w The width size of the part + * @param[in] h The height size of the part + */ +Evas_Object *view_create_parts(Evas_Object *parent, const char *image_path, int x, int y, int w, int h) +{ + Evas_Object *parts = NULL; + Eina_Bool ret = EINA_FALSE; + + if (parent == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "bg is NULL"); + return NULL; + } + + parts = elm_image_add(parent); + if (parts == NULL) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to add minute hand image"); + return NULL; + } + + ret = elm_image_file_set(parts, image_path, NULL); + if (ret != EINA_TRUE) { + dlog_print(DLOG_ERROR, LOG_TAG, "Failed to set minute hand image"); + evas_object_del(parts); + return NULL; + } + + evas_object_move(parts, x, y); + evas_object_resize(parts, w, h); + evas_object_show(parts); + + return parts; +} + +/** + * @brief Destroy base GUI. + */ +void view_destroy_base_gui(void) +{ + if (s_info.module_day_layout) { + evas_object_del(s_info.module_day_layout); + s_info.module_day_layout = NULL; + } + + if (s_info.module_month_layout) { + evas_object_del(s_info.module_month_layout); + s_info.module_month_layout = NULL; + } + + if (s_info.module_weekday_layout) { + evas_object_del(s_info.module_weekday_layout); + s_info.module_weekday_layout = NULL; + } + + if (s_info.bg) { + evas_object_data_del(s_info.bg, "__HANDS_SEC__"); + evas_object_data_del(s_info.bg, "__HANDS_MIN__"); + evas_object_data_del(s_info.bg, "__HANDS_HOUR__"); + evas_object_data_del(s_info.bg, "__HANDS_MODULE_MONTH__"); + evas_object_data_del(s_info.bg, "__HANDS_MODULE_WEEKDAY__"); + evas_object_data_del(s_info.bg, "__HANDS_SEC_SHADOW__"); + evas_object_data_del(s_info.bg, "__HANDS_MIN_SHADOW__"); + evas_object_data_del(s_info.bg, "__HANDS_HOUR_SHADOW__"); + evas_object_data_del(s_info.bg, "__HANDS_MODULE_MONTH_SHADOW__"); + evas_object_data_del(s_info.bg, "__HANDS_MODULE_WEEKDAY_SHADOW__"); + evas_object_del(s_info.bg); + s_info.bg = NULL; + } +} |