BabyStep 3: Interacting with the Model
In this chapter, we will bind a graphical element of a GUI to our ModelRoot class.
Binding the Observer : View part
Changes to the document model are reported to the Observers. In this tutorial we only have one Observer but we could have many, which allows us to isolate code that reacts to the a model change.
All the changes that are made in a transaction are reported to the document_changed function which is call from the root object. Reacting to a change of the model will be as simple as traversing the model tree and update the binded object accordingly. First we will show the general structure of a document_changed function, as this is always the same code pattern repeated over and over again. Then we will show how to fill it for our tutorial need.
ListingModifying BabystepGui.cpp
void BabystepGui::document_changed (ModelRoot & root) |
{ |
if (root.was_inited ()) |
{ |
// 1. |
} |
else |
{ |
// 2. |
} |
if (root.is_invalid ()) |
{ |
// 3. |
} |
if (root.was_restored ()) |
{ |
// 4. |
} |
} |
- the object has just been created
- the object is either restored or still resident, but still exists at this point
- the object contains a modification
- the object has been released, we must release its associated ressources.
Now we are going to bind our graphical object to this pattern.
ListingModifying BabystepGui.cpp
void BabystepGui::document_changed (ModelRoot & root) |
{ |
BundleRoot * bnd_ptr = 0; |
if (root.was_inited ()) |
{ |
bnd_ptr = new BundleRoot (root, _window.use_view ()); // 1. |
_window.use_view ().embed (*bnd_ptr, ohm::opa::BundleView::Slot_WORKSPACE); |
root.reset_data (bnd_ptr); // 2. |
} |
else |
{ |
bnd_ptr = root.get_data <BundleRoot> (); // 3. |
} |
if (root.is_invalid ()) |
{ |
bnd_ptr->update (); // 4. |
} |
if (root.was_restored ()) |
{ |
delete bnd_ptr; // 5. |
bnd_ptr = 0; |
root.reset_data <BundleRoot> (); // 6. |
} |
} |
- create the GUI object and bind it to the window. Note that this object will keep a reference to the model object.
- bind a pointer to the GUI object to the model object...
- ... as this allow to get it back between document_changed calls
- call the function which will update our GUI to match the model
- root is destroyed, remove the GUI object
- unbind the pointer to the GUI object from the model object
The following code shows the implementation of the update call.
ListingModifying BundleRoot.cpp
void BundleRoot::update () |
{ |
if (_root.point_changed ()) |
{ |
_prim_aptr->_point = ohm::opa::Point (_root.get_point_x (), _root.get_point_y ()); |
} |
} |
Binding the Observer : Controller part
User inputs can be translated into model changes by simply changing the model directly. The following code shows how this is done. The move function is called from the GUI element that interprets the user inputs.
ListingModifying BundleRoot.cpp
void BundleRoot::move (const ohm::opa::Point & point) |
{ |
_root.set_point (point._x, point._y); |
} |