Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Finished EditMode, needs some polish (no not the language…) though.
Took better advantage of lua tables in NotificationLayer.lua
Fixed a lot of bugs, it really is a miracle that the Notifications worked as well as they did.

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