Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel/src/modules/notifications/NotificationQueue.cc @ 8748

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

Some extension of NotificationQueue, font size and color can now be specified.

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