Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

NotificationQueue now disappears if there are no notifications to be displayed. Also: "Fixed" Seg-fault.

  • Property svn:eol-style set to native
File size: 11.2 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
31    @brief Implementation of the NotificationManager class.
32*/
33
34#include "NotificationManager.h"
35
36#include "core/CoreIncludes.h"
37#include "core/GUIManager.h"
38#include "util/ScopedSingletonManager.h"
39#include "interfaces/NotificationListener.h"
40#include "Notification.h"
41#include "NotificationQueue.h"
42
43namespace orxonox
44{
45
46    const std::string NotificationManager::ALL("all");
47    const std::string NotificationManager::NONE("none");
48
49    ManageScopedSingleton(NotificationManager, ScopeID::Graphics, false);
50
51    /**
52    @brief
53        Constructor. Registers the Object.
54    */
55    NotificationManager::NotificationManager()
56    {
57        RegisterRootObject(NotificationManager);
58
59        this->highestIndex_ = 0;
60
61        if(GameMode::showsGraphics())
62        {
63            GUIManager::getInstance().loadGUI("NotificationLayer");
64
65            // Create first queue:
66            this->queue_ = new NotificationQueue("all");
67        }
68    }
69
70    /**
71    @brief
72        Destructor.
73    */
74    NotificationManager::~NotificationManager()
75    {
76        //this->queue_->destroy();
77    }
78
79    /**
80    @brief
81        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationListeners associated with its sender.
82    @param notification
83        The Notification to be registered.
84    @return
85        Returns true if successful.
86    */
87    bool NotificationManager::registerNotification(Notification* notification)
88    {
89
90        if(notification == NULL) //!< A NULL-Notification cannot be registered.
91            return false;
92
93        std::time_t time = std::time(0); //TODO: Doesn't this expire? //!< Get current time.
94
95        this->allNotificationsList_.insert(std::pair<std::time_t,Notification*>(time,notification));
96
97        if(notification->getSender() == NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
98            return true;
99
100        bool all = false;
101        if(notification->getSender() == ALL) // If all are the sender, then the Notifications is added to every NotificationListener.
102            all = true;
103
104        // Insert the notification in all listeners that have its sender as target.
105        for(std::map<NotificationListener*,int>::iterator it = this->listenerList_.begin(); it != this->listenerList_.end(); it++) // Iterate through all listeners.
106        {
107            std::set<std::string> set = it->first->getTargetsSet();
108            if(all || set.find(notification->getSender()) != set.end() || set.find(ALL) != set.end()) //TODO: Make sure this works.
109            {
110                this->notificationLists_[it->second]->insert(std::pair<std::time_t,Notification*>(time,notification)); // Insert the Notification in the Notifications list of the current NotificationListener.
111                it->first->update(notification, time); // Update the listener.
112                std::map<Notification*, unsigned int>::iterator counterIt = this->listenerCounter_.find(notification);
113                if(counterIt == this->listenerCounter_.end())
114                    this->listenerCounter_[notification] = 1;
115                else
116                    this->listenerCounter_[notification] = counterIt->second + 1;
117            }
118        }
119
120        COUT(4) << "Notification registered with the NotificationManager." << std::endl;
121
122        return true;
123    }
124
125    /**
126    @brief
127        Unregisters a Notification within the NotificationManager.
128    @param notification
129        A pointer to the Notification to be unregistered.
130    @param listener
131        A pointer to the NotificationListener the Notification is unregistered for.
132    */
133    void NotificationManager::unregisterNotification(Notification* notification, NotificationListener* listener)
134    {
135        assert(notification);
136        assert(listener);
137
138        // 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.
139        if(this->removeNotification(notification, *(this->notificationLists_.find(this->listenerList_.find(listener)->second)->second)))
140            this->listenerCounter_[notification] = this->listenerCounter_[notification] - 1;
141
142        // If the Notification is no longer present in any of the NotificationListeners it can be removed from the map of all Notifications and be destroyed.
143        if(this->listenerCounter_[notification] == (unsigned int) 0)
144        {
145            this->removeNotification(notification, this->allNotificationsList_);
146            this->listenerCounter_.erase(notification);
147            notification->destroy();
148        }
149
150        COUT(4) << "Notification unregistered with the NotificationManager." << std::endl;
151    }
152
153    /**
154    @brief
155        Helper method that removes an input notification form an input map.
156    @param notification
157        A pointer to the notification to be removed.
158    @param map
159        The map the notification should be removed from.
160    @return
161        Returns true if successful.
162    */
163    //TODO: Needed?
164    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
165    {
166        // Iterates through all items in the map until the Notification is found.
167        //TODO: Do more efficiently?
168        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
169        {
170            if(it->second == notification)
171            {
172                map.erase(it);
173                return true;
174            }
175        }
176        return false;
177    }
178
179    /**
180    @brief
181        Registers a NotificationListener within the NotificationManager.
182    @param listener
183        The NotificationListener to be registered.
184    @return
185        Returns true if successful.
186    */
187    bool NotificationManager::registerListener(NotificationListener* listener)
188    {
189        this->highestIndex_ += 1;
190        int index = this->highestIndex_;
191
192        this->listenerList_[listener] = index; // Add the NotificationListener to the list of listeners.
193
194        std::set<std::string> set = listener->getTargetsSet(); //TODO: Does this work?
195
196        // 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.
197        if(set.find(ALL) != set.end())
198        {
199            this->notificationLists_[index] = &this->allNotificationsList_;
200            COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
201            return true;
202        }
203
204        this->notificationLists_[index] = new std::multimap<std::time_t,Notification*>;
205        std::multimap<std::time_t,Notification*> map = *this->notificationLists_[index];
206
207        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationListener.
208        for(std::multimap<std::time_t,Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
209        {
210            if(set.find(it->second->getSender()) != set.end()) // Checks whether the overlay has the sender of the current notification as target.
211            {
212                map.insert(std::pair<std::time_t, Notification*>(it->first, it->second));
213                std::map<Notification*, unsigned int>::iterator counterIt = this->listenerCounter_.find(it->second);
214                if(counterIt == this->listenerCounter_.end())
215                    this->listenerCounter_[it->second] = 1;
216                else
217                    this->listenerCounter_[it->second] = counterIt->second + 1;
218            }
219        }
220
221        listener->update(); // Update the listener.
222
223        COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
224
225        return true;
226    }
227
228    /**
229    @brief
230        Unregisters a NotificationListener withing the NotificationManager.
231    */
232    void NotificationManager::unregisterListener(NotificationListener* listener)
233    {
234        assert(listener);
235
236        int identifier = this->listenerList_.find(listener)->second;
237        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(identifier)->second;
238
239        // Make sure all Notifications are removed.
240        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
241        while(it != map->end())
242        {
243            this->unregisterNotification(it->second, listener);
244            it = map->begin();
245        }
246
247        this->listenerList_.erase(listener);
248        this->notificationLists_.erase(identifier);
249
250        // If the map is not the map of all notifications, delete it.
251        if(map != &this->allNotificationsList_)
252            delete map;
253
254        COUT(4) << "NotificationListener unregistered with the NotificationManager." << std::endl;
255    }
256
257    /**
258    @brief
259        Fetches the Notifications for a specific NotificationListener in a specified timeframe.
260    @param listener
261        The NotificationListener the Notifications are fetched for.
262    @param map
263        A multimap, in which the notifications are stored.
264    @param timeFrameStart
265        The start time of the timeframe.
266    @param timeFrameEnd
267        The end time of the timeframe.
268    @return
269        Returns true if successful.
270    */
271    bool NotificationManager::getNotifications(NotificationListener* listener, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
272    {
273        if(listener == NULL || map == NULL)
274            return false;
275
276        std::multimap<std::time_t,Notification*>* notifications = this->notificationLists_[this->listenerList_[listener]]; // The Notifications for the input NotificationListener.
277
278        if(notifications == NULL) // Returns NULL, if there are no Notifications.
279            return true;
280
281        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
282        itLowest = notifications->lower_bound(timeFrameStart);
283        itHighest = notifications->upper_bound(timeFrameStart);
284
285        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time Frame to the end of it.
286        {
287            map->insert(std::pair<std::time_t,Notification*>(it->first,it->second)); // Add the found Notifications to the map.
288        }
289
290        return true;
291    }
292
293}
Note: See TracBrowser for help on using the repository browser.