Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/notifications/NotificationManager.cc @ 7413

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

Removing some TODO comments.
Better handling of duplicate name in Notificationlayer.lua.
Moving StringCompare object from NotificationListener to StringUtils.

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