Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/presentation/src/modules/notifications/NotificationQueue.cc @ 8637

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

Merging tutoriallevel3 branch into presentation branch.

  • 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"
[8637]40#include "core/XMLPort.h"
[7403]41#include "util/SubString.h"
[2280]42
[2435]43namespace orxonox
44{
[2910]45
[8637]46    CreateFactory(NotificationQueue);
47   
[2911]48    /**
49    @brief
[8637]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.
71        The senders need to be seperated by commas.
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    */
[7163]77
[2911]78    /**
79    @brief
[7403]80        Destructor.
[2911]81    */
[7403]82    NotificationQueue::~NotificationQueue()
[2911]83    {
[7403]84        this->targets_.clear();
[2911]85
[8637]86        if(this->isRegistered()) // If the NotificationQueue is registered.
[7403]87        {
[7488]88            this->clear(true);
[2911]89
[7403]90            // Unregister with the NotificationManager.
91            NotificationManager::getInstance().unregisterQueue(this);
[7488]92        }
93    }
[7403]94
[7488]95    /**
96    @brief
[8637]97        Initializes the NotificationQueue.
[7488]98    */
[8637]99    void NotificationQueue::initialize(void)
[7488]100    {
[8637]101        this->size_ = 0;
102        this->tickTime_ = 0.0f;
103        this->maxSize_ = NotificationQueue::DEFAULT_SIZE;
104        this->displayTime_ = NotificationQueue::DEFAULT_DISPLAY_TIME;
[7488]105
[8637]106        this->creationTime_ = std::time(0);
[2911]107    }
108
109    /**
110    @brief
[8637]111        Creates the NotificationQueue.
[2911]112    */
[7403]113    void NotificationQueue::create(void)
[2911]114    {
[8637]115        // Register the NotificationQueue with the NotificationManager.
116        bool queueRegistered = NotificationManager::getInstance().registerQueue(this);
117        this->registered_ = true;
118        if(!queueRegistered) // If the registration has failed.
119        {
120            this->registered_ = false;
121            COUT(1) << "Error: NotificationQueue '" << this->getName() << "' could not be registered." << std::endl;
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.
[8637]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        {
[8637]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
[8637]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.
[8637]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.
[8637]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        {
[8637]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++)
[8637]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
[8637]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;
[8637]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
[8637]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
[8637]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
[8637]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
[8637]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
[8637]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
[8637]359        The number of seconds a Notification is displayed.
[2911]360    */
[8637]361    void NotificationQueue::setDisplayTime(int time)
[2911]362    {
[7403]363        if(this->displayTime_ == time)
364            return;
[2911]365
[8637]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
[8637]373        if(this->isRegistered())
[7403]374            this->update();
[2911]375    }
376
377    /**
378    @brief
[8637]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
[8637]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
[8637]415        // TODO: Why?
416        if(this->isRegistered())
[2911]417        {
[8637]418            NotificationManager::getInstance().unregisterQueue(this);
419            NotificationManager::getInstance().registerQueue(this);
[2911]420        }
421    }
422
[8637]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.