Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

Cleanup in Script. Some more documenting in Notifications module.

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