Flip Basics Programming Guide

Declaring the Model

When building a Flip compatible application, the first task is defining your model. The Model is a set of declarations that will be used together in a concrete Document. In this sense, the Model can be seen as a blueprint or template of the actual Documents you will make with.

To help you understand the Flip principles, this guide considers the following application :

Declaring the Model

Every class managed by flip needs to be part of a model. Therefore you first begin by declaring this model in your header files, and defines its revision string. The revision string represents a particular revision of the model itself, and is used when converting documents from one version to another.

#include "flip/DataModel.h"
class Model : public flip::DataModel <Model> {};
void  declare ()
{
   Model::version ("1.0");
}

Declaring a Class

Every class managed by flip will need to inherit from flip::Object, so the first thing is to inherit from it.

We will also need to declare the class before we can use it, so that we will add a static declare member.

Every model has exactly one root class. We could say that the root class, which represents the top level document class, is the song, and modelize this like the following example.

#include "flip/Object.h"
class Song : public flip::Object
{
public:
   static void    declare ();
};
void  Song::declare ()
{
   Model::declare <Song> ().name ("acme.product.Song");
}

Finally the function declare in the section above would now look like :

void  declare ()
{
   Model::version ("1.0");
   Song::declare ();
}

Adding the first Flip Member

In our example, the tempo is a global property of the song. To modelize that, we can simply make the tempo a floating point member of the song and write this like in the following example.

#include "flip/Float.h"
#include "flip/Object.h"
class Song : public flip::Object
{
public:
   static void    declare ();
   flip::Float    tempo;
};
void  Song::declare ()
{
   Model::declare <Song> ()
      .name ("acme.product.Song")
      .member <flip::Float, &Song::tempo> ("tempo");     (1)
}
  1. Add the typed Float, tempo Song member, and give it the name "tempo"

Important: Names are used for document writing, and are also used in conversions. As such, carefull naming of members is important.

Adding the Flip Containers

Flip provides different kinds of containers.

container.

The clips are implictely specified as implicitely ordered by their position. In this case, an Array or Collection could be used, but generally implicitely ordered elements are better modelized using a Collection.

The tracks contains a list of parameters, and those parameters name are known at runtime. So we will use a Map container.

We then will modelize the track using a Track class, and the clip using a Clip class. The song contains tracks, and a track contains clips. This can be modelized as in the following example.

#include "flip/Array.h"
#include "flip/Collection.h"
#include "flip/Float.h"
#include "flip/Object.h"
class Clip : public flip::Object
{
public:
   static void    declare ();
   flip::Float    position;
   flip::Float    duration;
};
class Parameter : public flip::Object
{
public:
   static void    declare ();
   flip::Float    value;
};
class Track : public flip::Object
{
public:
   static void    declare ();
   flip::Collection <Clip>
                  clips;
   flip::Map <Parameter>
                  parameters;
};
class Song : public flip::Object
{
public:
   static void    declare ();
   flip::Float    tempo;
   flip::Array <Track>
                  tracks;
};
void  Clip::declare ()
{
   Model::declare <Clip> ()
      .name ("acme.product.Clip")
      .member <flip::Float, &Clip::position> ("position")
      .member <flip::Float, &Clip::duration> ("duration");
}
void  Parameter::declare ()
{
   Model::declare <Parameter> ()
      .name ("acme.product.Parameter")
      .member <flip::Float, &Parameter::value> ("value");
}
void  Track::declare ()
{
   Model::declare <Track> ()
      .name ("acme.product.Track")
      .member <flip::Collection <Clip>, &Track::clips> ("clips")
      .member <flip::Map <Parameter>, &Track::parameters> ("parameters");
}
void  Song::declare ()
{
   Model::declare <Song> ()
      .name ("acme.product.Song")
      .member <flip::Float, &Song::tempo> ("tempo")
      .member <flip::Array <Track>, &Song::tracks> ("tracks");
}

Finally the whole model declaration, the function declare in the section above, would now look like :

void  declare ()
{
   Model::version ("1.0");
   Clip::declare ();
   Parameter::declare ();
   Track::declare ();
   Song::declare ();
}

Inheritance

Flip provides inheritance features. It allows you to declare a Flip class as inherited from another Flip class. Inheritance provides parent class members importing as well as C++ polymorphism.

In our example, the clip is specified as being one of two kind : either a clip containing audio or a clip containing musical events.

Both type of clips share the same main clip properties position and duration. In the case of the example, we can introduce ClipAudio and ClipMidi which allows to support those two behaviors.

class ClipAudio : public Clip             (1)
{
public:
   static void    declare ();
   flip::String   sample_url;
};
void  ClipAudio::declare ()
{
   Model::declare <MySubClass> ()
      .name ("acme.product.MySubClass")
      .inherit <MyClass> ()               (2)
      .member <flip::String, &ClipAudio::sample_url> ("sample_url");
}

Then declaring the flip class will look like the following example.

void  declare ()
{
   Model::version ("1.0");
   Clip::declare ();
   ClipAudio::declare ();
   ClipMidi::declare ();
   ... code skipped ...
}

Important: Make sure that the base class is declared before.

Flip Types

Every class managed by flip may contain an unlimited number of either Flip basic types or your own custom Flip classes.

Flip offers categories of basic types :

Value Types

Container Types

Reference Type

Signaling Type

The next chapter, Organizing your Code will guide you through the task of organizing the model code.