Badges Sample Overview

Mobile native

The Badge sample application demonstrates how you can handle application badges using the Badge API. You can create, modify, and delete badges displayed by any of the applications installed on a platform.

The following figure illustrates the application view.

Figure: Badge screen

Main view Main view with the target application selected

On the main screen, you can:

  • Browse a list of target applications and select a specific application for badge management

    All applications that can have a badge attached are displayed.

  • Manipulate badges

    You can create and remove badges, and update the badge counter of a selected application by altering the badge counter value.

The following figure illustrates the structure of the application user interface and components. EDJE layout scripts are used.

Figure: UI layout and component structure

UI layout structure UI component structure

The application workflow can be divided into 2 logical blocks: startup and application badge update. The following figure illustrates the workflow.

Figure: Application workflow

Application workflow - startup Application workflow - update

Prerequisites

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

  • http://tizen.org/privilege/packagemanager.info
  • http://tizen.org/privilege/notification

Implementation

Type Definitions

The main data structure is used as a container for the View and Model data:

typedef struct 
appdata
{
   // View module data
   viewdata_s viewdata; 
   
   // Model module data
   modeldata_s modeldata;  
} 
appdata_s;

The viewdata_s structure contains references to all the component objects created by the View module:

typedef struct 
_viewdata 
{
   // Main window component object
   Evas_Object* win;

   // Conformant component object                
   Evas_Object* conform;

   // Main window layout object (embedded into the conform component)
   Evas_Object* layout_main_panel;                 

   // Top panel layout object (embedded into the main_panel_badge_update_panel part of the layout_main_panel)
   Evas_Object* layout_badge_update_panel;   

   // Middle panel layout object (embedded into the main_panel_apps_list_panel part of the layout_main_panel)   
   Evas_Object* layout_available_apps_panel;

   // Bottom panel layout object (embedded into the main_panel_buttons_panel part of the layout_main_panel)
   Evas_Object* layout_buttons_panel;     

   // Spinner component object used for badge counter setting  
   Evas_Object* badge_counter_spinner;  
           
   // Genlist component object used for available applications listing
   Evas_Object* available_apps_list;    
      
   // Button component object used to confirm and apply the input data   
   Evas_Object* update_button;                    
} 
viewdata_s;
The modeldata_s contains a list of pkginfo_s items, where each pkginfo_s structure contains information about installed applications:
typedef struct 
_pkginfo 
{
   // Name of the application package
   char *pkg_name; 
   // Application ID
   char *app_id;   
} 
pkginfo_s;

typedef struct 
_modeldata 
{ 
   // List of pkginfo_s structures
   Eina_List *pkg_list;   
} 
modeldata_s;

Application Initialization

The entire application life-cycle is implemented in a badge.c file:

  • The sample uses a common Tizen application structure:
    int
    main(int argc, char *argv[])
    {
       appdata_s ad = {{0,},};
       // Declare and initialize variables
    
       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;
    
       // Assign event handlers 
    
       ret = ui_app_main(argc, argv, &event_callback, &ad);
       // Error handling
    
       return ret;
    }
    
  • The sample is implemented by using the MVC design pattern. Its initialization is done within the app_create() callback function.

    Within the callback, the user interface creation is triggered using the view_base_gui_create() function call, and the application data is initialized with the controller_application_init() function. For more information, see Controller and View.

    static bool
    app_create(void *data)
    {
       // Assign variables
    
       if (!view_base_gui_create(&ad->viewdata)) 
       {
          return false;
       }
    
       return controller_application_init(&ad->modeldata);
    }
    
  • When the application is terminated, the app_terminate() callback function frees all the allocated resources. For more information, see Controller.

    static void
    app_terminate(void *data)
    {
       appdata_s *ad = (appdata_s*)data;
    
       if (ad->viewdata.win) 
       {
          // Delete the main window and all descendants
          evas_object_del(ad->viewdata.win);              
       }
    
       // Free all allocated data
       controller_application_terminate(&ad->modeldata);       
    }
    

View

The entire application layout is implemented using EDJE scripts. All top level swallows are designed for EFL Elementary component embedding. The following EDJE swallow - EFL Elementary component relations and assigned functionalities are used (for more information, see the UI layout and component structure figure):

  • badge_update_panel_badge_counter_edit - elm_spinner: sets the new value of the badge counter for the selected application.
  • apps_list_panel_list - elm_genlist: list of all installed and displayable applications, consisting of the application identifier and the badge counter.
  • buttons_panel_button - elm_button: applies all the changes.

The following table defines the code snippets that create the UI layout.

Table: UI layout code snippets and figures
Code snippet Figure
The main layout is defined in the main.edc file:
collections 
{
   group 
   {
      name: GROUP_MAIN;

      parts 
      {
         // Background part occupies the entire window
         part 
         {
            name: PART_MAIN_BACKGROUND;
            type: RECT;
         }

         // Part is positioned in relation to PART_MAIN_BACKGROUND
         // Spacer occupies the entire area of PART_MAIN_BACKGROUND 
         // with a small margin all around
         part 
         {
            name: PART_MAIN_PANEL;
            type: SPACER;
         }

         // Part is positioned in relation to PART_MAIN_PANEL
         // Swallow occupies 30% of PART_MAIN_PANEL height
         // It is designed to hold the layout_badge_update_panel elm_layout
         part 
         {
            name: PART_MAIN_PANEL_BADGE_UPDATE_PANEL;
            type: SWALLOW;
         }

         // Part is positioned in relation to PART_MAIN_PANEL
         // Swallow has flexible height which depends on the height 
         // of other swallows
         // At this configuration, the swallow occupies 55% of PART_MAIN_PANEL 
         // height
         // It is designed to hold the layout_available_apps_panel elm_layout
         part 
         {
            name: PART_MAIN_PANEL_APPS_LIST_PANEL;
            type: SWALLOW;
         }

         // Part is positioned in relation to PART_MAIN_PANEL
         // Swallow occupies 15% of PART_MAIN_PANEL height
         // It is designed to hold the layout_buttons_panel elm_layout
         part 
         {
            name: PART_MAIN_PANEL_BUTTON_PANEL;
            type: SWALLOW;
         }
      }
   }
}

The main view of the application

The PART_MAIN_PANEL_BADGE_UPDATE_PANEL swallow is used as a container for the update layout defined in the badge-update-panel.edc file:

collections 
{
   group 
   {
      name: GROUP_BADGE_UPDATE_PANEL;

      parts 
      {
         // Part is positioned in relation to PART_MAIN_PANEL_BADGE_UPDATE_PANEL 
         // from badge.edc file
         // rect plays a role of the background for the update panel and 
         // occupies the entire area
         // of the PART_MAIN_PANEL_BADGE_UPDATE_PANEL
         part 
         {
            name: PART_BADGE_UPDATE_PANEL_BACKGROUND;
            type: RECT;
         }

         // Part is positioned in relation to PART_BADGE_UPDATE_PANEL_BACKGROUND
         // Text part occupies 50% height and 30% width of the 
         // PART_BADGE_UPDATE_PANEL_BACKGROUND
         // This part is responsible for static text label display only ("App name")
         part 
         {
            name: "badge_update_panel_app_name_caption";
            type: TEXT;
         }

         // Part is positioned in relation to PART_BADGE_UPDATE_PANEL_BACKGROUND
         // Text part occupies 50% height and 70% width of the 
         // PART_BADGE_UPDATE_PANEL_BACKGROUND
         // This part is responsible for text display which content is triggered 
         // by programs defined at the end of this file: "selected_app_name_show" 
         // and "selected_app_name_hide"
         part 
         {
            name: PART_BADGE_UPDATE_PANEL_APP_NAME;
            type: TEXT;
            description
            {
               state: STATE_BADGE_UPDATE_PANEL_APP_NAME_DEFAULT 0.0;
               // State is triggered by the "selected_app_name_show" program
            }
            description
            {
               state: STATE_BADGE_UPDATE_PANEL_APP_NAME_SELECTED 0.0;
               // State is triggered by the "selected_app_name_hide" program
            }
         }

         // Part is positioned in relation to PART_BADGE_UPDATE_PANEL_BACKGROUND
         // Text part occupies 50% height and 40% width of the 
         // PART_BADGE_UPDATE_PANEL_BACKGROUND
         // This part is responsible for static text label display only ("Badge counter")
         part 
         {
            name: "badge_update_panel_badge_counter_caption";
            type: TEXT;
         }

         // Part is positioned in relation to PART_BADGE_UPDATE_PANEL_BACKGROUND
         // rect plays a role of a background for the elm_spinner component
         // Its width is set to 60% of PART_BADGE_UPDATE_PANEL_BACKGROUND width
         // Height is set to 38% of the PART_PREF_EDIT_PANEL_KEY_PANEL height 
         // and it is vertically centered
         part 
         {
            name: PART_BADGE_UPDATE_PANEL_BADGE_COUNTER_BACKGROUND;
            type: RECT;
         }

         // Part is positioned in relation to 
         // PART_BADGE_UPDATE_PANEL_BADGE_COUNTER_BACKGROUND
         // Swallow occupies entire height of the 
         // PART_BADGE_UPDATE_PANEL_BADGE_COUNTER_BACKGROUND
         // part and 100% of its width
         part 
         {
            name: PART_BADGE_UPDATE_PANEL_BADGE_COUNTER_EDIT;
            type: SWALLOW;
         }
      }

      // Programs below are used to control the text content of the 
      // PART_BADGE_UPDATE_PANEL_APP_NAME part
      programs 
      {
         // "selected_app_name_show" program is triggered by 
         // sending the SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_SHOW
         // signal to the elm_layout embedded into the layout_badge_update_panel
         // As a result of the program execution, the text content of the 
         // PART_BADGE_UPDATE_PANEL_APP_NAME is changed to the "Select an application ..."
         // Text is displayed in red color
         program 
         {
            name: "selected_app_name_show";
            signal: SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_SHOW;

            // Part affected
            source: PART_BADGE_UPDATE_PANEL_APP_NAME;          
  
            // Part's state to be triggered          
            action: STATE_SET STATE_BADGE_UPDATE_PANEL_APP_NAME_SELECTED 0.0;

            // Part affected
            target: PART_BADGE_UPDATE_PANEL_APP_NAME;                        
         }
         // "selected_app_name_hide" program is triggered by 
         // sending the SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_HIDE
         // signal to the same elm_layout as above. As a result of the program 
         // execution, the text content of the PART_BADGE_UPDATE_PANEL_APP_NAME 
         // is changed to the currently selected application identifier
         // Text is displayed in green color
         program 
         {
            name: "selected_app_name_hide";
            signal: SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_HIDE;

            // Part affected
            source: PART_BADGE_UPDATE_PANEL_APP_NAME;                     
            // Part's state to be triggered  
            action: STATE_SET STATE_BADGE_UPDATE_PANEL_APP_NAME_UNSELECTED 0.0;
            // Part affected
            target: PART_BADGE_UPDATE_PANEL_APP_NAME;                        
         }
      }
   }
}

The update part of the main view of the application

The PART_MAIN_PANEL_APPS_LIST_PANEL swallow is used as a container for the application list layout defined in the apps-list-panel.edc file:

collections 
{
   group 
   {
      name: GROUP_APPS_LIST_PANEL;

      parts 
      {
         // Part is positioned in relation to 
         // PART_MAIN_PANEL_APPS_LIST_PANEL from badge.edc file
         // rect plays a role of the background for the
         // applications list panel and occupies the entire area of 
         // the PART_MAIN_PANEL_APPS_LIST_PANEL
         part 
         {
            name: PART_APPS_LIST_PANEL_BACKGROUND;
            type: RECT;
         }

         // Part is positioned in relation to 
         // PART_APPS_LIST_PANEL_BACKGROUND
         // Text part occupies 10% height and the entire 
         // width of the PART_APPS_LIST_PANEL_BACKGROUND
         // This part is responsible for static text label 
         // display only ("Available applications")
         part 
         {
            name: "apps_list_panel_available_apps_caption";
            type: TEXT;
         }

         // Part is positioned in relation to 
         // PART_APPS_LIST_PANEL_BACKGROUND
         // Swallow occupies 90% height of the 
         // PART_APPS_LIST_PANEL_BACKGROUND part and its entire width
         part
         {
            name: PART_APPS_LIST_PANEL_LIST;
            type: SWALLOW;
         }
      }
   }
}

The list part of the main view of the application

The PART_MAIN_PANEL_BUTTONS_PANEL swallow is used as a container for the action button layout defined in the buttons-panel.edc file:

collections 
{
   group 
   {
      name: GROUP_BUTTONS_PANEL;

      parts 
      {
         // Part is positioned in relation to 
         // PART_MAIN_PANEL_BUTTONS_PANEL from badge.edc file
         // rect plays a role of the background for the 
         // buttons panel and occupies the entire area of the 
         // PART_MAIN_PANEL_BUTTONS_PANEL
         part 
         {
            name: PART_BUTTONS_PANEL_BACKGROUND;
            type: RECT;
         }

         // Part is positioned in relation to 
         // PART_BUTTONS_PANEL_BACKGROUND
         // Swallow occupies 60% height and 60% width of the 
         // PART_BUTTONS_PANEL_BACKGROUND part
         // Swallow is horizontally and vertically centered
         part 
         {
            name: PART_BUTTONS_PANEL_BUTTON;
            type: SWALLOW;
         }
      }
   }
}

The buttons part of the main view of the application

Based on the layout defined with the EDJE scripts, the application interface is created with the view_base_gui_create() function (see Application Initialization), which takes one parameter - a pointer to the structure containing view data (viewdata_s - see Type Definitions). In succeeding calls to the view_*_panel_create() functions, the user interface is created.

bool
view_base_gui_create(viewdata_s *vd)
{
   viewdata = vd;

   if (!view_main_panel_create(vd) ||
       !view_update_panel_create(vd) ||
       !view_available_apps_panel_create(vd) ||
       !view_buttons_panel_create(vd)) 
   {
      evas_object_del(vd->win);

      return false;
   }
 
   evas_object_show(vd->win);

   return true;
}

The following table defines the base view creation details.

Table: Base view creation code snippets and figures
Description Code snippet Figure

view_main_panel_create():

The main window and descendant conformant are created (vd->win and vd->conform respectively) and used as a placeholder for the main layout (vd->layout_main_panel).

The main layout is created with the view_layout_create() function by loading the main group from the EDJE layout (badge.edj file). It is embedded into the vd->layout_main_panel container.

Finally, the view_layout_back_cb() callback function is attached to the vd->layout_main_panel layout for the back button handling.

static bool
view_main_panel_create(viewdata_s *vd)
{
   vd->win = view_window_create();
   // Error handling

   vd->conform = view_conformant_create(vd->win);
   // Error handling

   vd->layout_main_panel = view_layout_create(vd->conform, EDJ_MAIN_FILE_NAME, 
                                              GROUP_MAIN, NULL);
   // Error handling
   eext_object_event_callback_add(vd->layout_main_panel, EEXT_CALLBACK_BACK, 
                                  view_layout_back_cb, void*)vd);

   return true;
}

The application main view

view_update_panel_create():

The update subview is created by loading the GROUP_BADGE_UPDATE_PANEL group from the EDJE layout (the badge-update-panel.edc file). It is embedded in the elm_layout container which is then inserted into the PART_MAIN_PANEL_BADGE_UPDATE_PANEL swallow of the vd->layout_main_panel.

Finally, the elm_spinner component is created for setting the badge counter value.

static bool
view_update_panel_create(viewdata_s *vd)
{
   vd->layout_badge_update_panel = view_layout_create(vd->layout_main_panel,
                                                      EDJ_BADGE_UPDATE_PANEL_FILE_NAME,
                                                      GROUP_BADGE_UPDATE_PANEL,
                                                      PART_MAIN_PANEL_BADGE_UPDATE_PANEL);
   // Error handling

   vd->badge_counter_spinner = view_spinner_create(vd->layout_badge_update_panel);
   // Error handling

   return true;
}

The application main view with update panel

view_available_apps_panel_create():

The available application subview is created by loading the GROUP_APPS_LIST_PANEL group from the EDJE layout (the apps-list-panel.edc file). It is embedded to the elm_layout container which is then inserted into the PART_MAIN_PANEL_APPS_LIST_PANEL swallow of the vd->layout_main_panel.

Once the vd->layout_available_apps_panel layout is ready, the elm_genlist component is created (vd->available_apps_list) for the available application list display. 2 callback functions are assigned to the vd->available_apps_list component:

  • view_available_apps_item_selected_cb() for item selected action
  • view_available_apps_item_unselected_cb() for item unselected action
static bool
view_available_apps_panel_create(viewdata_s *vd)
{
   vd->layout_available_apps_panel = view_layout_create(vd->layout_main_panel,
                                                        EDJ_APPS_LIST_PANEL_FILE_NAME,
                                                        GROUP_APPS_LIST_PANEL,
                                                        PART_MAIN_PANEL_APPS_LIST_PANEL);
   // Error handling

   vd->available_apps_list = view_genlist_create(vd->layout_available_apps_panel,
                                                 PART_APPS_LIST_PANEL_LIST);
   // Error handling

   evas_object_smart_callback_add(vd->available_apps_list,
                                 "selected",
                                 view_available_apps_item_selected_cb,
                                 (void*)vd);
   evas_object_smart_callback_add(vd->available_apps_list,
                                  "unselected",
                                  view_available_apps_item_unselected_cb,
                                  (void*)vd);

   return true;
}

The application main view with application list panel

view_buttons_panel_create():

The action button subview is created by loading the GROUP_BUTTONS_PANEL group from the EDJE layout (the buttons-panel.edc file). It is embedded in the elm_layout container which is then inserted into the PART_MAIN_PANEL_APPS_LIST_PANEL swallow of the vd->layout_main_panel.

Once the vd->layout_buttons_panel layout is ready, the elm_button component is created (vd->update_button) for triggering the update action. A callback function which is responsible for introducing the changes to the application is connected to the vd->update_button component.

static bool
view_buttons_panel_create(viewdata_s *vd)
{
   vd->layout_buttons_panel = view_layout_create(vd->layout_main_panel,
                                                 EDJ_BUTTONS_PANEL_FILE_NAME,
                                                 GROUP_BUTTONS_PANEL,
                                                 PART_MAIN_PANEL_BUTTON_PANEL);
   // Error handling

   vd->update_button = view_button_create(vd->layout_buttons_panel,
                                          PART_BUTTONS_PANEL_BUTTON,
                                          "Update",
                                          view_badge_update_button_click_cb,
                                          (void*)vd);
   // Error handling

   return true;
}

The complete application main view

Items are added to the elm_genlist component on application initialization using the view_genlist_item_add() function. This function takes only 1 parameter of the pointer to the pkginfo_s structure type (for type specification, see Type Definitions). It contains the application identifier and the related package name, which is further passed to the elm_genlist_item_append() function for display purposes. Finally, the elm_genlist item text content is acquired and displayed with the view_genlist_item_label_get() function.

bool
view_genlist_item_add(pkginfo_s *pkginfo)
{
   static Elm_Genlist_Item_Class *itc = NULL;

   // Error handling

   if (!itc) 
   {
      itc = elm_genlist_item_class_new();
      // Error handling

      itc->item_style = "double_label";
      itc->func.text_get = view_genlist_item_label_get;
      // NULL value assignment to unused itc fields
   }

   Elm_Object_Item *item = elm_genlist_item_append(viewdata->available_apps_list, itc, (void*)pkginfo, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
   // Error handling

   // Data is assigned to the newly created genlist item
   elm_object_item_data_set(item, (void*)pkginfo);

   return true;
}

static char*
view_genlist_item_label_get(void *data, Evas_Object *obj, const char *part)
{
   pkginfo_s *pkginfo = (pkginfo_s*)data;

   // Error handling

   // 2 text buffers are populated (buff_main and buff_sub) with string content based on the pkginfo:
   //    - buff_main - the application's package name
   //    - buff_sub - the application's badge counter which is obtained with controller_badge_count_get() function

   if (!strcmp(part, "elm.text")) 
   {
      return strdup(pkginfo->pkg_name);
   } 
   else if (!strcmp(part, "elm.text.sub")) 
   {
      unsigned int badge_count = controller_badge_count_get(pkginfo->app_id);
      char buff[255] = {0,};

      snprintf(buff, sizeof(buff), "Badge count = %u", badge_count);

      return strdup(buff);
   }

   return NULL;
}

Each item added to the elm_genlist component supports the selected and unselected actions, which are used to display the selected application package name in the EDJE text container of the vd->layout_badge_update_panel defined in the badge-update-panel.edc file:

  • The selected action is handled by the view_available_apps_item_selected_cb() callback function:

    static void
    view_available_apps_item_selected_cb(void *data, Evas_Object *obj, void *event_info)
    {
       viewdata_s *vd = (viewdata_s*)data;
    
       // Get the selected item's reference
       item_selected = (Elm_Object_Item*)event_info;
       // Error handling
       // Get the pkginfo_s data assigned to the selected item
       pkginfo_s *pkginfo = (pkginfo_s*)elm_object_item_data_get(item_selected);
       // Error handling
    
       // Get the badge counter assigned to the selected application
       unsigned int badge_count = controller_badge_count_get(pkginfo->app_id);
       // Obtained badge counter value is set to the vd->badge_counter_spinner component
       // for future manipulation
       elm_spinner_value_set(vd->badge_counter_spinner, (double)badge_count);
       // Selected item is updated
       elm_genlist_item_update(item_selected);
       // Send the SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_SHOW signal in order to display
       // the selected application's package name in the PART_BADGE_UPDATE_PANEL_APP_NAME
       // part of the vd->layout_badge_update_panel layout with predefined color
       elm_object_signal_emit(vd->layout_badge_update_panel,
                              SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_SHOW,
                              PART_BADGE_UPDATE_PANEL_APP_NAME);
       // Application's package name is assigned to the PART_BADGE_UPDATE_PANEL_APP_NAME
       // part of the viewdata->layout_badge_update_panel layout
       elm_object_part_text_set(viewdata->layout_badge_update_panel,
                                PART_BADGE_UPDATE_PANEL_APP_NAME,
                                pkginfo->app_id);
    }
    
  • The unselected action is handled by the view_available_apps_item_unselected_cb() callback function:

    static void
    view_available_apps_item_unselected_cb(void *data, Evas_Object *obj, void *event_info)
    {
       viewdata_s *vd = (viewdata_s*)data;
    
       // Send the SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_HIDE signal in order to display
       // the default text in the PART_BADGE_UPDATE_PANEL_APP_NAME part of the
       // vd->layout_badge_update_panel layout with predefined color
       elm_object_signal_emit(vd->layout_badge_update_panel,
                              SIGNAL_BADGE_UPDATE_PANEL_APP_NAME_HIDE,
                              PART_BADGE_UPDATE_PANEL_APP_NAME);
       // Default text is assigned to the PART_BADGE_UPDATE_PANEL_APP_NAME
       // part of the viewdata->layout_badge_update_panel layout
       elm_object_part_text_set(viewdata->layout_badge_update_panel,
                                PART_BADGE_UPDATE_PANEL_APP_NAME,
                                TEXT_LABEL_BADGE_UPDATE_PANEL_APP_NAME_DEFAULT);
    
       // Current selection reference is cleared
       item_selected = NULL;
    }
    

The badge implementation is triggered by the Update button click. The view_badge_update_button_click_cb() callback function, assigned to the Update button, is invoked:

static void
view_badge_update_button_click_cb(void *data, Evas_Object *obj, void *event_info)
{
   viewdata_s *vd = (viewdata_s*)data;

   // Check whether any item was selected. The item_selected variable is declared
   // statically in global scope. The valid value of item_selected variable
   // is assigned in view_available_apps_item_selected_cb() callback function.
   if (!item_selected) 
   {
      return;
   }

   // Get the pkginfo_s data assigned to the selected item
    pkginfo_s *pkginfo = (pkginfo_s*)elm_object_item_data_get(item_selected);
   // Error handling

   // Get the badge counter assigned to the selected application
   unsigned int curr_badge_count = controller_badge_count_get(pkginfo->app_id);
   // Get the value of badge counter adjusted via the elm_spinner component
   int new_badge_count = (int)elm_spinner_value_get(vd->badge_counter_spinner);

   // If the adjusted badge counter value is equal to the badge counter value
   // currently assigned to the selected application, nothing happens
   if (curr_badge_count == new_badge_count) 
   {
      return;
   } 
   else
   // If the adjusted badge counter value is not equal to the badge counter value
   // currently assigned to the selected application, which is equal to zero,
   // new badge for the selected application is created
   if (curr_badge_count == 0) 
   {
      controller_badge_new(pkginfo->app_id, new_badge_count);
   } 
   else
   // If the adjusted badge counter value equals zero and the badge counter
   // value currently assigned to the selected application is greater then zero,
   // existing badge is removed
   if (new_badge_count == 0) 
   {
      controller_badge_remove(pkginfo->app_id);
   } 
   else 
   {
      // Otherwise, the badge counter assigned to the selected application
      // is updated
      controller_badge_update(pkginfo->app_id, new_badge_count);
   }

   // Selected item is updated
   elm_genlist_item_update(item_selected);
}

Controller

The controller module controls the application processes:

  • During the application initialization process, the controller provides the controller_application_init() function. The function acquires the application package list for the badge control using the model_packages_list_get() function, and adds the applications to the list view using the view_genlist_item_add() function. For more information, see Model and View.
    bool
    controller_application_init(modeldata_s *md)
    {
       if (!model_packages_list_get(&md->pkg_list)) 
       {
          return false;
       }
    
       // Declare variables
    
       EINA_LIST_FOREACH(md->pkg_list, it, pkginfo) 
       {
          view_genlist_item_add(pkginfo);
       }
    
       return true;
    }
    
  • While the application is running, the controller provides functions for controlling the badge management process. Each of the following functions requires the application ID to be provided as an input parameter to identify the target application whose badge is to be handled. Additionally, for the badge creation and update functions, the new badge counter value is required.

    • controller_badge_count_get()

      Obtains the badge number currently pinned to the selected application.

      unsigned int
      controller_badge_count_get(const char *app_id)
      {
         // Variable declaration
      
         if (!model_badge_count_get(app_id, &badge_count)) 
         {	
            // Query the badge counter value
      
            return 0;
         }
      
         // Log message
      
         return badge_count;
      }
      
    • controller_badge_new()

      Creates a new badge for the selected application.

      bool
      controller_badge_new(const char *app_id, unsigned int badge_count)
      {
         if (!model_badge_add(app_id)) 
         { 
            return false;
         }
      
         if (!model_badge_display_set(app_id, 1)) 
         {      
            // Request badge visibility
      
            return false;
         }
      
         // Request the badge counter initialization with provided badge_counter value
         return model_badge_count_set(app_id, badge_count);	
      }
      
    • controller_badge_remove()

      Removes the badge which is already pinned to the selected application.

      bool
      controller_badge_remove(const char *app_id)
      {
         if (!model_badge_count_set(app_id, 0)) 
         {	
            // Request to clear the badge counter
      
            return false;
         }
      
         if (!model_badge_display_set(app_id, 0)) 
         {	
            // Request the badge invisibility
      
            return false;
         }
      
         // Request badge deletion
         return model_badge_remove(app_id);
      }  
      
    • controller_badge_update()

      Updates the badge counter pinned to the selected application.

      bool
      controller_badge_update(const char *app_id, unsigned int badge_count)
      {
         bool display = false;
      
         if (!model_badge_display_get(app_id, &display)) 
         {	
            // Query the visibility state of the badge
      
            return false;
         }
      
         if (!display) 
         {
            // Only the visible badges are updated
      
            return false;
         }
      
         // Request badge counter update
         return model_badge_count_set(app_id, badge_count);	
      }
      
  • During the application termination process, the controller provides the controller_application_terminate() function. The function releases all the previously allocated memory (list of pkginfo_s structures). For more information, see Application Initialization and Model.

    void
    controller_application_terminate(modeldata_s *md)
    {
       model_packages_list_free(md->pkg_list);
    }
    

Model

The model module deals directly with the application data. It is responsible for:

  • Package names and related application identifier acquisition
  • Badge creation, counter alteration, and badge removal

To perform the above operations, the Application Manager and Badge API are used:

  • During the application initialization, the model_packages_list_get() function is used to obtain the list of valid application identifiers and related package names (for more information, see Application Initialization and Controller). The function invokes the app_manager_foreach_app_info() function with the model_app_info_cb() callback passed as a parameter in order to retrieve information about the installed applications. The application and package information is obtained with subsequent calls to the callback function.

    bool
    model_packages_list_get(Eina_List **list)
    {
       *list = NULL;
    
       int ret = app_manager_foreach_app_info(model_app_info_cb, (void*)list);
       // Error handling
    
       return true;
    }
    
    static bool
    model_app_info_cb(app_info_h app_info, void *user_data)
    {
       Eina_List **list = (Eina_List**)user_data;
    
       char *pkg_name = NULL;
       // Get the application package name
       int ret = app_info_get_package(app_info, amp;pkg_name);    
       // Error handling
    
       bool nodisplay = true;
       // Get the application display flag
       ret = app_info_is_nodisplay(app_info, &nodisplay);      
       // Error handling
    
       if (nodisplay)
       // Return, if the application is non-displayable
       {                                        
          free(pkg_name);
    
          return true;
       }
    
       char *app_id = NULL;
       // Get the application identifier
       ret = app_info_get_app_id(app_info, &app_id);           
       // Error handling
    
       // If the application is displayable and all the required information is retrieved successfully
       // (the package name and the application identifier), the pkginfo_s structure is created
       // and added to the list
       pkginfo_s *pkginfo = NULL;
       if (model_info_create(pkg_name, app_id, &pkginfo)) 
       {
          *list = eina_list_append(*list, (void*)pkginfo);
       }
    
       free(pkg_name);
    
       // Continue the foreach loop to retrieve application information
       return true;    
    }
    
  • While the application is running, the model module provides a set of wrapper functions for the Badge API. The Controller module calls these functions to:

    • Create and remove a badge.
    • Get and set the badge display flag.
    • Get and set the badge counter.
    • Check whether the badge exists.

    Each of the following functions require the application ID to be provided as an input parameter. The ID is used to identify the target application whose badge is to be handled. All the functions (except those used for badge creation, removal, and existence check) require an additional parameter for setting or getting a value (display flag or badge counter).

    bool
    model_badge_remove(const char *app_id)
    {
       int ret = badge_remove(app_id);
       // Error handling
    
       return true;
    }
    
    bool
    model_badge_display_get(const char *app_id, bool *display)
    {
       unsigned int is_display = 0;
    
       // By default, the false value is returned
       *display = (bool)is_display;    
    
       int ret = badge_get_display(app_id, &is_display);
       // Error handling
    
       *display = (bool)is_display;
    
       return true;
    }
    
    bool
    model_badge_display_set(const char *app_id, bool display)
    {
       unsigned int display_val = 0;
    
       if (display) 
       {
          display_val = 1;
       }
    
       int ret = badge_set_display(app_id, display_val);
       // Error handling
    
       return true;
    }
    
    bool
    model_badge_count_get(const char *app_id, unsigned int *badge_count)
    {
       int ret = badge_get_count(app_id, badge_count);
       // Error handling
    
       return true;
    }
    
    bool
    model_badge_count_set(const char *app_id, unsigned int badge_count)
    {
       int ret = badge_set_count(app_id, badge_count);
       // Error handling
    
       return true;
    }
    
  • During the application termination, the model_packages_list_free() function is used to release the memory allocated in the Application Initialization step. For more information on the controller_application_terminate() function implementation, see Controller.

    void
    model_packages_list_free(Eina_List *list)
    {
       // Variable declaration
    
       // List consists of pkginfo_s structures; the loop below results in
       // pkginfo->pkg_name, pkginfo->app_id and pkginfo deallocation
       EINA_LIST_FOREACH(list, it, pkginfo) 
       {
          free(pkginfo->pkg_name);
          free(pkginfo->app_id);
          free(pkginfo);
       }
    
       list = eina_list_free(list);
    }