Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Removing some TODO comments.
Better handling of duplicate name in Notificationlayer.lua.
Moving StringCompare object from NotificationListener to StringUtils.

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