Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Moving the Notification class int NotificationManager, since it is only a container now.

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