Flip Basics Programming Guide

More Fun with Flip

Providing Undo/Redo Feature

Flip provides an undo/redo history system.

void  run ()
{
   Document document (Model::use (), 123456789ULL, 'acme', 'gui ');
   History history (document);                                       (1)
   Root & root = document.root <Root> ();
   root.happiness_level = 100.0;
   document.set_label ("Change");                                    (2)
   auto tx = document.commit ();                                     (3)
   history.push (tx);                                                (4)
   history.undo ().execute ();                                       (5)
   history.redo ().execute ();                                       (6)
}
  1. Set up a history for document
  2. Set a label for the forming transaction
  3. commit returns a transaction, which has the label as a metadata
  4. push the transaction to the history system
  5. undo the transaction
  6. redo the transaction

The undo/redo/history topic is studied in more details in the book Flip History Strategy Guide.

Manipulating Transactions

Transactions represent exactly the difference between to state of the document. Flip flexibility allows to store them, and replay them in any direction.

void  run ()
{
   Document document (Model::use (), 123456789ULL, 'acme', 'gui ');
   Root & root = document.root <Root> ();
   assert (root.tempo == 0.0);            (1)
   root.tempo = 100.0;
   auto tx = document.commit ();
   document.execute_backward (tx);        (2)
   document.execute_forward (tx);         (3)
}
  1. All flip values are constructed with a zero value or an empty state
  2. play the transaction backward, happiness goes back to 0.0. Note that the transaction is applied, but the document is not commited
  3. play the transaction backward, happiness goes back to 100.0. Note that the transaction is applied, but the document is not commited. If it was commited, it would produce an empty transaction.

Since transactions can be copied and are just data without external coupling, they can be used for many usual kind of problem solving.

Reading/Writing a Document

Flip supports two formats :

Those two backend formats can be read or written in an infinite number of media using a traditional Consumer/Producer architecture.

Writing a Document

void  write ()
{
   BackEndIR backend = document.write ();       (1)
   std::vector <uint8_t> data;
   DataConsumerMemory consumer (data);          (2)
   backend.write <BackEndBinary> (consumer);    (3)
}
  1. Write the document into an intermediate representation format. This format is also used to do document revision conversion
  2. Set up a data consumer which will write in memory
  3. Write to the consumer using the binary format

See BackEndBinary or BackEndMl reference documentation for additional examples.

Reading a Document

void  read ()
{
   std::vector <uint8_t> data;                  (1)
   DataProviderMemory provider (data);          (2)
   BackEndIR backend;
   backend.register_backend <BackEndBinary> (); (3)
   backend.register_backend <BackEndMl> ();
   backend.read (provider);                     (4)
}
  1. Here we suppose that data is already filled with document data
  2. Attach a provider to the data to read
  3. Register the two formats that the backend can read. The backends implementation are able to tell if the incoming data is in the right format
  4. Read the document

See BackEndBinary or BackEndMl reference documentation for additional examples.

The next chapter, Model Versioning will guide you through converting a document from one revision of the model to another one.