interreality.org [VOS]
[Home] [About]
[Screenshots]
[Download]
[News]
[Community]
[Documentation] [Manual]
[Bugs & Requests] [Wiki]

/home/tetron/hack/vos/apps/tutorials/vostut6.cc

Go to the documentation of this file.
00001 /* Sixth VOS tutorial.  Child and Property Listeners
00002 
00003    This tutorial covers:
00004    - Subclassing ChildChangeListener and PropertyListener
00005    - Handling notify callbacks
00006    - The VobjectEvent and PropertyEvent classes
00007    - Adding listeners to Vobjects
00008 
00009    This file (vostut6.cc) is released into the public domain.  No
00010    restrictions are placed on its use, distribution or inclusion into
00011    other works.
00012 */
00013 
00014 #include <vos/vos/vos.hh>
00015 
00016 using namespace VUtil;
00017 using namespace VOS;
00018 
00019 #ifdef WIN32
00020 #define sleep _sleep
00021 #endif
00022 
00023 /* A very useful feature of VOS is the ability to get a notification
00024    callback when something interesting changes, such as the child list
00025    of a Vobject or the value of a property.  To handle these
00026    callbacks, you must subclass the appropriate "Listener" class.  The
00027    Listener defines certain methods which will be called when various
00028    events happen.  You must override and implement these methods in
00029    your own class.
00030  */
00031 
00032 
00033 // This should be fairly self-explanatory.  The events signaled by
00034 // notifyInserted, notifyReplaced and notifyRemoved correspond to the
00035 // insertChild, setChild and removeChild methods in Vobject.  The
00036 // VobjectEvent class provides specific information about what has happened.
00037 
00038 class TutorialChildListener : public ChildChangeListener
00039 {
00040 public:
00041     virtual void notifyChildInserted(VobjectEvent& e);
00042     virtual void notifyChildReplaced(VobjectEvent& e);
00043     virtual void notifyChildRemoved(VobjectEvent& e);
00044 };
00045 
00046 void TutorialChildListener::notifyChildInserted(VobjectEvent& e)
00047 {
00048     std::cout << "Parent " << e.getParent()->getURL().getString()
00049               << " has added child " << e.getChild()->getURL().getString()
00050               << "\n at position " << e.getPosition()
00051               << " with contextual name \"" << e.getContextualName() << "\"\n";
00052 }
00053 
00054 void TutorialChildListener::notifyChildReplaced(VobjectEvent& e)
00055 {
00056     std::cout << "Parent " << e.getParent()->getURL().getString()
00057               << " has replaced child " << e.getOldChild()->getURL().getString()
00058               << "\n with " << e.getNewChild()->getURL().getString()
00059               << "\n at position " << e.getPosition()
00060               << " with contextual name \"" << e.getContextualName() << "\"\n";
00061 }
00062 
00063 void TutorialChildListener::notifyChildRemoved(VobjectEvent& e)
00064 {
00065     std::cout << "Parent " << e.getParent()->getURL().getString()
00066               << " has removed child " << e.getChild()->getURL().getString()
00067               << "\n from position " << e.getPosition()
00068               << " (old contextual name \"" << e.getContextualName() << "\")\n";
00069 }
00070 
00071 
00072 // Similarly, you can ask to receive notification of property changes.
00073 
00074 class TutorialPropertyListener : public PropertyListener
00075 {
00076 public:
00077     virtual void notifyPropertyChange(const PropertyEvent& e);
00078 };
00079 
00080 
00081 void TutorialPropertyListener::notifyPropertyChange(const PropertyEvent& e)
00082 {
00083     std::cout << "Property " << e.getProperty()->getURLstr()
00084               << " has changed value from \"" << e.getOldValue()
00085               << "\" to \"" << e.getNewValue() << "\"\n";
00086 
00087 }
00088 
00089 int main(int argc, char** argv)
00090 {
00091     std::cout << "VOS Tutorial 6\n\n";
00092 
00093     Site localsite;
00094     localsite.addSiteExtension(new LocalVipSiteExtension());
00095 
00096     vRef<Vobject> sphere = localsite.createVobjectA("sphere");
00097     vRef<Vobject> tertius = localsite.createVobjectA("tertius");
00098     vRef<Vobject> quartus = localsite.createVobject<Property>("quartus");
00099     vRef<Vobject> quintus = localsite.createVobjectA("quintus");
00100     vRef<Vobject> sextus = localsite.createVobjectA("sextus");
00101     vRef<Vobject> septimus = localsite.createVobjectA("septimus");
00102 
00103     sphere->insertChild(-1, "position", tertius);
00104     sphere->insertChild(-1, "orientation", quartus);
00105 
00106 
00107     /* This adds the listener.  Whenever the child list for "sphere"
00108        changes, the TutorialChildListener class will be called.  Also
00109        note that when you add a listener, it will immediately be
00110        called with notifyChildInserted() for each child the Vobject
00111        currently has.
00112      */
00113     sphere->addChildListener(new TutorialChildListener());
00114 
00115 
00116     // Mess around with sphere's child list.  This is the same
00117     // sequence of actions from tutorial 4.
00118 
00119     sphere->insertChild(-1, "radius", quintus);
00120     sphere->insertChild(-1, "position", quartus);
00121     sphere->insertChild(2, "color", sextus);
00122     sphere->setChild(4, "mass", septimus);
00123     sphere->removeChild(sphere->findChild(1));
00124     sphere->removeChild(sphere->findChild(-1));
00125 
00126     /* You may use listeners on both local and remote Vobjects. When
00127        you are set up as a listener for the children of a remote
00128        vobject, that vobject's child list is cached and considered
00129        "hot" because any changes to the child list are automatically
00130        pushed to listeners.  This means that calls to methods like
00131        Vobject::getChildren() will use the cached copy and not have to
00132        access the network.  This can be a significant performance win
00133        for certain applications. */
00134 
00135 
00136     // Property listeners work similarly to child listeners.  The
00137     // listener will be called immediately when first added with the
00138     // initial value of the property, and the called as further
00139     // updates happen (from a call to write() or replace()).
00140 
00141     vRef<Property> positionproperty = meta_cast<Property>(quartus);
00142 
00143     positionproperty->addPropertyListener(new TutorialPropertyListener());
00144 
00145     positionproperty->replace("1 2 3", "list: float");
00146 
00147     positionproperty->write(2, "4");
00148 
00149     /* Be aware that event notification callbacks will happen in a
00150        separate thread!  This has the advantage that it doesn't
00151        interrupt the main thread, but you will need to lock any data
00152        structures that may be concurrently accessed.  You also need to
00153        be careful not to stall the task queue (discussed in another
00154        tutorial).  All VOS classes are threadsafe unless noted
00155        otherwise (the primary exceptions are vRef<> and the various
00156        Iterators).
00157     */
00158 
00159     sleep(1);
00160 }