Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/tutoriallevel2/src/modules/notifications/NotificationManager.cc @ 8446

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

Removing editMode stuff, since that doesn't work anymore and that won't change for quite some time.
Seperating CEGUI from NotificationQueue stuff by introducing a new NotificationQueue called the NotificationQueueCEGUI.

  • Property svn:eol-style set to native
File size: 17.5 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 NotificationManager.cc
31    @brief Implementation of the NotificationManager class.
32*/
33
34#include "NotificationManager.h"
35
36#include "core/command/ConsoleCommand.h"
37#include "core/CoreIncludes.h"
38#include "core/GameMode.h"
39#include "core/GUIManager.h"
40#include "core/LuaState.h"
41#include "util/Convert.h"
42#include "util/ScopedSingletonManager.h"
43
44#include "interfaces/NotificationListener.h"
45
46#include "Notification.h"
47#include "NotificationQueue.h"
48#include "NotificationQueueCEGUI.h"
49
50#include "ToluaBindNotifications.h"
51
52namespace orxonox
53{
54
55    // Register tolua_open function when loading the library.
56    DeclareToluaInterface(Notifications);
57
58    ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
59
60    /**
61    @brief
62        Constructor. Registers the Object.
63    */
64    NotificationManager::NotificationManager()
65    {
66        RegisterRootObject(NotificationManager);
67
68        COUT(3) << "NotificatioManager created." << std::endl;
69    }
70
71    /**
72    @brief
73        Destructor.
74    */
75    NotificationManager::~NotificationManager()
76    {
77        // Destroys all Notifications.
78        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it!= this->allNotificationsList_.end(); it++)
79            it->second->destroy();
80        this->allNotificationsList_.clear();
81
82        COUT(3) << "NotificationManager destroyed." << std::endl;
83    }
84
85    /**
86    @brief
87        Is called before the object is destroyed.
88    */
89    void NotificationManager::preDestroy(void)
90    {
91        // Destroys all NotificationQueues that have been registered with the NotificationManager.
92        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin();
93        while(it != this->queues_.end())
94        {
95            it->second->destroy();
96            it = this->queues_.begin();
97        }
98
99        this->queues_.clear();
100    }
101
102    /**
103    @brief
104        Creates and registers a Notification with the input message from the input sender.
105        This is called by the NotificationListener, whenever a new notification arrives.
106    @param message
107        The message of the new Notification.
108    @param sender
109        The name of the entity (of the collective) that sent the new Notification.
110    @return
111        Returns true if successful.
112    */
113    bool NotificationManager::registerNotification(const std::string& message, const std::string& sender, notificationMessageType::Value type)
114    {
115        // TODO: Do something with the type.
116        Notification* notification = new Notification(message, sender, type);
117        return this->registerNotification(notification);
118    }
119
120    /**
121    @brief
122        Executes the input command from the input sender.
123        This is called by the NotificationListener, whenever a new command arrives.
124    @param command
125        The command to be executed,
126    @param sender
127        The The name of the entity (of the collective) that sent the command.
128    */
129    bool NotificationManager::executeCommand(notificationCommand::Value command, const std::string& sender)
130    {
131        if(command == notificationCommand::clear)
132        {
133            this->commandClear(sender);
134            return true;
135        }
136
137        return false;
138    }
139
140    /**
141    @brief
142        The clear command. Clears all NotificationQueues that have its sender as a target.
143    @param sender
144        The sender of the clear command.
145    */
146    void NotificationManager::commandClear(const std::string& sender)
147    {
148        bool all = (sender == NotificationListener::ALL);
149        // Clear all NotificationQueues that have the input sender as target.
150        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
151        {
152            const std::set<std::string>& set = it->second->getTargetsSet();
153            // If either the sender is 'all', the NotificationQueue has as target all or the NotificationQueue has the input sender as a target.
154            if(all || set.find(NotificationListener::ALL) != set.end() || set.find(sender) != set.end())
155                it->second->tidy();
156        }
157    }
158   
159    /**
160    @brief
161        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationQueues associated with its sender.
162    @param notification
163        The Notification to be registered.
164    @return
165        Returns true if successful.
166    */
167    bool NotificationManager::registerNotification(Notification* notification)
168    {
169        assert(notification);
170
171        std::time_t time = std::time(0); // Get current time.
172
173        // Add the Notification to the list that holds all Notifications.
174        this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
175
176        if(notification->getSender() == NotificationListener::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
177            return true;
178
179        // If all are the sender, then the Notifications is added to every NotificationQueue.
180        bool all = (notification->getSender() == NotificationListener::ALL);
181
182        // Insert the Notification in all NotificationQueues that have its sender as target.
183        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); it++) // Iterate through all NotificationQueues.
184        {
185            const std::set<std::string>& set = it->second->getTargetsSet();
186            bool bAll = set.find(NotificationListener::ALL) != set.end();
187            // If either the Notification has as sender 'all', the NotificationQueue displays all Notifications or the NotificationQueue has the sender of the Notification as target.
188            if(all || bAll || set.find(notification->getSender()) != set.end())
189            {
190                if(!bAll)
191                    this->notificationLists_[it->second->getName()]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationQueue.
192                it->second->update(notification, time); // Update the NotificationQueue.
193            }
194        }
195
196        COUT(4) << "Notification (&" << notification << ") registered with the NotificationManager." << std::endl;
197
198        return true;
199    }
200
201    /**
202    @brief
203        Unregisters a Notification within the NotificationManager for a given NotificationQueue.
204    @param notification
205        A pointer to the Notification to be unregistered.
206    @param queue
207        A pointer to the NotificationQueue the Notification is unregistered for.
208    */
209    void NotificationManager::unregisterNotification(Notification* notification, NotificationQueue* queue)
210    {
211        assert(notification);
212        assert(queue);
213
214        // Remove the Notification from the list of Notifications of the input NotificationQueue.
215        this->removeNotification(notification, *(this->notificationLists_.find(queue->getName())->second));
216
217        COUT(4) << "Notification (&" << notification << ") unregistered with the NotificationManager from NotificationQueue " << queue->getName() << "." << std::endl;
218    }
219
220    /**
221    @brief
222        Helper method that removes an input Notification form an input map.
223    @param notification
224        A pointer to the Notification to be removed.
225    @param map
226        The map the Notification should be removed from.
227    @return
228        Returns true if successful.
229    */
230    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
231    {
232        // Iterates through all items in the map until the Notification is found.
233        //TODO: Do more efficiently?
234        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
235        {
236            if(it->second == notification)
237            {
238                map.erase(it);
239                return true;
240            }
241        }
242        return false;
243    }
244
245    /**
246    @brief
247        Fetches the Notifications for a specific NotificationQueue in a specified timeframe and stores them in the input map.
248    @param queue
249        The NotificationQueue the Notifications are fetched for.
250    @param map
251        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
252    @param timeFrameStart
253        The start time of the timeframe.
254    @param timeFrameEnd
255        The end time of the timeframe.
256    @return
257        Returns true if successful.
258    */
259    void NotificationManager::getNotifications(NotificationQueue* queue, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
260    {
261        assert(queue);
262        assert(map);
263
264        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
265
266        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
267        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
268        itLowest = notifications->lower_bound(timeFrameStart);
269        itHighest = notifications->upper_bound(timeFrameEnd);
270
271        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
272            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
273    }
274
275    /**
276    @brief
277        Fetches the newest Notifications for a specific NotificationQueue and stores them in the input map.
278    @param queue
279        The NotificationQueue the Notifications are fetched for.
280    @param map
281        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
282    @param numberOfNotifications
283        The number of newest Notifications to be got.
284    @return
285        Returns true if successful.
286    */
287    void NotificationManager::getNewestNotifications(NotificationQueue* queue, std::multimap<std::time_t, Notification*>* map, int numberOfNotifications)
288    {
289        assert(queue);
290        assert(map);
291
292        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[queue->getName()]; // All the Notifications for the input NotificationQueue.
293
294        if(!notifications->empty()) // If the list of Notifications is not empty.
295        {
296            std::multimap<std::time_t,Notification*>::iterator it = notifications->end();
297            for(int i = 0; i < numberOfNotifications; i++) // Iterate through the Notifications from the newest until we have the specified number of notifications.
298            {
299                it--;
300                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
301                if(it == notifications->begin())
302                    break;
303            }
304        }
305    }
306
307    /**
308    @brief
309        Registers a NotificationQueue.
310        This makes sure that the NotificationQueue can be accessed through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
311    @param queue
312        A pointer to the NotificationQueue to be registered.
313    @return
314        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
315    */
316    bool NotificationManager::registerQueue(NotificationQueue* queue)
317    {
318        assert(queue);
319
320        // If the NotificationQueue is already registered.
321        if(this->queues_.find(queue->getName()) != this->queues_.end())
322            return false;
323
324        this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)); // Add the NotificationQueue to the list of NotificationQueues.
325
326        const std::set<std::string>& set = queue->getTargetsSet();
327
328        // If all senders are the target of the NotificationQueue, then the list of Notifications for that specific NotificationQueue is the same as the list of all Notifications.
329        bool bAll = set.find(NotificationListener::ALL) != set.end();
330        std::multimap<std::time_t, Notification*>* map = NULL;
331        if(bAll)
332            this->notificationLists_[queue->getName()] = &this->allNotificationsList_;
333        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationQueues.
334        else
335        {
336            this->notificationLists_[queue->getName()] = new std::multimap<std::time_t, Notification*>;
337            map = this->notificationLists_[queue->getName()];
338        }
339
340        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationQueue.
341        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
342        {
343            if(!bAll && set.find(it->second->getSender()) != set.end()) // Checks whether the listener has the sender of the current Notification as target.
344                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second));
345        }
346
347        queue->update(); // Update the queue.
348       
349        COUT(4) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << std::endl;
350        return true;
351    }
352
353    /**
354    @brief
355        Unregisters a NotificationQueue.
356    @param queue
357        A pointer to the NotificationQueue to be unregistered.
358    */
359    void NotificationManager::unregisterQueue(NotificationQueue* queue)
360    {
361        assert(queue);
362
363        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(queue->getName())->second;
364
365        // If the map is not the map of all Notifications, make sure all Notifications are unregistered.
366        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
367        if(map != &this->allNotificationsList_)
368        {
369            while(it != map->end())
370            {
371                this->unregisterNotification(it->second, queue);
372                it = map->begin();
373            }
374            delete map;
375        }
376
377        // Remove the NotificationQueue from the list of NotificationQueues.
378        this->queues_.erase(queue->getName());
379        // Remove the Notifications list that was associated with the input NotificationQueue.
380        this->notificationLists_.erase(queue->getName());
381       
382        COUT(4) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << std::endl;
383    }
384
385    /**
386    @brief
387        Loads all the NotificationQueues that should exist.
388    */
389    void NotificationManager::loadQueues(void)
390    {
391        NotificationQueue* allQueue = new NotificationQueueCEGUI("all");
392        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.resizeQueue(\"all\", 0.5, 0, " + multi_cast<std::string>(allQueue->getMaxSize()) + ")");
393        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.moveQueue(\"all\", 0, 10, 0.3, 0)");
394
395        NotificationQueue* infoQueue = new NotificationQueueCEGUI("info", NotificationListener::ALL, 1, -1);
396        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.changeQueueFont(\"info\", 24, \"CCFFFF00\")");
397        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.resizeQueue(\"info\", 0.6, 0, " + multi_cast<std::string>(infoQueue->getMaxSize()) + ")");
398        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.moveQueue(\"info\", 0.2, 0, 0.8, 0)");
399        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.changeQueueAlignment(\"info\", \"HorzCentred\")");
400    }
401
402    /**
403    @brief
404        Creates a new NotificationQueue.
405        This is used in lua.
406    @param name
407        The name of the new NotificationQueue.
408    */
409    void NotificationManager::createQueue(const std::string& name)
410    {
411        new NotificationQueue(name);
412    }
413
414    /**
415    @brief
416        Get the NotificationQueue with the input name.
417    @param name
418        The name of the NotificationQueue.
419    @return
420        Returns a pointer to the NotificationQueue with the input name. Returns NULL if no NotificationQueue with such a name exists.
421    */
422    NotificationQueue* NotificationManager::getQueue(const std::string & name)
423    {
424        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
425        // Returns NULL if no such NotificationQueue exists.
426        if(it == this->queues_.end())
427            return NULL;
428
429        return (*it).second;
430    }
431
432}
Note: See TracBrowser for help on using the repository browser.