Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Merging tutoriallevel2 branch into tutoriallevel3 branch.

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