The aim of this second section of the tutorial series is to show examples of how the primer theory from the last section appears in the real world application we’re all looking at – the PebbleKit SDK. But first there is one more data storage convention in C we need to look at. But before that, a quick recap.
- A watch face file is a C file (*.c) and is compiled by the compilers supplied with the Pebble SDK.
- Statements (or lines of code) are executed one after another, except where diverted by program flow statements such as
- Variables are where data is stored. Examples are types such as integers, strings and floating points.
- Functions perform repeated tasks on data supplied as the arguments. Sometimes the resulting values are returned, and used in assignments.
If any of these things are completely foreign to you, please go back and read the last section!
In C, structures are a data type similar to
float, but contain many different values and can be created for a specific purpose by the user or in this case the SDK developers. You can think of them as a collection of variables that come under one heading, or an Object, if you’re coming from an Object Oriented Programming background.
The individual variables inside the structure can be accessed individually but are all declared at the same time by a single structure declaration. Let’s make this a little clearer with an example. Suppose we used a structure to define the aspects of a car.
The reason that structures are included here are that they are especially important in relation to the Pebble SDK, and so form our first real examples. Luckily we don’t have to access the individual variables inside a structure very often.
The final point on structures is that the key word
typedef can be used to define your structure as it’s own data type, and so avoid having to type
struct before any declaration. Here’s an example:
More Common Types To Know
In developing a watch face, there are a few more types of data constants to know (these are used as easy ways of specifying aspects of the watch face). The first example is the
GColor (Graphics Color). These are defined in order to be used to set the colours of parts of Layers. Their listing in the API documentation lets you know which ones are available. You’ll see how they fit in when we start to use them later.
Another common type you’ll be using a lot is the
GRect. This allows you to specify the dimensions of a rectangle for use in setting Layer frames, or starting and finishing positions for animations etc. It is crucial to enabling you to set where items appear on the watch face and how big they are.
Here are two real examples of these types in use:
If you see the API documentation for
GRect, it is actually a structure consisting of a
GPoint for the origin and a
GSize for the width and height. I hope you can guess what those two new ones do!
Structures in the PebbleSDK
A large number of structures are used in the SDK to represent various elements that go into a watch face or app. An example is the Layer structure. The variables stored inside this structure are items such as it’s geometry and the Window it is situated in. In the SDK reference material it looks like this.
At a distance, the most basic watch face possible is just a collection of structures representing user interface elements and functions that manipulate these structures through their pointers (easier than returning an entire struct!)
The first two I’ll introduce are Window and TextLayer. These are defined using
typedef, so the key word
struct is not needed when you use them.
The Window structure represents the ‘fullscreen window’ that IS your watch face. When you add an element such as a TextLayer to the Window, it is displayed in that Window. In order to be accessible to all parts of the watch face program, they are declared ‘globally’. This just means outside any function, and so visible to them all, like so:
So, the Window is the main place for all the parts of the watch face, and the TextLayer is a Layer that displays text to the user. Before either of these can be used, we must call functions provided by the SDK to set them up or ‘initialise’ them. The image below illustrates this process:
Notice throughout the process the Window structure the pointers are operating on is specified using a pointer to the structure, rather than the structure itself. This is done thought the ‘&’ symbol, used to specify the structure’s pointer.
Once this is done, we can initialise and add a TextLayer to the Window for displaying our demo text.
It is important to note that the order in which Layers are added to a Window matters. Much like the new Window is added to the top of the ‘stack’ of windows, the most recent’y added Layer will be at the front, on top of everything else. If the background colour is specified as
GColorClear, this is rarely an issue, but there could be times when this feature can be taken advantage of.
So that’s how the data types, functions and structures manifest themselves in creating a basic watch face. I hope I’ve made it clear enough, but if not, feel free to ask a question.
In the next section I’ll show a brief overview of how to setup a Ubuntu environment for building watch faces, if you prefer that to the cloud based solution mentioned in the first section.
After that, I’ll walk through a basic first watch face!