Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 8448 was 8448, checked in by dafrick, 13 years ago

Extending NotificationQueueCEGUI.

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