Subject.h

Go to the documentation of this file.
00001 /*
00002  * The information in this file is
00003  * Copyright(c) 2007 Ball Aerospace & Technologies Corporation
00004  * and is subject to the terms and conditions of the
00005  * GNU Lesser General Public License Version 2.1
00006  * The license text is available from   
00007  * http://www.gnu.org/licenses/lgpl.html
00008  */
00009 
00010 #ifndef __SUBJECT_H
00011 #define __SUBJECT_H
00012 
00013 #include "TypeAwareObject.h"
00014 
00015 #include <string>
00016 
00017 class SafeSlot;
00018 class Slot;
00019 
00020 /**
00021  *  This macro simplifies and standardizes creation of signal methods. This
00022  *  macro will create a static method to use when attaching, detaching
00023  *  and notifying. The full body of the method is created. For example:
00024  *  @code
00025  *  SIGNAL_METHOD(MyClass, MySignal)
00026  *  @endcode
00027  *  will create the following method:
00028  *  @code
00029  *  static const std::string &signalMySignal() { ... }
00030  *  @endcode
00031  *
00032  *  @param type
00033  *             The class that the signal is emitted by
00034  *  @param name
00035  *             The unique name for the signal.
00036  */
00037 #define SIGNAL_METHOD(type,name) \
00038    static const std::string &signal##name() \
00039    { \
00040       static std::string signalName(#type "::" #name);  \
00041       return signalName;\
00042    }
00043 
00044 /**
00045  *  This macro simplifies specifying a particular signal. For example:
00046  *  @code
00047  *  notify(SIGNAL_NAME(MyClass, MySignal));
00048  *  @endcode
00049  *  notifies with the signal created with
00050  *  @code
00051  *  SIGNAL_METHOD(MyClass, MySignal)
00052  *  @endcode
00053  *
00054  *  @param type
00055  *             The class that the signal is emitted by
00056  *  @param name
00057  *             The unique name for the signal.
00058  */
00059 #define SIGNAL_NAME(type,name) type::signal##name()
00060 
00061 /**
00062  *  Base class for objects to send notification when their data changes
00063  *
00064  *  Generalized interface for objects that can notify observers
00065  *  when changes have been made. It provides a uniform means for
00066  *  letting other objects register an interest in the contents 
00067  *  of this object's contents.
00068  *
00069  *  Each %Subject has signals that it will emit under certain circumstances.
00070  *  When a signal is emitted, all slots attached to that signal on the %Subject
00071  *  will be called. For example:
00072  *  @code
00073  *  pSubject->attach(SIGNAL_NAME(Subject, Modified), Slot(pObj, &Obj::mySlot));
00074  *  @endcode
00075  *  This will cause pObj->mySlot(*pSubject, "Subject::Modified", v) to be called
00076  *  whenever pSubject emits SIGNAL_NAME(Subject, Modified).
00077  *
00078  *  Whenever a signal other than Subject::Modified or Subject::Deleted is
00079  *  emitted, Subject::Modified will also be emitted.
00080  *  This means that all slots attached to Subject::signalModified on a 
00081  *  %Subject of type MyClass will be called when that MyClass object 
00082  *  emits SIGNAL_NAME(MyClass, MySignal).
00083  *
00084  *  Signals for a particular instance of a %Subject can be supressed by using
00085  *  either the SignalBlocker or SignalEnabler classes.
00086  *
00087  *  The notification of slots is done in two passes.
00088  *  First, all slots attached to the specific signal are notified in FIFO
00089  *  order (First In == first attached, and First Out == first notified).
00090  *  Then, assuming the specific signal is not Subject::Deleted or
00091  *  Subject::Modified, all slots attached to Subject::Modified
00092  *  are notified in FIFO order.
00093 
00094  *  @see    TypeAwareObject, Slot, SafeSlot, AutoSlot, Signal, SignalBlocker, SignalEnabler
00095  */
00096 class Subject : public TypeAwareObject
00097 {
00098 public:
00099    /**
00100     *  Emitted when a %Subject is deleted.  This will always be emitted, it CANNOT
00101     *  be blocked using SignalBlocker or SignalEnabler.
00102     */
00103    SIGNAL_METHOD(Subject, Deleted)
00104    /**
00105     *  Emitted when a %Subject is modified. Anytime a signal other than deleted
00106     *  or modified is notified, signalModified will be notified as well.
00107     */
00108    SIGNAL_METHOD(Subject, Modified)
00109 
00110    /**
00111     *  Allow another object to register an interest in specific changes on 
00112     *  this %Subject.
00113     *
00114     *  @param   signal
00115     *           The name of the signal to attach to. If signal is empty, the 
00116     *           Slot will be called on all signals from this %Subject.
00117     *
00118     *  @param   slot
00119     *           An object that contains the object and method to call when the
00120     *           specified signal is notified. This can be a Slot, SafeSlot or
00121     *           AutoSlot.
00122     *
00123     *  @return   true if the Slot was valid and was not already attached to
00124     *           the signal on the subject and false otherwise.
00125     *
00126     *  @notify  This method will call Observer::attached on the object in
00127     *           the slot, if the object inherits Observer.
00128     */
00129     virtual bool attach(const std::string& signal, const Slot& slot) = 0;
00130 
00131    /**
00132     *  Allow a Slot to be deregistered from a signal on this %Subject.
00133     *
00134     *  @param   signal
00135     *           The name of the signal the Slot is attached to. If signal is
00136     *           empty, the specified Slot will be detached from all signals on
00137     *           this %Subject.
00138     *
00139     *  @param   slot
00140     *           The Slot to detach from the specified signal. If the Slot is 
00141     *           empty, all slots will be detached from the specified signal.
00142     *           If the slot was originally attached as a SafeSlot or AutoSlot, 
00143     *           it needs to be detached as same type.
00144     *
00145     *  @return   true if the Slot was attached to the specified signal on the
00146     *          subject.
00147     *
00148     *  @notify  This method will call Observer::detached on the object in
00149     *           the slot, if the object inherits Observer.
00150     */
00151    virtual bool detach(const std::string& signal, const Slot& slot) = 0;
00152 
00153    /**
00154     *  Indicates whether the Subject's notification mechanism is enabled or not.
00155     *  If signals are disabled, then only SIGNAL_NAME(Subject, Deleted) will be
00156     *  emitted when requested, all other signals will be suppressed.
00157     *
00158     *  To disable signals, either the SignalBlocker or SignalEnabler classes 
00159     *  must be used.
00160     *
00161     *  @warning  Disabling signals can be very dangerous as it hides details from
00162     *            any attached slots which may depend on being notified to
00163     *            function properly.
00164     *  
00165     *  @see      SignalBlocker, SignalEnabler
00166     *  @return   true if the Subject's notification is enabled, or false otherwise.
00167     */
00168    virtual bool signalsEnabled() const = 0;
00169 
00170 protected:
00171    /**
00172     * This should not be deleted directly.  It should be deleted according to
00173     * the instructions provided for the relevant subclass.
00174     */
00175    virtual ~Subject() {}
00176 
00177 private:
00178    /**
00179     *  Allows the notification of signals by a Subject to be enabled or disabled.
00180     *
00181     *  @param   enabled
00182     *           Controls whether the Subject will notify or not when its notify
00183     *           method is called.
00184     */
00185    virtual void enableSignals(bool enabled) = 0;
00186 
00187 friend class SignalEnabler;
00188 friend class SignalBlocker;
00189 #ifdef CPPTESTS
00190 friend class SubjectObserverTest;
00191 #endif
00192 };
00193 
00194 #endif

Software Development Kit - Opticks 4.9.0 Build 16218