Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/questsystem5/src/orxonox/overlays/notifications/NotificationQueue.cc @ 2783

Last change on this file since 2783 was 2783, checked in by dafrick, 16 years ago

Erradicated an infinite loop, and some wannabe-memory leaks. Also started the positioning of the notifications. I'd actually call it usable at this point.

  • Property svn:eol-style set to native
File size: 13.0 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#include "OrxonoxStableHeaders.h"
30#include "NotificationQueue.h"
31
32#include <OgreOverlayManager.h>
33#include <OgreTextAreaOverlayElement.h>
34#include <list>
35
36#include "core/CoreIncludes.h"
37#include "core/XMLPort.h"
38
39#include "Notification.h"
40#include "NotificationOverlay.h"
41
42namespace orxonox
43{
44   
45    CreateFactory(NotificationQueue);
46   
47    const std::string NotificationQueue::DEFAULT_FONT = "VeraMono";
48
49    /**
50    @brief
51        Constructor. Creates and initializes the object.
52    */
53    NotificationQueue::NotificationQueue(BaseObject* creator) : OverlayGroup(creator)
54    {
55        this->initialize();
56    }
57   
58    /**
59    @brief
60        Destructor.
61    */
62    NotificationQueue::~NotificationQueue()
63    {
64        this->targets_.clear();
65        this->clear();
66    }
67   
68    /**
69    @brief
70        Initializes the object.
71        Registers the object, initializes variables, sets default values and registers the queue with the NotificationManager.
72    */
73    void NotificationQueue::initialize(void)
74    {
75        RegisterObject(NotificationQueue);
76       
77        this->size_ = 0;
78        this->tickTime_ = 0.0;
79       
80        NotificationManager::registerQueue(this);
81    }
82   
83    /**
84    @brief
85        Sets the defaults.
86    */
87    void NotificationQueue::setDefaults(void)
88    {
89        this->setMaxSize(DEFAULT_SIZE);
90        this->setNotificationLength(DEFAULT_LENGTH);
91        this->setDisplayTime(DEFAULT_DISPLAY_TIME);
92       
93        this->setTargets(NotificationManager::ALL);
94       
95        this->setFontSize(DEFAULT_FONT_SIZE);
96        this->setFont(DEFAULT_FONT);
97    }
98   
99    /**
100    @brief
101        Method for creating a NotificationQueue object through XML.
102    */
103    void NotificationQueue::XMLPort(Element& xmlElement, XMLPort::Mode mode)
104    {
105        SUPER(NotificationQueue, XMLPort, xmlElement, mode);
106       
107        this->setDefaults();
108
109        XMLPortParam(NotificationQueue, "maxSize", setMaxSize, getMaxSize, xmlElement, mode);
110        XMLPortParam(NotificationQueue, "notificationLength", setNotificationLength, getNotificationLength, xmlElement, mode);
111        XMLPortParam(NotificationQueue, "displayTime", setDisplayTime, getDisplayTime, xmlElement, mode);
112        XMLPortParam(NotificationQueue, "targets", setTargets, getTargets, xmlElement, mode);
113        XMLPortParam(NotificationQueue, "font", setFont, getFont, xmlElement, mode);
114        XMLPortParam(NotificationQueue, "fontSize", setFontSize, getFontSize, xmlElement, mode);
115       
116        COUT(3) << "NotificationQueue created." << std::endl;
117    }
118   
119    /**
120    @brief
121        Updates the queue from time to time.
122    @param dt
123        The time interval that has passed since the last tick.
124    */
125    void NotificationQueue::tick(float dt)
126    {
127        this->tickTime_ += dt; //!< Add the time interval that has passed to the time counter.
128        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.
129        {
130            this->timeLimit_.time = std::time(0)-this->displayTime_; //!< Container containig the current time.
131           
132            std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it;
133            it = this->containers_.begin();
134            while(it != this->containers_.upper_bound(&this->timeLimit_)) //!< Iterate through all elements whose creation time is smaller than the current time minus the display time.
135            {
136                this->removeContainer(*it);
137                this->scroll(Vector2(0.0,-(1.1*this->getFontSize())));
138                it = this->containers_.begin(); //TDO: Needed?
139            }
140           
141            this->tickTime_ = 0.0; //!< Reset time counter.
142        }
143    }
144   
145    /**
146    @brief
147        Updates the NotificationQueue.
148        Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting the in the queue.
149    */
150    void NotificationQueue::update(void)
151    {
152        this->clear();
153   
154        std::multimap<std::time_t,Notification*>* notifications = NotificationManager::getNotifications(this, this->displayTime_);
155       
156        if(notifications == NULL)
157            return;
158       
159        for(std::multimap<std::time_t,Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++)
160        {
161            this->addNotification(it->second, it->first);
162        }
163       
164        COUT(3) << "NotificationQueue updated." << std::endl;
165    }
166   
167    /**
168    @brief
169        Updates the NotificationQueue by adding an new Notification.
170    @param notification
171        Pointer to the Notification.
172    @param time
173        The time the Notification was sent.
174    */
175    void NotificationQueue::update(Notification* notification, const std::time_t & time)
176    {
177        this->addNotification(notification, time);
178       
179        std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it;
180        while(this->getSize() > this->getMaxSize())
181        {
182            it = this->containers_.begin();
183            this->removeContainer(*it);
184            this->scroll(Vector2(0.0,-(1.1*this->getFontSize())));
185        }
186       
187        COUT(3) << "NotificationQueue updated. A new Notifications has been added." << std::endl;
188    }
189   
190    /**
191    @brief
192        Sets the maximum number of displayed Notifications.
193    @param size
194        The size to be set.
195    @return
196        Returns true if successful.
197    */
198    bool NotificationQueue::setMaxSize(int size)
199    {
200        if(size < 0)
201            return false;
202        this->maxSize_ = size;
203        this->update();
204        return true;
205    }
206   
207    /**
208    @brief
209        Sets the maximum number of characters a Notification message displayed by this queue is allowed to have.
210    @param length
211        The length to be set.
212    @return
213        Returns true if successful.
214    */
215    bool NotificationQueue::setNotificationLength(int length)
216    {
217        if(length < 0)
218            return false;
219        this->notificationLength_ = length;
220        this->update();
221        return true;
222    }
223   
224    /**
225    @brief
226        Sets the maximum number of seconds a Notification is displayed.
227    @param time
228        The number of seconds the Notifications is displayed.
229    @return
230        Returns true if successful.
231    */
232    bool NotificationQueue::setDisplayTime(int time)
233    {
234        if(time < 0)
235            return false;
236        this->displayTime_ = time;
237        this->update();
238        return true;
239    }
240   
241    /**
242    @brief
243        Produces all targets concatinated as string, with kommas (',') as seperators.
244    @param string
245        Pointer to a string which will be used by the method to fill with the concatination of the targets.
246    @return
247        Returns true if successful.
248    */
249    bool NotificationQueue::getTargets(std::string* string) const
250    {
251        if(string == NULL)
252        {
253            COUT(4) << "Input string must have memory allocated." << std::endl;
254            return false;
255        }
256        string->clear();
257        bool first = true;
258        for(std::set<std::string>::iterator it = this->targets_.begin(); it != this->targets_.end(); it++) //!< Iterate through the set of targets.
259        {
260            if(!first)
261            {
262                *string += ",";
263            }
264            else
265            {
266                first = false;
267            }
268            *string += *it;
269        }
270       
271        return true;
272    }
273   
274    /**
275    @brief
276        Sets the targets of the queue.
277        The targets are the senders whose Notifications are displayed in this queue.
278    @param targets
279        Accepts a string of targets, each seperated by commas (','), spaces are ignored.
280    @return
281        Returns true if successful.
282    */
283    bool NotificationQueue::setTargets(const std::string & targets)
284    {
285        this->targets_.clear();
286
287        std::string* pTemp;
288        unsigned int index = 0;
289        while( index < targets.size() ) //!< Go through the string, character by character until the end is reached.
290        {
291            pTemp = new std::string("");
292            while(index < targets.size() && targets[index] != ',' && targets[index] != ' ')
293            {
294                *pTemp += targets[index];
295                index++;
296            }
297            index++;
298            this->targets_.insert(*pTemp);
299        }
300       
301        return true;
302    }
303   
304    /**
305    @brief
306        Sets the font size.
307    @param size
308        The font size.
309    @return
310        Returns true if successful.
311    */
312    bool NotificationQueue::setFontSize(float size)
313    {
314        if(size <= 0)
315            return false;
316        this->fontSize_ = size;
317        for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); ++it) //!< Set the font size for each overlay.
318        {
319            it->second->overlay->setFontSize(size);
320        }
321        return true;
322    }
323   
324    /**
325    @brief
326        Sets the font.
327    @param font
328        The font.
329    @return
330        Returns true if successful.
331    */
332    bool NotificationQueue::setFont(const std::string & font)
333    {
334        this->font_ = font;
335        for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); ++it) //!< Set the font for each overlay.
336        {
337            it->second->overlay->setFont(font);
338        }
339        return true;
340    }
341
342    void NotificationQueue::scroll(const Vector2 pos)
343    {
344        for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); ++it) //!< Scroll each overlay.
345        {
346            it->second->overlay->scroll(pos);
347        }
348    }
349
350    /**
351    @brief
352        Adds a Notification, to the queue.
353        It inserts it into the storage containers, creates an corresponding overlay and a container.
354    @param notification
355        The Notification.
356    @param time
357        The time.
358    */
359    void NotificationQueue::addNotification(Notification* notification, const std::time_t & time)
360    {
361        NotificationOverlayContainer* container = new NotificationOverlayContainer;
362        container->overlay = new NotificationOverlay(this, notification);
363        container->notification = notification;
364        container->time = time;
365        std::string timeString = std::ctime(&time);
366        timeString.erase(timeString.length()-1);
367        char buffer[64]; //TDO: Very un-nice.
368        std::sprintf(buffer,"%x",(unsigned long)notification); //TDO: Use other conversion to avoid 64bit problems.
369        std::string addressString = buffer;
370        container->name = "NotificationOverlay(" + timeString + ")&" + addressString;
371       
372        this->containers_.insert(container);
373        this->overlays_[notification] = container;
374        this->insertElement(container->overlay, container->name);
375        this->size_= this->size_+1;
376
377        container->overlay->scroll(Vector2(0.0,(1.1*this->getFontSize())*(this->getSize()-1)));
378    }
379   
380    /**
381    @brief
382        Removes a container from the queue.
383    @param container
384        A pointer to the container.
385    @return
386        Returns true if successful.
387    */
388    bool NotificationQueue::removeContainer(NotificationOverlayContainer* container)
389    {
390        if(this->size_ == 0) //!< You cannot remove anything if the queue is empty.
391            return false;
392       
393        this->removeElement(container->name);
394        this->containers_.erase(container);
395        this->overlays_.erase(container->notification);
396        delete container->overlay;
397        delete container;
398        this->size_= this->size_-1;
399       
400        return true;
401    }
402   
403    /**
404    @brief
405        Clears the queue by removing all containers.
406    */
407    void NotificationQueue::clear(void)
408    {
409        std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it = this->containers_.begin();
410        while(it != this->containers_.end())
411        {
412            this->removeContainer(*it);
413            it = this->containers_.begin(); //TDO: Needed?
414        }
415    }
416
417}
Note: See TracBrowser for help on using the repository browser.