--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=9" />
+ <link rel="stylesheet" type="text/css" href="../css/styles.css" />
+ <link rel="stylesheet" type="text/css" href="../css/snippet.css" />
+ <script type="text/javascript" src="../scripts/snippet.js"></script>
+ <script type="text/javascript" src="../scripts/jquery.util.js" charset="utf-8"></script>
+ <script type="text/javascript" src="../scripts/common.js" charset="utf-8"></script>
+ <script type="text/javascript" src="../scripts/core.js" charset="utf-8"></script>
+ <script type="text/javascript" src="../scripts/search.js" charset="utf-8"></script>
+
+ <title>The (Circle) Ambient Analog Watch Sample Overview</title>
+</head>
+
+<body class="no-toc" onload="prettyPrint()" style="overflow: auto;">
+
+<div id="toc-navigation">
+</div>
+
+<div id="container"><div id="contents"><div class="content">
+ <div id="profile">
+ <p><img alt="Wearable native" src="../images/wearable_s_n.png"/></p>
+ </div>
+
+ <h1>(Circle) Ambient Analog Watch Sample Overview</h1>
+
+<p>The (Circle) Ambient Analog Watch sample application demonstrates how to implement a simple watch application with ambient mode support.</p>
+
+<p>The following figure illustrates two screens of the (Circle) Ambient Analog Watch sample application: the normal mode watch view, the ambient mode watch view and the cipher disc selection view.</p>
+
+<p class="figure">Figure 1: (Circle) Ambient Analog Watch views</p>
+ <p align="center">
+ <img alt="(Circle) Ambient Analog Watch views" src="../images/circleambientanalogwatch_wn0.png" height="240" width="240"/>
+ <img alt="(Circle) Ambient Analog Watch views" src="../images/circleambientanalogwatch_wn6.png" height="240" width="240"/>
+ <img alt="(Circle) Ambient Analog Watch views" src="../images/circleambientanalogwatch_wn1.png" height="240" width="240"/>
+ </p>
+
+<p>The current time is displayed as follows:</p>
+ <ul>
+ <li>red dot indicates seconds,</li>
+ <li>small blue dot indicates hours,</li>
+ <li>large blue dot indicates minutes.</li>
+ </ul>
+<p>Above the current date there are indicators for battery level and WiFi RSSI.</p>
+<p>To enter cipher disc selection view, you have to click the gear wheel button. From there you can select which cipher disc style you want to use.</p>
+
+<p class="figure">Figure 2: (Circle) Ambient Analog Watch widgets structure</p>
+<p align="center">
+ <img alt="(Circle) Sensors widgets structure" src="../images/circleambientanalogwatch_wn2.png" height="263" width="747"/>
+</p>
+<h2>Prerequisites</h2>
+<p>To ensure proper application execution, the
+<span style="font-family: Courier New,Courier,monospace">http://tizen.org/privilege/network.get</span> privilege must be set.</p>
+
+<h2>Implementation</h2>
+
+<h3>Main module</h3>
+<p>The <span style="font-family: Courier New,Courier,monospace">main()</span> function of the sample application is show below. The application loop
+is started when the <span style="font-family: Courier New,Courier,monospace">watch_app_main()</span>
+function is invoked. An object of <span style="font-family: Courier New,Courier,monospace">watch_app_lifecycle_callback_s</span> type can be passed to it.
+Notice how it differs from <span style="font-family: Courier New,Courier,monospace">ui_app_lifecycle_callback_s</span> typed used in the standard application type.
+The <span style="font-family: Courier New,Courier,monospace">watch_app_lifecycle_callback_s</span> structure introduces three new callback pointers to:
+</p>
+<ul>
+ <li><span style="font-family: Courier New,Courier,monospace">watch_app_time_tick_cb</span> - called every second when the application is in normal mode, giving the application a chance to refresh the time indicator,</li>
+ <li><span style="font-family: Courier New,Courier,monospace">watch_app_ambient_tick_cb</span> - called every minute when the application is in ambient, giving the application a chance to refresh the time indicator,</li>
+ <li><span style="font-family: Courier New,Courier,monospace">watch_app_ambient_changed_cb</span> - called whenever the application enters normal or ambient mode.</li>
+</ul>
+
+<pre class="prettyprint">
+int main(int argc, char *argv[])
+{
+ int ret = 0;
+
+ watch_app_lifecycle_callback_s event_callback = {0,};
+
+ event_callback.create = app_create;
+ event_callback.resume = app_resume;
+ event_callback.pause = app_pause;
+ event_callback.terminate = app_terminate;
+ event_callback.time_tick = app_time_tick;
+ event_callback.ambient_tick = app_time_tick;
+ event_callback.ambient_changed = app_ambient_changed;
+
+ ret = watch_app_main(argc, argv, &event_callback, NULL);
+ // Error handling ...
+
+ return ret;
+}
+</pre>
+
+<pre class="prettyprint">
+static void app_time_tick(watch_time_h watch_time, void *data)
+{
+ // Variable definitions and error handling ...
+ __get_date_from_watch_time(watch_time,
+ &year, &month, &day, &day_of_week,
+ &hours, &minutes, &seconds);
+
+ controller_tick(hours, minutes, seconds, year, month, day, day_of_week);
+}
+</pre>
+
+<pre class="prettyprint">
+static void app_ambient_changed(bool ambient_mode, void *data)
+{
+ controller_set_ambient_mode(ambient_mode);
+}
+</pre>
+
+<pre class="prettyprint">
+static void __get_date_from_watch_time(const watch_time_h watch_time,
+ int *year, int *month, int *day, int *day_of_week,
+ int *hours, int *minutes, int *seconds)
+{
+ watch_time_get_hour24(watch_time, hours);
+ watch_time_get_minute(watch_time, minutes);
+ watch_time_get_second(watch_time, seconds);
+ watch_time_get_year(watch_time, year);
+ watch_time_get_month(watch_time, month);
+ watch_time_get_day(watch_time, day);
+ watch_time_get_day_of_week(watch_time, day_of_week);
+}
+</pre>
+
+<h3>Controller module</h3>
+<p>Three important functions of this module are presented below. The <span style="font-family: Courier New,Courier,monospace">controller_start_application()</span>
+is called at the application's startup. It sets up the view and adds the
+<span style="font-family: Courier New,Courier,monospace">__wifi_rssi_level_changed_cb()</span>
+callback to monitor WiFi signal strength's changes. It also sets the current time on the watch view.</p>
+
+<pre class="prettyprint">
+bool controller_start_application(int width, int height,
+ int hour, int min, int sec,
+ int year, int month, int day, int week_day)
+{
+ if (!view_create_gui(width, height))
+ return false;
+
+ if (wifi_monitor_init())
+ wifi_monitor_start_measure(__wifi_rssi_level_changed_cb);
+
+ view_set_time(hour, min, sec, year, month, day, week_day);
+
+ return true;
+}
+</pre>
+
+<p>The <span style="font-family: Courier New,Courier,monospace">controller_set_ambient_mode()</span> function is called from
+<span style="font-family: Courier New,Courier,monospace">app_ambient_changed()</span>
+callback, defined in the main module. This way, the application can track whether it is in ambient or normal mode.
+It is recommended to stop any power consuming operations in the ambient mode. For example, you can change the display state to one that has most of its pixels dark.</p>
+
+<pre class="prettyprint">
+void controller_set_ambient_mode(bool ambient_mode)
+{
+ cdata.ambient_mode = ambient_mode;
+ view_set_ambient(cdata.ambient_mode);
+ if (cdata.ambient_mode) {
+ wifi_monitor_stop_measure();
+ } else {
+ wifi_monitor_start_measure(__wifi_rssi_level_changed_cb);
+ }
+}
+</pre>
+<p>Aside from updating the time and date indicators, the <span style="font-family: Courier New,Courier,monospace">controller_tick()</span>
+function reads the battery level and sets up the battery display accordingly. It happens only in ambient mode.
+The <span style="font-family: Courier New,Courier,monospace">controller_tick()</span>
+is called with one second interval when the application is in normal mode
+and with one minute interval when it is in ambient mode.</p>
+
+<pre class="prettyprint">
+void controller_tick(int hour, int min, int sec,
+ int year, int month, int day, int week_day)
+{
+ int batt_percent = 0;
+ view_set_time(hour, min, sec, year, month, day, week_day);
+ if (!cdata.ambient_mode) {
+ device_battery_get_percent(&batt_percent);
+ view_set_batt(batt_percent);
+ }
+}
+</pre>
+
+<h3>Main view module</h3>
+
+<p>The <span style="font-family: Courier New,Courier,monospace">watch_app_get_elm_win()</span>
+function is used to obtain a special watch type window. This way the application can receive ambient/normal mode switch events properly.</p>
+<p>The next step is creating two circular indicators. In order to do it, first it is neccesary to create an elementary widget and associate it with
+the circular surface.</p>
+<p>The <span style="font-family: Courier New,Courier,monospace">elm_layout</span> widget has been chosen for this operation.
+Once the <span style="font-family: Courier New,Courier,monospace">indicators_layout</span> pointer is obtained, it is possible to
+call <span style="font-family: Courier New,Courier,monospace">eext_circle_surface_layout_add()</span> function and obtain a pointer
+(<span style="font-family: Courier New,Courier,monospace">indicators_layout_surface</span>) to a
+<span style="font-family: Courier New,Courier,monospace">Eext_Circle_Surface</span> object associated with this layout.</p>
+<p>These two pointers can now be used to create circle objects - time indicators. The pointers are passed to the
+<span style="font-family: Courier New,Courier,monospace">__create_time_indicator()</span>
+function and from there to the <span style="font-family: Courier New,Courier,monospace">circle_indicator_create()</span>
+function from circle indicator module.</p>
+<p>Up to this point in <span style="font-family: Courier New,Courier,monospace">view_create_gui()</span>
+function, this application would look like in Figure 3 (left).</p>
+<p>Next, the main layout is created. It consists, among others, of circular black background with two transparent rings as in Figure 3 (right).
+The main layout object is stacked above circular objects and the effect can be seen in Figure 1.</p>
+<p>Finally, the ambient digital clock layout is created. It is hidden until the application enters the ambient mode. It is shown in Figure 1 (middle).</p>
+
+<p class="figure">Figure 3: Two circle indicators and the background</p>
+<p align="center">
+ <img alt="Two circle indicators and the background" src="../images/circleambientanalogwatch_wn4.png" height="240" width="240"/>
+ <img alt="Two circle indicators and the background" src="../images/circleambientanalogwatch_wn5.png" height="240" width="240"/>
+</p>
+
+
+<pre class="prettyprint">
+bool view_create_gui(int width, int height)
+{
+ Evas_Object *indicators_layout = NULL;
+ Eext_Circle_Surface *indicators_layout_surface = NULL;
+
+ watch_app_get_elm_win(&vd.win);
+
+ // Error handling ...
+
+ evas_object_resize(vd.win, width, height);
+
+ indicators_layout = elm_layout_add(vd.win);
+
+ // Error handling ...
+
+ evas_object_resize(indicators_layout, width, height);
+ evas_object_show(indicators_layout);
+ indicators_layout_surface = eext_circle_surface_layout_add(indicators_layout);
+
+ // Error handling ...
+
+ __create_time_indicator(&vd.hours_minutes_indicator, indicators_layout_surface, indicators_layout,
+ (HOURS_INDICATOR_REL_SIZE * (float)width/2.0),
+ TIME_INDICATOR_THICKNESS,
+ TIME_INDICATOR_R_COLOR,
+ TIME_INDICATOR_G_COLOR,
+ TIME_INDICATOR_B_COLOR);
+
+ __create_time_indicator(&vd.seconds_indicator, indicators_layout_surface, indicators_layout,
+ (MINUTES_INDICATOR_REL_SIZE * (float)width/2.0),
+ TIME_INDICATOR_THICKNESS,
+ TIME_INDICATOR_R_COLOR,
+ TIME_INDICATOR_G_COLOR,
+ TIME_INDICATOR_B_COLOR);
+
+ vd.main_layout = __create_layout(MAIN_LAYOUT_EDJE_FILE, MAIN_GRP, width, height);
+ evas_object_show(vd.main_layout);
+
+ // Other UI elements creation code ...
+
+ vd.ambient_clock = ambient_clock_create(vd.main_layout);
+ elm_layout_content_set(vd.main_layout, AMBIENT_SWALLOW_PART, vd.ambient_clock);
+
+ // Common code ...
+}
+</pre>
+
+<pre class="prettyprint">
+static const Circle_Indicator *__create_time_indicator(const Circle_Indicator **indicator,
+ Eext_Circle_Surface *indicators_layout_surface,
+ Evas_Object *indicators_layout,
+ int radius, int thickness, int r, int g, int b)
+{
+ *indicator = circle_indicator_create(indicators_layout, indicators_layout_surface);
+
+ if (!*indicator)
+ return NULL;
+
+ circle_indicator_set_radius(*indicator, radius);
+ circle_indicator_set_thickness(*indicator, thickness);
+ circle_indicator_set_color(*indicator, r, g, b,
+ TIME_INDICATOR_R_COLOR_2,
+ TIME_INDICATOR_G_COLOR_2,
+ TIME_INDICATOR_B_COLOR_2);
+ circle_indicator_show(*indicator, true);
+
+ return *indicator;
+}
+</pre>
+
+<p>Each time a time tick occurs, the controller module calls <span style="font-family: Courier New,Courier,monospace">view_set_time()</span>
+function. One of its roles is to set the proper positions of dot indicators. This is calculated when a message is sent to the main layout object
+using <span style="font-family: Courier New,Courier,monospace">edje_object_message_send()</span> function.
+</p>
+
+<pre class="prettyprint">
+void view_set_time(int hours, int minutes, int seconds,
+ int year, int month, int day, int week_day)
+{
+ // Other variable definitions ...
+
+ Edje_Message_Int_Set *msg = NULL;
+
+ if (!vd.ambient) {
+
+ // Calculations ...
+
+ circle_indicator_set(vd.seconds_indicator, 0.0, ((float)seconds) / 60.0);
+ circle_indicator_set(vd.hours_minutes_indicator,
+ ((float)hours_12) / 12.0 + ((float)minutes) / 60.0 / 12.0,
+ ((float)minutes) / 60.0);
+
+ // Date string setting ...
+
+ msg = alloca(sizeof(Edje_Message_Int_Set) + 2 * sizeof(int));
+
+ // Error handling ...
+
+ msg->count = 3;
+ msg->val[0] = hours_12;
+ msg->val[1] = minutes;
+ msg->val[2] = seconds;
+
+ edje_object_message_send(elm_layout_edje_get(vd.main_layout), EDJE_MESSAGE_INT_SET, SET_TIME_MSG_ID, msg);
+ }
+
+ ambient_clock_set_time(vd.ambient_clock, hours, minutes);
+}
+</pre>
+
+<p>Once the message is received, it is processed by edje layout object's script function:</p>
+
+<pre class="prettyprint">
+script
+{
+ public bool:ambient_mode = false;
+
+ public message(Msg_Type:type, id, ...)
+ {
+ static Float:h = 0.0;
+ static Float:m = 0.0;
+ static Float:s = 0.0;
+ static Float:rx = 0.0;
+ static Float:ry = 0.0;
+
+ if (type == MSG_INT_SET && id == SET_TIME_MSG_ID)
+ {
+ h = getarg(2);
+ m = getarg(3);
+ s = getarg(4);
+
+ rx = sin( 360.0 * (h / 12.0 + m / 60.0 / 12.0), DEGREES);
+ ry = cos( 360.0 * (h / 12.0 + m / 60.0 / 12.0), DEGREES);
+ custom_state(PART:HOURS_DOT_PART, "default", 0.0);
+ set_state_val(PART:HOURS_DOT_PART, STATE_REL1,
+ 0.5 + HOURS_MINS_DOT_RADIUS*rx - HOURS_DOT_SIZE / 2.0,
+ 0.5 - HOURS_MINS_DOT_RADIUS*ry - HOURS_DOT_SIZE / 2.0);
+ set_state_val(PART:HOURS_DOT_PART, STATE_REL2,
+ 0.5 + HOURS_MINS_DOT_RADIUS*rx + HOURS_DOT_SIZE / 2.0,
+ 0.5 - HOURS_MINS_DOT_RADIUS*ry + HOURS_DOT_SIZE / 2.0);
+ set_state(PART:HOURS_DOT_PART, "custom", 0.0);
+
+ rx = sin( 360.0 * m / 60.0, DEGREES);
+ ry = cos( 360.0 * m / 60.0, DEGREES);
+ custom_state(PART:MINUTES_DOT_PART, "default", 0.0);
+ set_state_val(PART:MINUTES_DOT_PART, STATE_REL1,
+ 0.5 + HOURS_MINS_DOT_RADIUS*rx - MINUTES_DOT_SIZE / 2.0,
+ 0.5 - HOURS_MINS_DOT_RADIUS*ry - MINUTES_DOT_SIZE / 2.0);
+ set_state_val(PART:MINUTES_DOT_PART, STATE_REL2,
+ 0.5 + HOURS_MINS_DOT_RADIUS*rx + MINUTES_DOT_SIZE / 2.0,
+ 0.5 - HOURS_MINS_DOT_RADIUS*ry + MINUTES_DOT_SIZE / 2.0);
+ set_state(PART:MINUTES_DOT_PART, "custom", 0.0);
+
+ rx = sin( 360.0 * s / 60.0, DEGREES);
+ ry = cos( 360.0 * s / 60.0, DEGREES);
+ custom_state(PART:SECONDS_DOT_PART, "default", 0.0);
+ set_state_val(PART:SECONDS_DOT_PART, STATE_REL1,
+ 0.5 + SECONDS_DOT_RADIUS*rx - SECONDS_DOT_SIZE / 2.0,
+ 0.5 - SECONDS_DOT_RADIUS*ry - SECONDS_DOT_SIZE / 2.0);
+ set_state_val(PART:SECONDS_DOT_PART, STATE_REL2,
+ 0.5 + SECONDS_DOT_RADIUS*rx + SECONDS_DOT_SIZE / 2.0,
+ 0.5 - SECONDS_DOT_RADIUS*ry + SECONDS_DOT_SIZE / 2.0);
+ set_state(PART:SECONDS_DOT_PART, "custom", 0.0);
+ }
+ }
+}
+</pre>
+
+<h3>Circle indicator view module</h3>
+
+<p>The circle indicator is a complex object, as shown in Figure 2. It holds pointers to two circle objects. One circle object is used to display an arc
+to indicate current time value progress. The second one shows the arc of progress yet to come. The creation code is shown below.</p>
+
+<pre class="prettyprint">
+const Circle_Indicator *circle_indicator_create(Evas_Object *parent, Eext_Circle_Surface *indicators_layout_surface)
+{
+ Circle_Indicator *indicator = NULL;
+
+ indicator = calloc(1, sizeof(Circle_Indicator));
+
+ if (!indicator)
+ return NULL;
+
+ indicator->indicating_indicator = eext_circle_object_add(parent, indicators_layout_surface);
+ eext_circle_object_angle_min_max_set(indicator->indicating_indicator, 0, 360);
+
+ indicator->bg_indicator = eext_circle_object_add(parent, indicators_layout_surface);
+ eext_circle_object_angle_min_max_set(indicator->bg_indicator, 0, 360);
+
+ evas_object_data_set(indicator->bg_indicator, CI_DATA_KEY, indicator);
+ evas_object_event_callback_add(indicator->bg_indicator, EVAS_CALLBACK_DEL, __evas_object_before_delete_cb, NULL);
+
+ return indicator;
+}
+</pre>
+
+<script type="text/javascript" src="../scripts/jquery.zclip.min.js"></script>
+<script type="text/javascript" src="../scripts/showhide.js"></script>
+</div></div></div>
+
+<a class="top sms" href="#"><img src="../images/btn_top.gif" alt="Go to top" /></a>
+
+<div id="footer">
+<p class="footer">Except as noted, this content - excluding the Code Examples - is licensed under <a href="http://creativecommons.org/licenses/by/3.0/legalcode" target="_blank">Creative Commons Attribution 3.0</a> and all of the Code Examples contained herein are licensed under <a href="https://www.tizen.org/bsd-3-clause-license" target="_blank">BSD-3-Clause</a>.<br/>For details, see the <a href="https://www.tizen.org/content-license" target="_blank">Content License</a>.</p>
+</div>
+
+<script type="text/javascript">
+var _gaq = _gaq || [];
+_gaq.push(['_setAccount', 'UA-25976949-1']);
+_gaq.push(['_trackPageview']);
+(function() {
+var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
+ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
+var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
+})();
+</script>
+
+</body>
+</html>