Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel3/src/modules/notifications/NotificationQueue.cc @ 8703

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

Making NotificationQueue XML-loadable. Adding notifications to all levels.

  • Property svn:eol-style set to native
File size: 14.7 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"
[8636]40#include "core/XMLPort.h"
[7403]41#include "util/SubString.h"
[2280]42
[2435]43namespace orxonox
44{
[2910]45
[8636]46    CreateFactory(NotificationQueue);
47   
[2911]48    /**
49    @brief
[8636]50        Default constructor. Registers and initializes the object.
51    @param creator
52        The creator of the NotificationQueue.
53    */
54    NotificationQueue::NotificationQueue(BaseObject* creator) : BaseObject(creator), registered_(false)
55    {
56        RegisterObject(NotificationQueue);
57
58        this->initialize();
59    }
60
61    // TODO move to docu.
62    /**
63    @brief
64        Constructor. Registers and initializes the object.
65    @param creator
66        The creator of the NotificationQueue
[7403]67    @param name
[7484]68        The name of the new NotificationQueue. It needs to be unique
[7403]69    @param senders
70        The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays.
[8636]71        The senders need to be seperated by commas.
[7403]72    @param size
73        The size (the maximum number of displayed Notifications) of this NotificationQueue.
74    @param displayTime
75        The time during which a Notification is (at most) displayed.
[2911]76    */
[8636]77
78    /**
79    @brief
80        Destructor.
81    */
82    NotificationQueue::~NotificationQueue()
[2280]83    {
[8636]84        this->targets_.clear();
[7163]85
[8636]86        if(this->isRegistered()) // If the NotificationQueue is registered.
87        {
88            this->clear(true);
[2911]89
[8636]90            // Unregister with the NotificationManager.
91            NotificationManager::getInstance().unregisterQueue(this);
92        }
93    }
94
95    /**
96    @brief
97        Initializes the NotificationQueue.
98    */
99    void NotificationQueue::initialize(void)
100    {
[2911]101        this->size_ = 0;
[7413]102        this->tickTime_ = 0.0f;
[8636]103        this->maxSize_ = NotificationQueue::DEFAULT_SIZE;
104        this->displayTime_ = NotificationQueue::DEFAULT_DISPLAY_TIME;
[2911]105
[8636]106        this->creationTime_ = std::time(0);
107    }
[7403]108
[8636]109    /**
110    @brief
111        Creates the NotificationQueue.
112    */
113    void NotificationQueue::create(void)
114    {
[7403]115        // Register the NotificationQueue with the NotificationManager.
116        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
[7163]117        this->registered_ = true;
[7403]118        if(!queueRegistered) // If the registration has failed.
119        {
120            this->registered_ = false;
[7413]121            COUT(1) << "Error: NotificationQueue '" << this->getName() << "' could not be registered." << std::endl;
[7403]122            return;
123        }
124
125        COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl;
[2911]126    }
127
128    /**
129    @brief
130        Updates the queue from time to time.
131    @param dt
132        The time interval that has passed since the last tick.
133    */
134    void NotificationQueue::tick(float dt)
135    {
[7403]136        this->tickTime_ += dt; // Add the time interval that has passed to the time counter.
[8453]137        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]138        {
[8636]139            this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containing the current time.
[2911]140
[7403]141            std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin();
142            // Iterate through all elements whose creation time is smaller than the current time minus the display time.
[7410]143            while(it != this->ordering_.upper_bound(&this->timeLimit_))
[2911]144            {
[8079]145                this->remove(it); // Remove the Notifications that have expired.
146                it = this->ordering_.begin();
[2911]147            }
148
[7403]149            this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter.
[2910]150        }
[2911]151    }
152
[8636]153    void NotificationQueue::XMLPort(Element& xmlelement, XMLPort::Mode mode)
154    {
155        SUPER(NotificationQueue, XMLPort, xmlelement, mode);
156
157        XMLPortParam(NotificationQueue, "targets", setTargets, getTargets, xmlelement, mode).defaultValues(NotificationListener::ALL);
158        XMLPortParam(NotificationQueue, "size", setMaxSize, getMaxSize, xmlelement, mode);
159        XMLPortParam(NotificationQueue, "displayTime", setDisplayTime, getDisplayTime, xmlelement, mode);
160
161        this->create();
162    }
163
[2911]164    /**
165    @brief
166        Updates the NotificationQueue.
[7403]167        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue.
[8453]168        This is called by the NotificationManager when the Notifications have changed so much, that the NotificationQueue may have to re-initialize his operations.
[2911]169    */
170    void NotificationQueue::update(void)
171    {
172        this->clear();
173
[7403]174        std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>;
175        // Get the Notifications sent in the interval from now to now minus the display time.
[8453]176        if(this->displayTime_ == INF)
177            NotificationManager::getInstance().getNewestNotifications(this, notifications, this->getMaxSize());
178        else
179            NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_);
[2910]180
[7403]181        if(!notifications->empty())
[2911]182        {
[8636]183            // Add all Notifications that have been created after this NotificationQueue was created.
[7403]184            for(std::multimap<std::time_t, Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++)
[8636]185            {
186                if(it->first >= this->creationTime_)
187                    this->push(it->second, it->first);
188            }
[2911]189        }
190
191        delete notifications;
192
[7163]193        COUT(4) << "NotificationQueue '" << this->getName() << "' updated." << std::endl;
[2280]194    }
[2910]195
[2911]196    /**
197    @brief
198        Updates the NotificationQueue by adding an new Notification.
199    @param notification
200        Pointer to the Notification.
201    @param time
202        The time the Notification was sent.
203    */
204    void NotificationQueue::update(Notification* notification, const std::time_t & time)
[2280]205    {
[7489]206        assert(notification);
207
[7403]208        this->push(notification, time);
[2910]209
[7403]210        COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << std::endl;
[2280]211    }
[2910]212
[2911]213    /**
214    @brief
[7403]215        Adds (pushes) a Notification to the NotificationQueue.
216        It inserts it into the storage containers, creates a corresponding container and pushes the Notification message to the GUI.
217    @param notification
218        The Notification to be pushed.
219    @param time
220        The time when the Notification has been sent.
[2911]221    */
[7403]222    void NotificationQueue::push(Notification* notification, const std::time_t & time)
[2280]223    {
[7489]224        assert(notification);
225
[7403]226        NotificationContainer* container = new NotificationContainer;
227        container->notification = notification;
228        container->time = time;
229
230        // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed.
231        if(this->getSize() >= this->getMaxSize())
232            this->pop();
233
234        this->size_++;
235
236        this->ordering_.insert(container);
237        // Insert the Notification at the begin of the list (vector, actually).
238        this->notifications_.insert(this->notifications_.begin(), container);
239
[8453]240        // Inform that a Notification was pushed.
241        this->notificationPushed(notification);
[8079]242
243        COUT(5) << "Notification \"" << notification->getMessage() << "\" pushed to NotificationQueue '" << this->getName() << "'" << endl;
[8453]244        COUT(3) << "NotificationQueue \"" << this->getName() << "\": " << notification->getMessage() << endl;
[2911]245    }
[2500]246
[2911]247    /**
248    @brief
[7403]249        Removes (pops) the least recently added Notification form the NotificationQueue.
[2911]250    */
[7403]251    void NotificationQueue::pop(void)
[2911]252    {
[7403]253        NotificationContainer* container = this->notifications_.back();
[7412]254        // Get all the NotificationContainers that were sent the same time the NotificationContainer we want to pop was sent.
255        std::pair<std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator, std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator> iterators = this->ordering_.equal_range(container);
[8079]256
[7489]257        // Iterate through all suspects and remove the container as soon as we find it.
[7412]258        for(std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = iterators.first; it != iterators.second; it++)
259        {
260            if(container == *it)
261            {
[8079]262                COUT(5) << "Notification \"" << (*it)->notification->getMessage() << "\" popped from NotificationQueue '" << this->getName() << "'" << endl;
[7412]263                this->ordering_.erase(it);
264                break;
265            }
266        }
[7403]267        this->notifications_.pop_back();
[2910]268
[7403]269        this->size_--;
270
271        delete container;
272
[8453]273        // Inform that a Notification was popped.
274        this->notificationPopped();
[2911]275    }
[2910]276
[2911]277    /**
278    @brief
[7403]279        Removes the Notification that is stored in the input NotificationContainer.
[7412]280    @param containerIterator
281        An iterator to the NotificationContainer to be removed.
[2911]282    */
[7412]283    void NotificationQueue::remove(const std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator& containerIterator)
[2911]284    {
[7412]285        std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), *containerIterator);
[7403]286        // Get the index at which the Notification is.
287        std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin ();
[8079]288
289        COUT(5) << "Notification \"" << (*it)->notification->getMessage() << "\" removed from NotificationQueue '" << this->getName() << "'" << endl;
290
[7412]291        this->ordering_.erase(containerIterator);
[7403]292        this->notifications_.erase(it);
[2911]293
[7403]294        this->size_--;
295
[7412]296        delete *containerIterator;
[7403]297
[8453]298        // TODO: index automatically cast?
299        // Inform that a Notification was removed.
300        this->notificationRemoved(index);
[2909]301    }
[2500]302
[2911]303    /**
304    @brief
[7403]305        Clears the NotificationQueue by removing all NotificationContainers.
[7488]306    @param noGraphics
[8453]307        If this is set to true the GUI is not informed of the clearing of the NotificationQueue. This is needed only internally.
[2911]308    */
[7488]309    void NotificationQueue::clear(bool noGraphics)
[2280]310    {
[8079]311        COUT(4) << "Clearing NotificationQueue " << this->getName() << "." << endl;
[7403]312        this->ordering_.clear();
313        // Delete all NotificationContainers in the list.
314        for(std::vector<NotificationContainer*>::iterator it = this->notifications_.begin(); it != this->notifications_.end(); it++)
315            delete *it;
[2911]316
[7403]317        this->notifications_.clear();
318        this->size_ = 0;
[2346]319    }
[2500]320
[2911]321    /**
322    @brief
[7403]323        Sets the name of the NotificationQueue.
324    @param name
325        The name to be set.
[2911]326    */
[7403]327    void NotificationQueue::setName(const std::string& name)
[2280]328    {
[7403]329        this->name_ = name;
[2280]330    }
[2500]331
[2911]332    /**
333    @brief
[7403]334        Sets the maximum number of displayed Notifications.
335    @param size
336        The size to be set.
[2911]337    */
[7403]338    void NotificationQueue::setMaxSize(unsigned int size)
[2280]339    {
[7403]340        if(this->maxSize_ == size)
341            return;
[2911]342
[8636]343        if(size == 0)
344        {
345            COUT(2) << "Trying to set maximal size of NotificationQueue '" << this->getName() << "' to 0. Ignoring..." << endl;
346            return;
347        }
348       
[7403]349        this->maxSize_ = size;
350
[8636]351        if(this->isRegistered())
[7403]352            this->update();
[2911]353    }
354
355    /**
356    @brief
[7403]357        Sets the maximum number of seconds a Notification is displayed.
[2911]358    @param time
[8453]359        The number of seconds a Notification is displayed.
[2911]360    */
[8453]361    void NotificationQueue::setDisplayTime(int time)
[2911]362    {
[7403]363        if(this->displayTime_ == time)
364            return;
[2911]365
[8636]366        if(time != NotificationQueue::INF && time <= 0)
367        {
368            COUT(2) << "Trying to set display time of NotificationQueue '" << this->getName() << "' to non-positive value. Ignoring..." << endl;
369        }
370           
[7403]371        this->displayTime_ = time;
[2911]372
[8636]373        if(this->isRegistered())
[7403]374            this->update();
[2911]375    }
376
377    /**
378    @brief
[8453]379        Produces all targets of the NotificationQueue concatenated as string, with commas (',') as separators.
[2911]380    @return
[7403]381        Returns the targets as a string.
[2911]382    */
[7403]383    const std::string& NotificationQueue::getTargets(void) const
[2911]384    {
[7403]385        std::stringstream stream;
386        bool first = true;
387        // Iterate through the set of targets.
[7417]388        for(std::set<std::string>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++)
[7403]389        {
390            if(!first)
391                stream << ", ";
392            else
393                first = false;
394            stream << *it;
395        }
[2911]396
[7403]397        return *(new std::string(stream.str()));
[2911]398    }
399
400    /**
401    @brief
[7403]402        Sets the targets of the NotificationQueue.
403        The targets are the senders whose Notifications are displayed in this queue.
404    @param targets
[8453]405        Accepts a string of targets, each separated by commas (','), spaces are ignored.
[2911]406    */
[7403]407    void NotificationQueue::setTargets(const std::string & targets)
[2911]408    {
[7403]409        this->targets_.clear();
410
411        SubString string = SubString(targets, ",", " ", false);
412        for(unsigned int i = 0; i < string.size(); i++)
413            this->targets_.insert(string[i]);
414
[8453]415        // TODO: Why?
[8636]416        if(this->isRegistered())
[2911]417        {
[8453]418            NotificationManager::getInstance().unregisterQueue(this);
419            NotificationManager::getInstance().registerQueue(this);
[2911]420        }
421    }
422
[8453]423    /**
424    @brief
425        Pops all Notifications from the NotificationQueue.
426    @return
427        Returns true if successful, false if not.
428    */
429    bool NotificationQueue::tidy(void)
430    {
431        while(this->size_ > 0)
432            this->pop();
433        return true;
434    }
435
[2280]436}
[7403]437
Note: See TracBrowser for help on using the repository browser.