(Circle) Alarm Sample Overview

Wearable native

The (Circle) Alarm sample application demonstrates how you can create and manage several alarms, and save alarm data. The sample application introduces the flow of a common alarm application.

For information on creating the sample application project in the IDE, see Creating Sample Applications.

The following figure illustrates the main screens of the (Circle) Alarm.

Figure: (Circle) Alarm screens

Alarm screens

The application opens with the base view (top left in the above figure), if no alarms exist. Otherwise, the alarm list is shown (bottom left in the above figure).

To set an alarm:

  1. Click Add in the alarm list, or the alarm clock button in the middle of the base view.
  2. In the Set alarm view, turn the rotary on the device to set a specific time and click the check button at the bottom of the screen to save the alarm.

    The new alarm is shown in the alarm list.

The user can scroll up and down the alarm list, and activate and cancel the alarms using the check box. When an activated alarm reaches its time and goes off, the ringing alarm view is shown. To stop the alarm, click Dismiss.

Prerequisites

To ensure proper application execution, the following privileges must be set:

  • http://tizen.org/privilege/alarm.set

Source Files

You can create and view the sample application project including the source files in the IDE.

Table: Source files
File name Description
edje/images This file contains the image files used in the main.edc file.
inc/alarm.h This file contains information and definition of the variables and functions used in the C files, especially in the main.c file.
inc/data.h This file contains information and definition of the variables and functions used in the C files, especially in the data.c file.
inc/view.h This file contains information and definition of the variables and functions used in the C files, especially in the view.c file.
res/edje/main.edc This file is for the UI and contains style, image, and position of the sample application.
res/image This directory contains the image files used in the C files.
src/data.c This file contains the functions for retrieving and making data for the application.
src/main.c This file contains the functions related to the application life-cycle, callback functions, and view control.
src/view.c This file contains the functions for implementing the views and handling events.

Implementation

Application Layout

To create the basic application layout, use the view_create() function. The window and conformant components are essential parts of the application layout.

void 
view_create(void)
{
   // Create window 
   s_info.win = view_create_win(PACKAGE);
   if (s_info.win == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a window.");

      return;
   }

   // Create conformant 
   s_info.conform = view_create_conformant_without_indicator(s_info.win);
   if (s_info.conform == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a conformant");

      return;
   }

   // Show the window after the main view is set up 
   evas_object_show(s_info.win);
}

To manage multiple views efficiently (change between views, access view resources, and show effects), you need a naviframe component. To create the naviframe and a circular layout, use the view_alarm_create() function:

void 
view_alarm_create(void)
{
   // Create the naviframe
   s_info.nf = view_create_naviframe(s_info.conform);
   if (s_info.nf == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a naviframe.");
      evas_object_del(s_info.win);

      return;
   }

   // Create Eext circle surface for a circular genlist and datetime objects to show a circular layout
   s_info.circle_surface = eext_circle_surface_naviframe_add(s_info.nf);
}

Base View

The base view is shown when no alarms exist. To create the base view, use the _create_layout_no_alarmlist() function in the app_create() function.

layout = _create_layout_no_alarmlist(nf, edje_path, "base_alarm");

Figure: Base view frame

Base view frame

To fill out each part of the view, use the view_set_text() and view_set_button() functions:

  • To set the view title and additional text at the bottom of the screen, define the text in the third parameter of the view_set_text() function.

  • Create the button with the view_set_button() function.

    The button is transparent, and located below the no_alarm.img object that is set by the EDJ file. The focus style makes the button transparent. If the button requires its own image, the fourth parameter of the view_set_button() function can be used for that.

    To change the appearance of the button when it is pressed or released, customize the _no_alarm_down_cb() and _no_alarm_up_cb() callbacks. In this sample, the no_alarm.img and no_alarm.text parts are dimmed when the button is pressed, and return to normal when the button is released.

    To change the appearance of the button when it is clicked, customize the _no_alarm_clicked_cb() callback. In this sample, the Set alarm view is opened when the button is clicked.

view_set_text(layout, "no_alarm.title", "Alarm");
view_set_button(layout, "swallow.no_alarm.button", "focus", NULL, NULL,
                _no_alarm_down_cb, _no_alarm_up_cb, _no_alarm_clicked_cb, layout);
view_set_text(layout, "no_alarm.text", "Add alarm");

Set Alarm View

When the button on the base view (swallow.no_alarm.button part) is clicked, the _no_alarm_clicked_cb() callback is triggered and the Set alarm view opens.

Figure: Set alarm view

Set alarm view

static void 
_no_alarm_clicked_cb(void *data, Evas_Object *obj, void *event_info)
{
   Evas_Object *nf = NULL;
   Evas_Object *layout = NULL;

   // Add a set time layout to the naviframe
   nf = view_get_naviframe();

   layout = _create_layout_set_time(nf);
   if (layout == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a layout of setting time.");

      return;
   }

   view_push_item_to_naviframe(nf, layout, NULL, NULL);
}

To create the layout, use the _create_layout_set_time() function.

The Set alarm view layout uses a theme of the datetime style. When a layout uses a theme, it does not need an EDJ file, because it sets the edje group from the used elementary theme.

static Evas_Object*
_create_layout_set_time(Evas_Object *parent)
{
   Evas_Object *layout = NULL;
   char image_path[BUF_LEN] = {0, };

   if (!parent) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to get parent.");

      return NULL;
   }

   // Create a layout for setting time
   layout = view_create_layout_by_theme(parent, "layout", "circle", "datetime");

   // Set the title of the layout
   view_set_text(layout, "elm.text", "Set alarm");

   // Create the check button to set the alarm 
   data_get_resource_path("images/ic_popup_btn_check.png", image_path, sizeof(image_path));

   view_set_button(layout, "elm.swallow.btn", "bottom", image_path, NULL, NULL, NULL, _set_clicked_cb, NULL);

   // Create the date and time picker
   view_create_datetime(layout, "timepicker/circle");

   return layout;
}

The following figure shows the view frame created by the above code.

Figure: Set alarm view frame

Set alarm view frame

To fill out each part of the view:

  • Use the view_set_text() function to modify the elm.text part at the top of the layout.
  • Use the view_set_button() function to modify the elm.swallow.btn part to set the button.

    When the button is clicked, the _set_clicked_cb() callback is triggered.

List View

After an alarm has been set, the list view with all the existing alarms is shown.

Figure: List view

List view

To create the list view, use the _set_layout_exist_alarmlist() function in the app_create() function:

  • As in the base view, you can create a circular list view. This view inherits from the base view layout created using the _create_layout_no_alarmlist() function.
  • To create a circular genlist, use the view_create_circle_genlist() function.

    The genlist component is meant for more expansive lists than the simple list in Elementary, with flexible items and more entries while still being fast and low on memory usage. If you want a simple list with icons and a single text, use the normal List component.

  • To create a title for the genlist, use the view_append_item_to_genlist() function with title as the second parameter.
  • You can also create a padding item to fine-tune the list item location on the screen.

    Since the padding item is located at the end of the genlist, it ensures that the list items are located in the middle of the screen.

static void 
_set_layout_exist_alarmlist(Evas_Object *layout)
{
   Evas_Object *genlist = NULL;

   if (!layout) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to get layout.");

      return;
   }

   genlist = view_create_circle_genlist(layout);
   if (genlist == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a genlist of saving alarm.");

      return;
   }

   // Append a genlist item as a title
   view_append_item_to_genlist(genlist, "title", NULL, NULL, NULL);

   // Create a genlist item for padding
   s_info.padding_item = view_append_item_to_genlist(genlist, "padding", NULL, NULL, NULL);
   if (s_info.padding_item == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create padding item of genlist.");

      return;
   }

   view_set_content_to_part(layout, "swallow.genlist", genlist);

   view_set_button(layout, "swallow.genlist.button", "bottom", NULL, "Add",
         NULL, NULL, _add_clicked_cb, NULL);

   view_set_genlist(genlist);
}

The following figure shows the view frame created by the above code.

Figure: List view frame

List view frame

To fill out each part of the view:

  • To set the genlist as content in the swallow.genlist part, use the view_set_content_to_part() function. After calling this function, the genlist is set at the predefined location determined by the swallow.genlist part in the EDJ file.
  • Make a bottom style button in the swallow.genlist.button part to allow the user to add more alarms.

Ringing Alarm View

When a scheduled alarm goes off, the ringing alarm view appears.

Figure: Ringing alarm view

Ringing alarm view

To create the view, use the _create_layout_ring_alarm() function in the app_control() function.

static void 
_create_layout_ring_alarm(Evas_Object *parent, struct tm *saved_time)
{
   Evas_Object *layout = NULL;
   char buf[BUF_LEN] = {0, };
   char file_path[BUF_LEN] = {0, };

   if (parent == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to get parent.");

      return;
   }

   // Create a layout that shows when the alarm sounds
   data_get_resource_path("edje/main.edj", file_path, sizeof(file_path));

   layout = view_create_layout(parent, file_path, "ringing_alarm", NULL, NULL);
   if (layout == NULL) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to create a layout.");

      return;
   }

   // Set the scheduled time as text
   if (saved_time) 
   {
      strftime(buf, sizeof(buf) - 1, "%l:%M %p", saved_time);
      view_set_text(layout, "ringing_alarm.text", buf);
   }

   // Set the bottom style button to dismiss the alarm
   view_set_button(layout, "swallow.button", "bottom", NULL, "Dismiss",
         NULL, NULL, _dismiss_clicked_cb, NULL);

   view_push_item_to_naviframe(parent, layout, NULL, NULL);
}

The following figure shows the view frame created by the above code. The ringing_alarm is the name of the group in the EDJ file used to make the view.

Figure: Ringing alarm view frame

Ringing alarm view frame

Using an Application Control and Scheduling an Alarm

To schedule an alarm at the specified time, you need an app_control handle. Create the handle with the _create_app_control() function at the application startup when all data initializes:

s_info.app_control = _create_app_control(APP_CONTROL_OPERATION_ALARM_ONTIME, PACKAGE);

You can create the app_control handle with the App Control APIs:

  • The app_control handle is created using the app_control_create() function.
  • The operation (information for the launch request to be performed) is set using the app_control_set_operation() function.
static app_control_h 
_create_app_control(const char *operation, const char *app_id)
{
   app_control_h app_control;

   app_control_create(&app_control);
   app_control_set_operation(app_control, operation);
   // Package name is declared in the "main.h" file
   app_control_set_app_id(app_control, app_id);

   return app_control;
}

When you have your app_control handle, you can schedule alarms. When the user clicks the check button in the Set alarm view, call the alarm_schedule_at_date() function:

alarm_schedule_at_date(app_control, saved_time, 0, &alarm_id)

The app_control handle as the first parameter performs specific work when the alarm is triggered. The second parameter is the time that sounds the alarm for the first time. The third parameter is the amount of time between subsequent alarms. After scheduling an alarm, you can get the alarm ID that uniquely identifies the alarm.

Canceling an Alarm

When you want to cancel an alarm, use the alarm_cancel() function with the specific alarm ID:

alarm_cancel(alarm_id);

In this example, to cancel the alarm, the user must click the check box next to the alarm in the alarm list.

Figure: Activating and canceling an alarm

Activating and canceling an alarm

Creating a Bundle to Store Alarms

This application uses a bundle to manage the alarm IDs.

When the application data is initialized, the bundle is created using the data_create_bundle() function, which calls the bundle_create() function.

s_info.b = data_create_bundle();

To add an alarm ID (converted into a string type key-value) to the bundle, use the data_add_bundle_by_str() function to call the bundle_add_str() function and create the bundle object:

data_add_bundle_by_str(buf, buf);