/* * GLMoleculeObject_bond.hpp * * Created on: Aug 17, 2011 * Author: heber */ #ifndef GLMOLECULEOBJECT_BOND_HPP_ #define GLMOLECULEOBJECT_BOND_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "GLMoleculeObject.hpp" #include #include #include #include "CodePatterns/Observer/Observer.hpp" #include "CodePatterns/ObservedValue.hpp" #include "LinearAlgebra/Vector.hpp" #include "Bond/bond.hpp" #include "types.hpp" class atom; class GLWorldScene; class GLMoleculeObject_bond : public GLMoleculeObject, public Observer { Q_OBJECT public: enum SideOfBond { left, right }; typedef std::pair bondIds_t; GLMoleculeObject_bond( QGLSceneNode *mesh[], QObject *parent, const bondIds_t bondIds, const enum SideOfBond side); GLMoleculeObject_bond( QGLSceneNode *mesh[], QObject *parent, const bondIds_t bondIds, const enum SideOfBond side, std::vector &_ObservedValues, const boost::function &_subjectKilled); virtual ~GLMoleculeObject_bond(); // Observer functions void update(Observable *publisher); void subjectKilled(Observable *publisher); void recieveNotification(Observable *publisher, Notification_ptr notification); signals: void BondRemoved(const atomId_t leftnr, const atomId_t rightnr); void elementChanged(); void positionChanged(); void degreeChanged(); private slots: //!> grant GLMoleculeObject_molecule acess to reset functions friend class GLMoleculeObject_molecule; /** Recalculates the element of the cylinder representing the bond. * */ void resetElement(); /** Recalculates the position of the cylinder representing the bond. * */ void resetPosition(); /** Recalculates the width of the cylinder representing the bond's degree. * */ void resetWidth(); private: void init(); void removeChannels(); static atomId_t updateIndex(); static Vector updateLeftPosition( const boost::function &_getLeftAtomIndex); static Vector updateRightPosition( const boost::function &_getRightAtomIndex); static atomicNumber_t updateLeftElement( const boost::function &_getLeftAtomIndex); static atomicNumber_t updateRightElement( const boost::function &_getRightAtomIndex); static int updateDegree( const boost::function &_getLeftAtomIndex, const boost::function &_getRightAtomIndex); static const atom * const getAtomConst(const atomId_t _id); static atom * const getAtom(const atomId_t _id); private: //!> contains ref to Observable of left atom const Observable * const leftowner; //!> contains ref to Observable of right atom const Observable * const rightowner; //!> temporary variable used in cstor const Observable * const bondowner; const enum SideOfBond BondSide; private: /** Observed Values **/ //!> enumeration of observed values to match with entries in ObservedValues enum ObservedTypes { //!> contains the id of the left atom leftIndex, //!> contains the id of the right atom rightIndex, //!> contains the position of the left atom leftPosition, //!> contains the position of the right atom rightPosition, //!> contains the element of the left atom leftElement, //!> contains the element of the right atom rightElement, //!> contains the degree of the bond Degree, //!> gives the size of the enumeration MAX_ObservedTypes }; //!> vector with all observed values std::vector ObservedValues; /** Initializes all \a ObservedValues entries. * * \param _ObservedValues vector of ObservedValue to be filled * \param _leftatomId left atom id * \param _rightatomId right atom id * \param _leftowner reference to left atom * \param _rightowner reference to right atom * \param _bondowner reference to bond * \param _leftsubjectKilled ref to function to call on subjectKilled() for left atom * \param _rightsubjectKilled ref to function to call on subjectKilled() for right atom * \param _bondsubjectKilled ref to function to call on subjectKilled() for bond */ static void initObservedValues( std::vector &_ObservedValues, const atomId_t _leftatomId, const atomId_t _rightatomId, const Observable * const _leftowner, const Observable * const _rightowner, const Observable * const _bondowner, const boost::function &_leftsubjectKilled, const boost::function &_rightsubjectKilled, const boost::function &_bondsubjectKilled); /** Destroys all \a ObservedValues entries. * * \param _ObservedValues vector of ObservedValue to be destroyed */ static void destroyObservedValues( std::vector &_ObservedValues); /** Getter to left atom's id contained in \a ObservedValues. * * \return left atom's id */ const atomId_t& getleftIndex() const; /** Getter to right atom's id contained in \a ObservedValues. * * \return right atom's id */ const atomId_t& getrightIndex() const; /** Getter to left atom's position contained in \a ObservedValues. * * \return left atom's position */ const Vector& getleftPosition() const; /** Getter to right atom's position contained in \a ObservedValues. * * \return right atom's position */ const Vector& getrightPosition() const; /** Getter to left atom's element contained in \a ObservedValues. * * \return left atom's element */ const atomicNumber_t& getleftElement() const; /** Getter to rightatom's element contained in \a ObservedValues. * * \return right atom's element */ const atomicNumber_t& getrightElement() const; /** Getter to bond's degree contained in \a ObservedValues. * * \return bond's degree */ const int& getDegree() const; /** Counts how many ObservedValues got subjectKilled. * * This is used to give InstanceRemoved() signal only when each and every * ObservedValue (and the instance itself) has been subjectKilled by the * monitored Observable. Only then can we safely remove the instance. * * \param _bondIds bond ids whose bond has called subjectKilled() */ void countsubjectKilled( const bondIds_t &_bondIds) { countsubjectKilled(); } void countsubjectKilled( const atomId_t &_atomid) { countsubjectKilled(); } void countsubjectKilled(); //!> counts how many ObservedValues have already been subjectKilled() mutable size_t subjectKilledCount; private: //!> indicate whether we are signed in to leftobservable bool leftobservable_enabled; //!> indicate whether we are signed in to rightobservable bool rightobservable_enabled; //!> indicate whether we are signed in to bond itself bool bond_enabled; //!> list of channels when id needs to update static const Observable::channels_t IndexChannels; //!> list of channels when position needs to update static const Observable::channels_t BondPositionChannels; //!>list of channels when degree needs to update static const Observable::channels_t BondDegreeChannels; //!> list of channels when element needs to update static const Observable::channels_t BondElementChannels; //!> callback function to inform about subjectKilled() const boost::function board_subjectKilled; }; #endif /* GLMOLECULEOBJECT_BOND_HPP_ */