Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 7488 was 7488, checked in by dafrick, 15 years ago

Some more documentation.
Making NotificationManager Root scope, cleaning up, especially in Notification (now it's just a data structure anymore).

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