Skip to content

andrewroycarter/SimpleMenuLayerTutorial

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Image SimpleMenuLayerTutorial

A tutorial on using SimpleMenuLayer in the Pebble SDK

Let's Go!

First thing you want to do is install the Pebble SDK. I like to use Vagrant to do my Pebble development. You can find a nice setup for that here! I'm going to make the assumption that you've used the pathing and naming that the install guide reccomends. If not you'll have to alter any file paths that don't match.

Creating the project

cd into the directory you would like to create the project, and run ~/pebble-dev/PebbleSDK-1.12/Pebble/tools/create_pebble_project.py ~/pebble-dev/PebbleSDK-1.12/Pebble/sdk SimpleMenuLayerTutorial to create the folder SimpleMenuLayerTutorial which will contain the boilerplate for our app. cd into this directory, and run ./waf configure to get everything setup. Then run ./waf build to ensure that everything is building ok. If you're unable to successfuly build the app, go back through the SDK setup guide to ensure that everything is right.

Code it up

You'll notice that a few directories and files have been created for us by running that python script above. You can read a little about what's been generated here. The only file we'll need to work with for this tutorial is src/SimpleMenuLayerTutorial.c. Go ahead and open that up in your text editor of choice.

Let's go ahead and alter the PBL_APP_INFO bit to give the app a new name.

PBL_APP_INFO(MY_UUID,
             "My App", "My Company",
             1, 0, /* App version */
             DEFAULT_MENU_ICON,
             APP_INFO_STANDARD_APP);

The Pebble SDK doesn't allow dynamic memory allocation, so let's go ahead and get all of our variables in place that we'll need for our app. Add the following below Window window.

static SimpleMenuLayer s_simple_menu_layer;
static SimpleMenuItem s_fruit_menu_items[4];
static SimpleMenuItem s_animal_menu_items[4];
static SimpleMenuSection s_menu_sections[2];
static char *s_fruit_names[4] = {"Apple", "Banana", "Grape", "Pear"};
static char *s_animal_names[4] = {"Cat", "Dog", "Horse", "Fish"};

Our app is going to display a list of fruits and animals, seperated into two titled sections. s_simple_menu_layer will be used to hold our SimpleMenuLayer, s_fruit_menu_items and s_animal_menu_items will hold each item in our menu. s_menu_sections will contain both the fruit and animal sections. s_fruit_names and s_animal_names will contain the names of all of our items.

Below this block of code, add the following function prototypes

void setup_window();
void window_load();
void setup_menu_items();
void setup_menu_sections();

in setup_window we'll configure the app's window. window_load will be a callback that is called when the window loads. This is where we'll setup and add s_simple_menu_layer. setup_menu_items and setup_menu_sections will be used to setup our item and section variables.

Let's change the handle_init function to look like this

void handle_init(AppContextRef ctx) 
{
  setup_menu_items();
  setup_menu_sections();
  setup_window();
  window_stack_push(&window, true /* Animated */);
}

When the application init's we'll go ahead and setup all of our items and sections, setup our window, and finally push our window to the stack. In the Pebble SDK, you push and pop windows onto a window stack that feels very similar to UINavigationController in the iOS SDK.

Let's go ahead and code up setup_window

void setup_window()
{
  window_init(&window, "Window Name");
  window_set_window_handlers(&window, (WindowHandlers){
    .load = window_load
    });
}

Here we init the window, and set the window's handlers. There are handlers for a few events on the window (load / unload / appear / etc) but the only one we need to worry about is load.

Now we can implement setup_menu_items and setup_menu_secctions.

void setup_menu_items()
{
  for (int i = 0; i < (int)(sizeof(s_fruit_names) / sizeof(s_fruit_names[0])); i++)
  {
    s_fruit_menu_items[i] = (SimpleMenuItem){
      .title = s_fruit_names[i],
    };
  }

  for (int i = 0; i < (int)(sizeof(s_animal_names) / sizeof(s_animal_names[0])); i++)
  {
    s_animal_menu_items[i] = (SimpleMenuItem)
    {
      .title = s_animal_names[i],
    };
  }
}

void setup_menu_sections()
{
  s_menu_sections[0] = (SimpleMenuSection)
  {
    .title = "Fruits",
    .items = s_fruit_menu_items,
    .num_items = sizeof(s_fruit_menu_items) / sizeof(s_fruit_menu_items[0])
  };

  s_menu_sections[1] = (SimpleMenuSection)
  {
    .title = "Animals",
    .items = s_animal_menu_items,
    .num_items = sizeof(s_animal_menu_items) / sizeof(s_animal_menu_items[0])
  };
}

This is pretty straight forward. Our SimpleMenuLayer is going to want an array of SimpleMenuSection to display. SimpleMenuSection needs to have a title, items (SimpleMenuItem), and a count of the number of items. SimpleMenuItem in our case just has a title. You can also add an icon, subtitle, and callback (function to call when the item is selected) to SimpleMenuItem, but we're not going to worry about that in this demo.

The last thing we need to do is implement our window_load function.

void window_load(Window *window)
{
  Layer *root_layer = window_get_root_layer(window);
  simple_menu_layer_init(&s_simple_menu_layer,
                         layer_get_bounds(root_layer),
                         window,
                         s_menu_sections,
                         sizeof(s_menu_sections) / sizeof(s_menu_sections[0]),
                         NULL
  );
  layer_add_child(root_layer, (Layer *)&s_simple_menu_layer);
}

Here we grab the window's root layer (which we know is ready to go because the window has loaded). We use this during simple_menu_layer_init to properly size or SimpleMenuLayer, We also pass in the window that will contain our SimpleMenuLayer, our sections that we've setup (s_menu_sections), the number of sections, and NULL for the callback context (because we're not using that).

Now we should be ready to build and test our app! If you want to make sure everything is coded properly you can compare against the completed version here

In order to build the app, run ./waf build from within the project directory. Assuming everything compiles ok (again check the above file for reference) we can go ahead and put it on the watch. To do this, we need to http serve our project directory so we can use the iOS and Android Pebble app to install our app. From the project directory run python -m SimpleHTTPServer . This is an easy way to serve a directory! Now visit the website we're serving from your phone (if your IP address was 192.168.1.1 the address would be http://192.168.1.1:8000 and navigate to /build/SimpleMenuLayerTutorial.pbw. Now you should be able to install the application on your watch!

If I've missed anything, or you're having any trouble, please file an issue or pull request. I'm not the best writer in the world, and this is the first development writeup I've ever done, so any contributions or criticism is more than welcome!

About

A tutorial on using SimpleMenuLayer in the Pebble SDK

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages