Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel2/src/modules/notifications/NotificationQueue.cc @ 8448

Last change on this file since 8448 was 8448, checked in by dafrick, 14 years ago

Extending NotificationQueueCEGUI.

  • Property svn:eol-style set to native
File size: 13.3 KB
RevLine 
[2280]1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
[2911]29/**
[7403]30    @file NotificationQueue.cc
[2911]31    @brief Implementation of the NotificationQueue class.
32*/
33
[2280]34#include "NotificationQueue.h"
35
[7403]36#include <map>
37#include <sstream>
38
39#include "core/CoreIncludes.h"
40#include "util/SubString.h"
[2280]41
[7403]42#include "Notification.h"
43
[2435]44namespace orxonox
45{
[2910]46
[2911]47    /**
48    @brief
49        Constructor. Creates and initializes the object.
[7403]50    @param name
[7484]51        The name of the new NotificationQueue. It needs to be unique
[7403]52    @param senders
53        The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
[8445]54        The senders need to be separated by commas.
[7403]55    @param size
56        The size (the maximum number of displayed Notifications) of this NotificationQueue.
57    @param displayTime
58        The time during which a Notification is (at most) displayed.
[2911]59    */
[7403]60    NotificationQueue::NotificationQueue(const std::string& name, const std::string& senders, unsigned int size, unsigned int displayTime)
[2280]61    {
[7163]62        this->registered_ = false;
63
[7403]64        RegisterRootObject(NotificationQueue);
[2911]65
[7403]66        // Initialize.
[2911]67        this->size_ = 0;
[7413]68        this->tickTime_ = 0.0f;
[2911]69
[7403]70        // Sets the input values.
71        this->setTargets(senders);
72        this->name_ = name;
73        this->maxSize_ = size;
74        this->setDisplayTime(displayTime);
75
76        // Register the NotificationQueue with the NotificationManager.
77        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
[7163]78        this->registered_ = true;
[7403]79        if(!queueRegistered) // If the registration has failed.
80        {
81            this->registered_ = false;
[7413]82            COUT(1) << "Error: NotificationQueue '" << this->getName() << "' could not be registered." << std::endl;
[7403]83            return;
84        }
85
86        COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl;
[2911]87    }
88
89    /**
90    @brief
[7403]91        Destructor.
[2911]92    */
[7403]93    NotificationQueue::~NotificationQueue()
[2911]94    {
[7403]95        this->targets_.clear();
[2911]96
[7488]97        if(this->registered_) // If the NotificationQueue is registered.
[7403]98        {
[7488]99            this->clear(true);
[2911]100
[7403]101            // Unregister with the NotificationManager.
102            NotificationManager::getInstance().unregisterQueue(this);
[7488]103        }
[8446]104       
[8079]105        COUT(3) << "NotificationQueue '" << this->getName() << "' destroyed." << std::endl;
[2911]106    }
107
108    /**
109    @brief
110        Updates the queue from time to time.
111    @param dt
112        The time interval that has passed since the last tick.
113    */
114    void NotificationQueue::tick(float dt)
115    {
[7403]116        this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
[8371]117        if(this->displayTime_ != INF && 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.
[2910]118        {
[7403]119            this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containig the current time.
[2911]120
[7403]121            std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin();
122            // Iterate through all elements whose creation time is smaller than the current time minus the display time.
[7410]123            while(it != this->ordering_.upper_bound(&this->timeLimit_))
[2911]124            {
[8079]125                this->remove(it); // Remove the Notifications that have expired.
126                it = this->ordering_.begin();
[2911]127            }
128
[7403]129            this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter.
[2910]130        }
[2911]131    }
132
133    /**
134    @brief
135        Updates the NotificationQueue.
[7403]136        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
[8374]137        This is called by the NotificationManager when the Notifications have changed so much, that the NotificationQueue may have to re-initialize his operations.
[2911]138    */
139    void NotificationQueue::update(void)
140    {
141        this->clear();
142
[7403]143        std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
144        // Get the Notifications sent in the interval from now to now minus the display time.
[8371]145        if(this->displayTime_ == INF)
146            NotificationManager::getInstance().getNewestNotifications(this, notifications, this->getMaxSize());
147        else
148            NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
[2910]149
[7403]150        if(!notifications->empty())
[2911]151        {
[7403]152            // Add all Notifications.
153            for(std::multimap<std::time_t, Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++)
154                this->push(it->second, it->first);
[2911]155        }
156
157        delete notifications;
158
[7163]159        COUT(4) << "NotificationQueue '" << this->getName() << "' updated." << std::endl;
[2280]160    }
[2910]161
[2911]162    /**
163    @brief
164        Updates the NotificationQueue by adding an new Notification.
165    @param notification
166        Pointer to the Notification.
167    @param time
168        The time the Notification was sent.
169    */
170    void NotificationQueue::update(Notification* notification, const std::time_t & time)
[2280]171    {
[7489]172        assert(notification);
173
[7403]174        this->push(notification, time);
[2910]175
[7403]176        COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << std::endl;
[2280]177    }
[2910]178
[2911]179    /**
180    @brief
[7403]181        Adds (pushes) a Notification to the NotificationQueue.
182        It inserts it into the storage containers, creates a corresponding container and pushes the Notification message to the GUI.
183    @param notification
184        The Notification to be pushed.
185    @param time
186        The time when the Notification has been sent.
[2911]187    */
[7403]188    void NotificationQueue::push(Notification* notification, const std::time_t & time)
[2280]189    {
[7489]190        assert(notification);
191
[7403]192        NotificationContainer* container = new NotificationContainer;
193        container->notification = notification;
194        container->time = time;
195
196        // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed.
197        if(this->getSize() >= this->getMaxSize())
198            this->pop();
199
200        this->size_++;
201
202        this->ordering_.insert(container);
203        // Insert the Notification at the begin of the list (vector, actually).
204        this->notifications_.insert(this->notifications_.begin(), container);
205
[8446]206        // Inform that a Notification was pushed.
207        this->notificationPushed(notification);
[8079]208
209        COUT(5) << "Notification \"" << notification->getMessage() << "\" pushed to NotificationQueue '" << this->getName() << "'" << endl;
[8448]210        COUT(3) << "NotificationQueue \"" << this->getName() << "\": " << notification->getMessage() << endl;
[2911]211    }
[2500]212
[2911]213    /**
214    @brief
[7403]215        Removes (pops) the least recently added Notification form the NotificationQueue.
[2911]216    */
[7403]217    void NotificationQueue::pop(void)
[2911]218    {
[7403]219        NotificationContainer* container = this->notifications_.back();
[7412]220        // Get all the NotificationContainers that were sent the same time the NotificationContainer we want to pop was sent.
221        std::pair<std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator, std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator> iterators = this->ordering_.equal_range(container);
[8079]222
[7489]223        // Iterate through all suspects and remove the container as soon as we find it.
[7412]224        for(std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = iterators.first; it != iterators.second; it++)
225        {
226            if(container == *it)
227            {
[8079]228                COUT(5) << "Notification \"" << (*it)->notification->getMessage() << "\" popped from NotificationQueue '" << this->getName() << "'" << endl;
[7412]229                this->ordering_.erase(it);
230                break;
231            }
232        }
[7403]233        this->notifications_.pop_back();
[2910]234
[7403]235        this->size_--;
236
237        delete container;
238
[8446]239        // Inform that a Notification was popped.
240        this->notificationPopped();
[2911]241    }
[2910]242
[2911]243    /**
244    @brief
[7403]245        Removes the Notification that is stored in the input NotificationContainer.
[7412]246    @param containerIterator
247        An iterator to the NotificationContainer to be removed.
[2911]248    */
[7412]249    void NotificationQueue::remove(const std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator& containerIterator)
[2911]250    {
[7412]251        std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), *containerIterator);
[7403]252        // Get the index at which the Notification is.
253        std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin ();
[8079]254
255        COUT(5) << "Notification \"" << (*it)->notification->getMessage() << "\" removed from NotificationQueue '" << this->getName() << "'" << endl;
256
[7412]257        this->ordering_.erase(containerIterator);
[7403]258        this->notifications_.erase(it);
[2911]259
[7403]260        this->size_--;
261
[7412]262        delete *containerIterator;
[7403]263
[8446]264        // TODO: index automatically cast?
265        // Inform that a Notification was removed.
266        this->notificationRemoved(index);
[2909]267    }
[2500]268
[2911]269    /**
270    @brief
[7403]271        Clears the NotificationQueue by removing all NotificationContainers.
[7488]272    @param noGraphics
[8445]273        If this is set to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
[2911]274    */
[7488]275    void NotificationQueue::clear(bool noGraphics)
[2280]276    {
[8079]277        COUT(4) << "Clearing NotificationQueue " << this->getName() << "." << endl;
[7403]278        this->ordering_.clear();
279        // Delete all NotificationContainers in the list.
280        for(std::vector<NotificationContainer*>::iterator it = this->notifications_.begin(); it != this->notifications_.end(); it++)
281            delete *it;
[2911]282
[7403]283        this->notifications_.clear();
284        this->size_ = 0;
[2346]285    }
[2500]286
[2911]287    /**
288    @brief
[7403]289        Sets the name of the NotificationQueue.
290    @param name
291        The name to be set.
[2911]292    */
[7403]293    void NotificationQueue::setName(const std::string& name)
[2280]294    {
[7403]295        this->name_ = name;
[2280]296    }
[2500]297
[2911]298    /**
299    @brief
[7403]300        Sets the maximum number of displayed Notifications.
301    @param size
302        The size to be set.
[2911]303    */
[7403]304    void NotificationQueue::setMaxSize(unsigned int size)
[2280]305    {
[7403]306        if(this->maxSize_ == size)
307            return;
[2911]308
[7403]309        this->maxSize_ = size;
310
311        if(this->registered_)
312            this->update();
[2911]313    }
314
315    /**
316    @brief
[7403]317        Sets the maximum number of seconds a Notification is displayed.
[2911]318    @param time
[8371]319        The number of seconds a Notification is displayed.
[2911]320    */
[8371]321    void NotificationQueue::setDisplayTime(int time)
[2911]322    {
[7403]323        if(this->displayTime_ == time)
324            return;
[2911]325
[7403]326        this->displayTime_ = time;
[2911]327
[7403]328        if(this->registered_)
329            this->update();
[2911]330    }
331
332    /**
333    @brief
[8445]334        Produces all targets of the NotificationQueue concatenated as string, with commas (',') as separators.
[2911]335    @return
[7403]336        Returns the targets as a string.
[2911]337    */
[7403]338    const std::string& NotificationQueue::getTargets(void) const
[2911]339    {
[7403]340        std::stringstream stream;
341        bool first = true;
342        // Iterate through the set of targets.
[7417]343        for(std::set<std::string>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++)
[7403]344        {
345            if(!first)
346                stream << ", ";
347            else
348                first = false;
349            stream << *it;
350        }
[2911]351
[7403]352        return *(new std::string(stream.str()));
[2911]353    }
354
355    /**
356    @brief
[7403]357        Sets the targets of the NotificationQueue.
358        The targets are the senders whose Notifications are displayed in this queue.
359    @param targets
[8445]360        Accepts a string of targets, each separated by commas (','), spaces are ignored.
[2911]361    */
[7403]362    void NotificationQueue::setTargets(const std::string & targets)
[2911]363    {
[7403]364        this->targets_.clear();
365
366        SubString string = SubString(targets, ",", " ", false);
367        for(unsigned int i = 0; i < string.size(); i++)
368            this->targets_.insert(string[i]);
369
[8374]370        // TODO: Why?
[7403]371        if(this->registered_)
[2911]372        {
[8374]373            NotificationManager::getInstance().unregisterQueue(this);
374            NotificationManager::getInstance().registerQueue(this);
[2911]375        }
376    }
[8448]377
378    /**
379    @brief
380        Pops all Notifications from the NotificationQueue.
381    @return
382        Returns true if successful, false if not.
383    */
384    bool NotificationQueue::tidy(void)
[8445]385    {
386        while(this->size_ > 0)
387            this->pop();
[8448]388        return true;
[8445]389    }
[2911]390
[2280]391}
[7403]392
Note: See TracBrowser for help on using the repository browser.