Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Some cleanup and documenting.
After some more extensive testing it seems to work, the code looks ok as well…

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