Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Some cleanup and documenting.
After some more extensive testing it seems to work, the code looks ok as well…

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