Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Done some selective testing and it finally seems to work.

  • Property svn:eol-style set to native
File size: 13.1 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#include "interfaces/NotificationListener.h"
42#include "Notification.h"
43#include "NotificationQueue.h"
44
45#include "ToluaBindNotifications.h"
46
47namespace orxonox
48{
49
50    const std::string NotificationManager::ALL("all");
51    const std::string NotificationManager::NONE("none");
52
53    // Register tolua_open function when loading the library.
54    DeclareToluaInterface(Notifications);
55
56    ManageScopedSingleton(NotificationManager, ScopeID::Graphics, false);
57
58    //TODO: Make work.
59    SetConsoleCommand("enterEditMode", &NotificationManager::enterEditMode);
60
61    /**
62    @brief
63        Constructor. Registers the Object.
64    */
65    NotificationManager::NotificationManager()
66    {
67        RegisterRootObject(NotificationManager);
68
69        this->highestIndex_ = 0;
70
71        ModifyConsoleCommand("enterEditMode").setObject(this);
72       
73        COUT(3) << "NotificatioManager created." << std::endl;
74    }
75
76    /**
77    @brief
78        Destructor.
79    */
80    NotificationManager::~NotificationManager()
81    {
82        ModifyConsoleCommand("enterEditMode").setObject(NULL);
83
84        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
85            it->second->destroy();
86       
87        COUT(3) << "NotificationManager destroyed." << std::endl;
88    }
89
90    void NotificationManager::preDestroy(void)
91    {
92        for(std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin(); it != this->queues_.end(); )
93        {
94            NotificationQueue* queue = (*it).second;
95            it++;
96            queue->destroy();
97        }
98        this->queues_.clear();
99    }
100
101    /**
102    @brief
103        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationListeners associated with its sender.
104    @param notification
105        The Notification to be registered.
106    @return
107        Returns true if successful.
108    */
109    bool NotificationManager::registerNotification(Notification* notification)
110    {
111        if(notification == NULL) // A NULL-Notification cannot be registered.
112            return false;
113
114        std::time_t time = std::time(0); //TODO: Doesn't this expire? //!< Get current time.
115
116        this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
117
118        if(notification->getSender() == NotificationManager::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
119            return true;
120
121        bool all = false;
122        if(notification->getSender() == NotificationManager::ALL) // If all are the sender, then the Notifications is added to every NotificationListener.
123            all = true;
124
125        // Insert the notification in all listeners that have its sender as target.
126        for(std::map<NotificationListener*,int>::iterator it = this->listenerList_.begin(); it != this->listenerList_.end(); it++) // Iterate through all listeners.
127        {
128            std::set<std::string, NotificationListenerStringCompare> set = it->first->getTargetsSet();
129            bool bAll = set.find(NotificationManager::ALL) != set.end();
130            if(all || bAll || set.find(notification->getSender()) != set.end()) //TODO: Make sure this works.
131            {
132                if(!bAll)
133                {
134                    this->notificationLists_[it->second]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the Notifications list of the current NotificationListener.
135                }
136                it->first->update(notification, time); // Update the listener.
137                std::map<Notification*, unsigned int>::iterator counterIt = this->listenerCounter_.find(notification);
138                if(counterIt == this->listenerCounter_.end())
139                    this->listenerCounter_[notification] = 1;
140                else
141                    this->listenerCounter_[notification] = counterIt->second + 1;
142            }
143        }
144
145        COUT(4) << "Notification (&" << notification << ") registered with the NotificationManager." << std::endl;
146
147        return true;
148    }
149
150    /**
151    @brief
152        Unregisters a Notification within the NotificationManager.
153    @param notification
154        A pointer to the Notification to be unregistered.
155    @param listener
156        A pointer to the NotificationListener the Notification is unregistered for.
157    */
158    void NotificationManager::unregisterNotification(Notification* notification, NotificationListener* listener)
159    {
160        assert(notification);
161        assert(listener);
162
163        // If the Notification was removed from the list of Notifications of the input NotificationListener, the counter for the Notification of the number of NotificationListeners it is present in is decremented.
164        if(this->removeNotification(notification, *(this->notificationLists_.find(this->listenerList_.find(listener)->second)->second)))
165            this->listenerCounter_[notification] = this->listenerCounter_[notification] - 1;
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.
202    */
203    bool NotificationManager::registerListener(NotificationListener* listener)
204    {
205        this->highestIndex_ += 1;
206        int index = this->highestIndex_;
207
208        this->listenerList_[listener] = index; // Add the NotificationListener to the list of listeners.
209
210        std::set<std::string, NotificationListenerStringCompare> set = listener->getTargetsSet();
211
212        // If all senders are the target of the listener, then the list of notification for that specific listener is te same as the list of all Notifications.
213        bool bAll = set.find(NotificationManager::ALL) != set.end();
214        std::multimap<std::time_t, Notification*>* map;
215        if(bAll)
216            this->notificationLists_[index] = &this->allNotificationsList_;
217        else
218        {
219            this->notificationLists_[index] = new std::multimap<std::time_t, Notification*>;
220            map = this->notificationLists_[index];
221        }
222
223        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationListener.
224        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
225        {
226            if(bAll || set.find(it->second->getSender()) != set.end()) // Checks whether the listener has the sender of the current notification as target.
227            {
228                if(!bAll)
229                    map->insert(std::pair<std::time_t, Notification*>(it->first, it->second));
230                std::map<Notification*, unsigned int>::iterator counterIt = this->listenerCounter_.find(it->second);
231                if(counterIt == this->listenerCounter_.end())
232                    this->listenerCounter_[it->second] = 1;
233                else
234                    this->listenerCounter_[it->second] = counterIt->second + 1;
235            }
236        }
237
238        listener->update(); // Update the listener.
239
240        COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
241
242        return true;
243    }
244
245    /**
246    @brief
247        Unregisters a NotificationListener withing the NotificationManager.
248    */
249    void NotificationManager::unregisterListener(NotificationListener* listener)
250    {
251        assert(listener);
252
253        int identifier = this->listenerList_.find(listener)->second;
254        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(identifier)->second;
255
256        // If the map is not the map of all notifications, make sure all Notifications are removed and delete it.
257        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
258        if(map != &this->allNotificationsList_)
259        {
260            while(it != map->end())
261            {
262                this->unregisterNotification(it->second, listener);
263                it = map->begin();
264            }
265            delete map;
266        }
267
268        this->listenerList_.erase(listener);
269        this->notificationLists_.erase(identifier);
270
271        COUT(4) << "NotificationListener unregistered with the NotificationManager." << std::endl;
272    }
273
274    /**
275    @brief
276        Fetches the Notifications for a specific NotificationListener in a specified timeframe.
277    @param listener
278        The NotificationListener the Notifications are fetched for.
279    @param map
280        A multimap, in which the notifications are stored.
281    @param timeFrameStart
282        The start time of the timeframe.
283    @param timeFrameEnd
284        The end time of the timeframe.
285    @return
286        Returns true if successful.
287    */
288    bool NotificationManager::getNotifications(NotificationListener* listener, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
289    {
290        if(listener == NULL || map == NULL)
291            return false;
292
293        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[this->listenerList_[listener]]; // The Notifications for the input NotificationListener.
294
295        if(notifications == NULL) // Returns false, if there are no Notifications.
296            return false;
297
298        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
299        itLowest = notifications->lower_bound(timeFrameStart);
300        itHighest = notifications->upper_bound(timeFrameEnd);
301
302        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time Frame to the end of it.
303            map->insert(std::pair<std::time_t, Notification*>(it->first,it->second)); // Add the found Notifications to the map.
304
305        return true;
306    }
307
308    void NotificationManager::loadQueues(void)
309    {
310        new NotificationQueue("all");
311    }
312
313    void NotificationManager::createQueue(const std::string& name)
314    {
315        new NotificationQueue(name);
316    }
317
318    NotificationQueue* NotificationManager::getQueue(const std::string & name)
319    {
320        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
321        if(it == this->queues_.end())
322            return NULL;
323
324        return (*it).second;
325    }
326
327    bool NotificationManager::registerQueue(NotificationQueue* queue)
328    {
329        return this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)).second;
330    }
331   
332    void NotificationManager::unregisterQueue(NotificationQueue* queue)
333    {
334        this->queues_.erase(queue->getName());
335    }
336
337    void NotificationManager::enterEditMode(void)
338    {
339        GUIManager::getInstance().hideGUI("NotificationLayer");
340        GUIManager::getInstance().showGUI("NotificationLayer", false, false);
341        GUIManager::getInstance().getLuaState()->doString("NotificationLayer.enterEditMode()");
342    }
343
344}
Note: See TracBrowser for help on using the repository browser.