Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/notifications/NotificationQueue.cc @ 7488

Last change on this file since 7488 was 7488, checked in by dafrick, 15 years ago

Some more documentation.
Making NotificationManager Root scope, cleaning up, especially in Notification (now it's just a data structure anymore).

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