Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Sep 11, 2010, 10:20:44 AM (14 years ago)
Author:
dafrick
Message:

Merged notifications branch back to trunk.

Location:
code/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • code/trunk

  • code/trunk/src/modules/notifications/NotificationQueue.cc

    r7401 r7403  
    2828
    2929/**
    30     @file
     30    @file NotificationQueue.cc
    3131    @brief Implementation of the NotificationQueue class.
    3232*/
     
    3434#include "NotificationQueue.h"
    3535
     36#include <map>
     37#include <sstream>
     38
     39#include "core/CoreIncludes.h"
     40#include "core/GUIManager.h"
     41#include "core/LuaState.h"
    3642#include "util/Convert.h"
    37 #include "core/CoreIncludes.h"
    38 #include "core/XMLPort.h"
    39 #include "NotificationOverlay.h"
    40 #include "NotificationManager.h"
     43#include "util/SubString.h"
     44
     45#include "Notification.h"
    4146
    4247namespace orxonox
    4348{
    4449
    45     CreateFactory(NotificationQueue);
    46 
    47     const std::string NotificationQueue::DEFAULT_FONT("VeraMono");
    48     const Vector2 NotificationQueue::DEFAULT_POSITION(0.0,0.0);
    49     const float NotificationQueue::DEFAULT_FONT_SIZE = 0.025f;
    50 
    5150    /**
    5251    @brief
    5352        Constructor. Creates and initializes the object.
    54     */
    55     NotificationQueue::NotificationQueue(BaseObject* creator) : OverlayGroup(creator)
     53    @param name
     54        The name of the new NotificationQueue.
     55    @param senders
     56        The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
     57        The senders need to be seperated by commas.
     58    @param size
     59        The size (the maximum number of displayed Notifications) of this NotificationQueue.
     60    @param displayTime
     61        The time during which a Notification is (at most) displayed.
     62    */
     63    NotificationQueue::NotificationQueue(const std::string& name, const std::string& senders, unsigned int size, unsigned int displayTime)
    5664    {
    5765        this->registered_ = false;
    5866
    59         RegisterObject(NotificationQueue);
    60         this->initialize();
    61     }
    62 
    63     /**
    64     @brief
    65         Destructor.
    66     */
    67     NotificationQueue::~NotificationQueue()
    68     {
    69         this->targets_.clear();
    70         this->clear();
    71 
    72         if(this->registered_)
    73             NotificationManager::getInstance().unregisterListener(this);
    74     }
    75 
    76     /**
    77     @brief
    78         Initializes the object.
    79         Registers the object, initializes variables, sets default values and registers the queue with the NotificationManager.
    80     */
    81     void NotificationQueue::initialize(void)
    82     {
     67        RegisterRootObject(NotificationQueue);
     68
     69        // Initialize.
    8370        this->size_ = 0;
    8471        this->tickTime_ = 0.0;
    8572
    86         NotificationManager::getInstance().registerListener(this);
     73        // Sets the input values.
     74        this->setTargets(senders);
     75        this->name_ = name;
     76        this->maxSize_ = size;
     77        this->setDisplayTime(displayTime);
     78
     79        //TODO: Destroy if registration fails?
     80
     81        // Register the NotificationQueue with the NotificationManager.
     82        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
    8783        this->registered_ = true;
    88     }
    89 
    90     /**
    91     @brief
    92         Sets the defaults.
    93     */
    94     void NotificationQueue::setDefaults(void)
    95     {
    96         this->setMaxSize(DEFAULT_SIZE);
    97         this->setNotificationLength(DEFAULT_LENGTH);
    98         this->setDisplayTime(DEFAULT_DISPLAY_TIME);
    99         this->setPosition(DEFAULT_POSITION);
    100 
    101         this->setTargets(NotificationManager::ALL);
    102 
    103         this->setFontSize(DEFAULT_FONT_SIZE);
    104         this->setFont(DEFAULT_FONT);
    105     }
    106 
    107     /**
    108     @brief
    109         Method for creating a NotificationQueue object through XML.
    110     */
    111     void NotificationQueue::XMLPort(Element& xmlelement, XMLPort::Mode mode)
    112     {
    113         SUPER(NotificationQueue, XMLPort, xmlelement, mode);
    114 
    115         this->setDefaults();
    116 
    117         XMLPortParam(NotificationQueue, "maxSize", setMaxSize, getMaxSize, xmlelement, mode);
    118         XMLPortParam(NotificationQueue, "notificationLength", setNotificationLength, getNotificationLength, xmlelement, mode);
    119         XMLPortParam(NotificationQueue, "displayTime", setDisplayTime, getDisplayTime, xmlelement, mode);
    120         XMLPortParam(NotificationQueue, "targets", setTargets, getTargets, xmlelement, mode);
    121         XMLPortParam(NotificationQueue, "font", setFont, getFont, xmlelement, mode);
    122         XMLPortParam(NotificationQueue, "fontSize", setFontSize, getFontSize, xmlelement, mode);
    123         XMLPortParam(NotificationQueue, "position", setPosition, getPosition, xmlelement, mode);
     84        if(!queueRegistered) // If the registration has failed.
     85        {
     86            this->registered_ = false;
     87            COUT(1) << "Error: Notification Queue '" << this->getName() << "' could not be registered." << std::endl;
     88            return;
     89        }
     90
     91        this->create(); // Creates the NotificationQueue in lua.
     92
     93        // register the NotificationQueue as NotificationListener with the NotificationManager.
     94        bool listenerRegistered = NotificationManager::getInstance().registerListener(this);
     95        if(!listenerRegistered) // If the registration has failed.
     96        {
     97            this->registered_ = false;
     98            // Remove the NotificationQueue in lua.
     99            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
     100            NotificationManager::getInstance().unregisterQueue(this);
     101            COUT(1) << "Error: Notification Queue '" << this->getName() << "' could not be registered." << std::endl;
     102            return;
     103        }
    124104
    125105        COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl;
     106    }
     107
     108    /**
     109    @brief
     110        Destructor.
     111    */
     112    NotificationQueue::~NotificationQueue()
     113    {
     114        this->targets_.clear();
     115
     116        if(this->registered_) // If the
     117        {
     118            this->clear();
     119
     120            // Unregister with the NotificationManager.
     121            NotificationManager::getInstance().unregisterListener(this);
     122            NotificationManager::getInstance().unregisterQueue(this);
     123
     124            // Remove the NotificationQueue in lua.
     125            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() +  "\")");
     126        }
     127    }
     128
     129    /**
     130    @brief
     131        Creates the NotificationQueue in lua.
     132    */
     133    void NotificationQueue::create(void)
     134    {
     135        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.createQueue(\"" + this->getName() +  "\", " + multi_cast<std::string>(this->getMaxSize()) + ")");
    126136    }
    127137
     
    134144    void NotificationQueue::tick(float dt)
    135145    {
    136         this->tickTime_ += dt; //!< Add the time interval that has passed to the time counter.
    137         if(this->tickTime_ >= 1.0) //!< If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
    138         {
    139             this->timeLimit_.time = std::time(0)-this->displayTime_; //!< Container containig the current time.
    140 
    141             std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it;
    142             it = this->containers_.begin();
    143             while(it != this->containers_.upper_bound(&this->timeLimit_)) //!< Iterate through all elements whose creation time is smaller than the current time minus the display time.
     146        this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
     147        if(this->tickTime_ >= 1.0) // If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.
     148        {
     149            this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containig the current time.
     150
     151            std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin();
     152            // Iterate through all elements whose creation time is smaller than the current time minus the display time.
     153            while(it != this->ordering_.upper_bound(&this->timeLimit_))
    144154            {
    145                 this->removeContainer(*it);
    146                 this->scroll(Vector2(0.0f,-(1.1f*this->getFontSize())));
    147                 it = this->containers_.begin(); //TODO: Needed?
     155                NotificationContainer* temp = *it;
     156                it++;
     157                this->remove(temp); // Remove the Notifications that have expired.
    148158            }
    149159
    150             this->tickTime_ = 0.0f; //!< Reset time counter.
     160            this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter.
    151161        }
    152162    }
     
    155165    @brief
    156166        Updates the NotificationQueue.
    157         Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting the in the queue.
     167        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
    158168    */
    159169    void NotificationQueue::update(void)
     
    161171        this->clear();
    162172
    163         std::multimap<std::time_t,Notification*>* notifications = new std::multimap<std::time_t,Notification*>;
    164         if(!NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_)) //!< Get the Notifications sent in the interval form now to minus the display time.
    165         {
    166             COUT(1) << "NotificationQueue update failed due to undetermined cause." << std::endl;
    167             return;
    168         }
    169 
    170         if(notifications->empty())
    171             return;
    172 
    173         for(std::multimap<std::time_t,Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++) //!> Add all Notifications.
    174         {
    175             this->addNotification(it->second, it->first);
     173        std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
     174        // Get the Notifications sent in the interval from now to now minus the display time.
     175        NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
     176
     177        if(!notifications->empty())
     178        {
     179            // Add all Notifications.
     180            for(std::multimap<std::time_t, Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++)
     181                this->push(it->second, it->first);
    176182        }
    177183
     
    191197    void NotificationQueue::update(Notification* notification, const std::time_t & time)
    192198    {
    193         this->addNotification(notification, time);
    194 
    195         std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it;
    196         while(this->getSize() > this->getMaxSize())
    197         {
    198             it = this->containers_.begin();
    199             this->removeContainer(*it);
    200             this->scroll(Vector2(0.0f,-(1.1f*this->getFontSize())));
    201         }
    202 
    203         COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notifications has been added." << std::endl;
     199        this->push(notification, time);
     200
     201        COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << std::endl;
     202    }
     203
     204    /**
     205    @brief
     206        Adds (pushes) a Notification to the NotificationQueue.
     207        It inserts it into the storage containers, creates a corresponding container and pushes the Notification message to the GUI.
     208    @param notification
     209        The Notification to be pushed.
     210    @param time
     211        The time when the Notification has been sent.
     212    */
     213    void NotificationQueue::push(Notification* notification, const std::time_t & time)
     214    {
     215        NotificationContainer* container = new NotificationContainer;
     216        container->notification = notification;
     217        container->time = time;
     218
     219        // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed.
     220        if(this->getSize() >= this->getMaxSize())
     221            this->pop();
     222
     223        this->size_++;
     224
     225        this->ordering_.insert(container);
     226        // Insert the Notification at the begin of the list (vector, actually).
     227        this->notifications_.insert(this->notifications_.begin(), container);
     228
     229        // Push the Notification to the GUI.
     230        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")");
     231    }
     232
     233    /**
     234    @brief
     235        Removes (pops) the least recently added Notification form the NotificationQueue.
     236    */
     237    void NotificationQueue::pop(void)
     238    {
     239        NotificationContainer* container = this->notifications_.back();
     240        this->ordering_.erase(container);
     241        this->notifications_.pop_back();
     242
     243        this->size_--;
     244
     245        delete container;
     246
     247        // Pops the Notification from the GUI.
     248        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.popNotification(\"" + this->getName() + "\")");
     249    }
     250
     251    /**
     252    @brief
     253        Removes the Notification that is stored in the input NotificationContainer.
     254    @param container
     255        The NotificationContainer with the Notification to be removed.
     256    */
     257    void NotificationQueue::remove(NotificationContainer* container)
     258    {
     259        std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), container);
     260        // Get the index at which the Notification is.
     261        std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin ();
     262        this->ordering_.erase(container);
     263        this->notifications_.erase(it);
     264
     265        this->size_--;
     266
     267        delete container;
     268
     269        // Removes the Notification from the GUI.
     270        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")");
     271    }
     272
     273    /**
     274    @brief
     275        Clears the NotificationQueue by removing all NotificationContainers.
     276    */
     277    void NotificationQueue::clear(void)
     278    {
     279        this->ordering_.clear();
     280        // Delete all NotificationContainers in the list.
     281        for(std::vector<NotificationContainer*>::iterator it = this->notifications_.begin(); it != this->notifications_.end(); it++)
     282            delete *it;
     283
     284        this->notifications_.clear();
     285
     286        this->size_ = 0;
     287
     288        // Clear the NotificationQueue in the GUI.
     289        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.clearQueue(\"" + this->getName() + "\")");
     290    }
     291
     292    /**
     293    @brief
     294        Sets the name of the NotificationQueue.
     295    @param name
     296        The name to be set.
     297    */
     298    void NotificationQueue::setName(const std::string& name)
     299    {
     300        this->name_ = name;
    204301    }
    205302
     
    209306    @param size
    210307        The size to be set.
    211     @return
    212         Returns true if successful.
    213     */
    214     bool NotificationQueue::setMaxSize(int size)
    215     {
    216         if(size < 0)
    217             return false;
     308    */
     309    void NotificationQueue::setMaxSize(unsigned int size)
     310    {
     311        if(this->maxSize_ == size)
     312            return;
     313
    218314        this->maxSize_ = size;
    219         this->update();
    220         return true;
    221     }
    222 
    223     /**
    224     @brief
    225         Sets the maximum number of characters a Notification message displayed by this queue is allowed to have.
    226     @param length
    227         The length to be set.
    228     @return
    229         Returns true if successful.
    230     */
    231     bool NotificationQueue::setNotificationLength(int length)
    232     {
    233         if(length < 0)
    234             return false;
    235         this->notificationLength_ = length;
    236         this->update();
    237         return true;
     315
     316        if(this->registered_)
     317            this->update();
    238318    }
    239319
     
    246326        Returns true if successful.
    247327    */
    248     bool NotificationQueue::setDisplayTime(int time)
    249     {
    250         if(time < 0)
    251             return false;
     328    void NotificationQueue::setDisplayTime(unsigned int time)
     329    {
     330        if(this->displayTime_ == time)
     331            return;
     332
    252333        this->displayTime_ = time;
    253         this->update();
    254         return true;
    255     }
    256 
    257     /**
    258     @brief
    259         Produces all targets concatinated as string, with kommas (',') as seperators.
    260     @param string
    261         Pointer to a string which will be used by the method to fill with the concatination of the targets.
     334
     335        if(this->registered_)
     336            this->update();
     337    }
     338
     339    /**
     340    @brief
     341        Produces all targets of the NotificationQueue concatinated as string, with kommas (',') as seperators.
    262342    @return
    263         Returns true if successful.
    264     */
    265     bool NotificationQueue::getTargets(std::string* string) const
    266     {
    267         if(string == NULL)
    268         {
    269             COUT(4) << "Input string must have memory allocated." << std::endl;
    270             return false;
    271         }
    272         string->clear();
     343        Returns the targets as a string.
     344    */
     345    const std::string& NotificationQueue::getTargets(void) const
     346    {
     347        std::stringstream stream;
    273348        bool first = true;
    274         for(std::set<std::string>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++) //!< Iterate through the set of targets.
     349        // Iterate through the set of targets.
     350        for(std::set<std::string, NotificationListenerStringCompare>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++)
    275351        {
    276352            if(!first)
    277             {
    278                 *string += ',';
    279             }
     353                stream << ", ";
    280354            else
    281             {
    282355                first = false;
    283             }
    284             *string += *it;
    285         }
    286 
    287         return true;
    288     }
    289 
    290     /**
    291     @brief
    292         Sets the targets of the queue.
     356            stream << *it;
     357        }
     358
     359        return *(new std::string(stream.str()));
     360    }
     361
     362    /**
     363    @brief
     364        Sets the targets of the NotificationQueue.
    293365        The targets are the senders whose Notifications are displayed in this queue.
    294366    @param targets
    295367        Accepts a string of targets, each seperated by commas (','), spaces are ignored.
    296     @return
    297         Returns true if successful.
    298     */
    299     bool NotificationQueue::setTargets(const std::string & targets)
     368    */
     369    void NotificationQueue::setTargets(const std::string & targets)
    300370    {
    301371        this->targets_.clear();
    302372
    303         std::string* pTemp;
    304         unsigned int index = 0;
    305         while( index < targets.size() ) //!< Go through the string, character by character until the end is reached.
    306         {
    307             pTemp = new std::string();
    308             while(index < targets.size() && targets[index] != ',' && targets[index] != ' ')
    309             {
    310                 *pTemp += targets[index];
    311                 index++;
    312             }
    313             index++;
    314             this->targets_.insert(*pTemp);
    315         }
    316 
    317         return true;
    318     }
    319 
    320     /**
    321     @brief
    322         Sets the font size.
    323     @param size
    324         The font size.
    325     @return
    326         Returns true if successful.
    327     */
    328     bool NotificationQueue::setFontSize(float size)
    329     {
    330         if(size <= 0)
    331             return false;
    332         this->fontSize_ = size;
    333         for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); it++) //!< Set the font size for each overlay.
    334         {
    335             it->second->overlay->setFontSize(size);
    336         }
    337         return true;
    338     }
    339 
    340     /**
    341     @brief
    342         Sets the font.
    343     @param font
    344         The font.
    345     @return
    346         Returns true if successful.
    347     */
    348     bool NotificationQueue::setFont(const std::string & font)
    349     {
    350         this->font_ = font;
    351         for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); it++) //!< Set the font for each overlay.
    352         {
    353             it->second->overlay->setFont(font);
    354         }
    355         return true;
    356     }
    357 
    358     /**
    359     @brief
    360         Scrolls the NotificationQueue, meaning all NotificationOverlays are moved the input vector.
    361     @param pos
    362         The vector the NotificationQueue is scrolled.
    363     */
    364     void NotificationQueue::scroll(const Vector2 pos)
    365     {
    366         for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); ++it) //!< Scroll each overlay.
    367         {
    368             it->second->overlay->scroll(pos);
    369         }
    370     }
    371 
    372     /**
    373     @brief
    374         Aligns all the Notifications to the position of the NotificationQueue.
    375     */
    376     void NotificationQueue::positionChanged(void)
    377     {
    378         int counter = 0;
    379         for (std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it = this->containers_.begin(); it != this->containers_.end(); it++) //!< Set the position for each overlay.
    380         {
    381             (*it)->overlay->setPosition(this->getPosition());
    382             (*it)->overlay->scroll(Vector2(0.0f,(1.1f*this->getFontSize())*counter));
    383             counter++;
    384         }
    385     }
    386 
    387     /**
    388     @brief
    389         Adds a Notification, to the queue.
    390         It inserts it into the storage containers, creates an corresponding overlay and a container.
    391     @param notification
    392         The Notification.
    393     @param time
    394         The time.
    395     */
    396     void NotificationQueue::addNotification(Notification* notification, const std::time_t & time)
    397     {
    398         NotificationOverlayContainer* container = new NotificationOverlayContainer;
    399         container->overlay = new NotificationOverlay(this, notification);
    400         container->notification = notification;
    401         container->time = time;
    402         std::string timeString = std::ctime(&time);
    403         timeString.erase(timeString.length()-1);
    404         const std::string& addressString = multi_cast<std::string>(reinterpret_cast<unsigned long>(notification));
    405         container->name = "NotificationOverlay(" + timeString + ")&" + addressString;
    406 
    407         this->containers_.insert(container);
    408         this->overlays_[notification] = container;
    409         this->addElement(container->overlay);
    410         this->size_= this->size_+1;
    411 
    412         container->overlay->scroll(Vector2(0.0f,(1.1f*this->getFontSize())*(this->getSize()-1)));
    413     }
    414 
    415     /**
    416     @brief
    417         Removes a container from the queue.
    418     @param container
    419         A pointer to the container.
    420     @return
    421         Returns true if successful.
    422     */
    423     bool NotificationQueue::removeContainer(NotificationOverlayContainer* container)
    424     {
    425         if(this->size_ == 0) //!< You cannot remove anything if the queue is empty.
    426             return false;
    427 
    428         // Unregister the NotificationQueue with the NotificationManager.
    429         NotificationManager::getInstance().unregisterNotification(container->notification, this);
    430 
    431         this->removeElement(container->overlay);
    432         this->containers_.erase(container);
    433         this->overlays_.erase(container->notification);
    434         container->overlay->destroy();
    435         delete container;
    436         this->size_= this->size_-1;
    437 
    438         return true;
    439     }
    440 
    441     /**
    442     @brief
    443         Clears the queue by removing all containers.
    444     */
    445     void NotificationQueue::clear(void)
    446     {
    447         std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it = this->containers_.begin();
    448         while(it != this->containers_.end())
    449         {
    450             this->removeContainer(*it);
    451             it = this->containers_.begin();
     373        SubString string = SubString(targets, ",", " ", false);
     374        for(unsigned int i = 0; i < string.size(); i++)
     375            this->targets_.insert(string[i]);
     376
     377        if(this->registered_)
     378        {
     379            NotificationManager::getInstance().unregisterListener(this);
     380            NotificationManager::getInstance().registerListener(this);
    452381        }
    453382    }
    454383
    455384}
     385
Note: See TracChangeset for help on using the changeset viewer.