From: Radek Kintop Date: Fri, 23 Oct 2015 08:25:21 +0000 (+0200) Subject: Documentation for wearable native circular Ambient analog watch sample. X-Git-Tag: tizen_3.0/TD_SYNC/20161201~347^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=58900ab20e39ddae5a95d69b775e0627b8df458e;p=sdk%2Fonline-doc.git Documentation for wearable native circular Ambient analog watch sample. Change-Id: I22629dd0139f6f2b4d342224cb45283038da2a0e Signed-off-by: Radek Kintop --- diff --git a/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn0.png b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn0.png new file mode 100644 index 0000000..cd02356 Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn0.png differ diff --git a/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn1.png b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn1.png new file mode 100644 index 0000000..39d3ebb Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn1.png differ diff --git a/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn2.png b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn2.png new file mode 100644 index 0000000..626ba45 Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn2.png differ diff --git a/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn4.png b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn4.png new file mode 100644 index 0000000..1a9b70a Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn4.png differ diff --git a/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn5.png b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn5.png new file mode 100644 index 0000000..7f571ca Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn5.png differ diff --git a/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn6.png b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn6.png new file mode 100644 index 0000000..7cc9993 Binary files /dev/null and b/org.tizen.sampledescriptions/html/images/circleambientanalogwatch_wn6.png differ diff --git a/org.tizen.sampledescriptions/html/wearable_n/circleambientanalogwatch_wn.htm b/org.tizen.sampledescriptions/html/wearable_n/circleambientanalogwatch_wn.htm new file mode 100644 index 0000000..ab3b01a --- /dev/null +++ b/org.tizen.sampledescriptions/html/wearable_n/circleambientanalogwatch_wn.htm @@ -0,0 +1,434 @@ + + + + + + + + + + + + + + The (Circle) Ambient Analog Watch Sample Overview + + + + +
+
+ +
+
+

Wearable native

+
+ +

(Circle) Ambient Analog Watch Sample Overview

+ +

The (Circle) Ambient Analog Watch sample application demonstrates how to implement a simple watch application with ambient mode support.

+ +

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.

+ +

Figure 1: (Circle) Ambient Analog Watch views

+

+ (Circle) Ambient Analog Watch views + (Circle) Ambient Analog Watch views + (Circle) Ambient Analog Watch views +

+ +

The current time is displayed as follows:

+
    +
  • red dot indicates seconds,
  • +
  • small blue dot indicates hours,
  • +
  • large blue dot indicates minutes.
  • +
+

Above the current date there are indicators for battery level and WiFi RSSI.

+

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.

+ +

Figure 2: (Circle) Ambient Analog Watch widgets structure

+

+ (Circle) Sensors widgets structure +

+

Prerequisites

+

To ensure proper application execution, the +http://tizen.org/privilege/network.get privilege must be set.

+ +

Implementation

+ +

Main module

+

The main() function of the sample application is show below. The application loop +is started when the watch_app_main() +function is invoked. An object of watch_app_lifecycle_callback_s type can be passed to it. +Notice how it differs from ui_app_lifecycle_callback_s typed used in the standard application type. +The watch_app_lifecycle_callback_s structure introduces three new callback pointers to: +

+
    +
  • watch_app_time_tick_cb - called every second when the application is in normal mode, giving the application a chance to refresh the time indicator,
  • +
  • watch_app_ambient_tick_cb - called every minute when the application is in ambient, giving the application a chance to refresh the time indicator,
  • +
  • watch_app_ambient_changed_cb - called whenever the application enters normal or ambient mode.
  • +
+ +
+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;
+}
+
+ +
+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);
+}
+
+ +
+static void app_ambient_changed(bool ambient_mode, void *data)
+{
+  controller_set_ambient_mode(ambient_mode);
+}
+
+ +
+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);
+}
+
+ +

Controller module

+

Three important functions of this module are presented below. The controller_start_application() +is called at the application's startup. It sets up the view and adds the +__wifi_rssi_level_changed_cb() +callback to monitor WiFi signal strength's changes. It also sets the current time on the watch view.

+ +
+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;
+}
+
+ +

The controller_set_ambient_mode() function is called from +app_ambient_changed() +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.

+ +
+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);
+  }
+}
+
+

Aside from updating the time and date indicators, the controller_tick() +function reads the battery level and sets up the battery display accordingly. It happens only in ambient mode. +The controller_tick() +is called with one second interval when the application is in normal mode +and with one minute interval when it is in ambient mode.

+ +
+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);
+  }
+}
+
+ +

Main view module

+ +

The watch_app_get_elm_win() +function is used to obtain a special watch type window. This way the application can receive ambient/normal mode switch events properly.

+

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.

+

The elm_layout widget has been chosen for this operation. +Once the indicators_layout pointer is obtained, it is possible to +call eext_circle_surface_layout_add() function and obtain a pointer +(indicators_layout_surface) to a +Eext_Circle_Surface object associated with this layout.

+

These two pointers can now be used to create circle objects - time indicators. The pointers are passed to the +__create_time_indicator() +function and from there to the circle_indicator_create() +function from circle indicator module.

+

Up to this point in view_create_gui() +function, this application would look like in Figure 3 (left).

+

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.

+

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).

+ +

Figure 3: Two circle indicators and the background

+

+ Two circle indicators and the background + Two circle indicators and the background +

+ + +
+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 ...
+}
+
+ +
+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;
+}
+
+ +

Each time a time tick occurs, the controller module calls view_set_time() +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 edje_object_message_send() function. +

+ +
+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);
+}
+
+ +

Once the message is received, it is processed by edje layout object's script function:

+ +
+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);
+    }
+  }
+}
+
+ +

Circle indicator view module

+ +

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.

+ +
+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;
+}
+
+ + + +
+ +Go to top + + + + + + + diff --git a/org.tizen.sampledescriptions/html/wearable_n/sd_wn.htm b/org.tizen.sampledescriptions/html/wearable_n/sd_wn.htm index 3736242..3ea839e 100644 --- a/org.tizen.sampledescriptions/html/wearable_n/sd_wn.htm +++ b/org.tizen.sampledescriptions/html/wearable_n/sd_wn.htm @@ -60,7 +60,11 @@ (Circle) Cairo EvasGL Demonstrates how you can implement the Cairo GL backend with the Evas_GL surface. - + + + (Circle) Ambient Analog Watch + Demonstrates how you can implement a simple watch application with ambient mode support. + (Circle) Email Demonstrates how you can implement a complex circular email view using EFL UI components and containers.