- Timestamp:
- Sep 11, 2010, 10:20:44 AM (15 years ago)
- Location:
- code/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
code/trunk
- Property svn:mergeinfo changed
/code/branches/notifications (added) merged: 7319,7324,7326,7338-7343,7348-7349,7351,7354-7355,7358-7360,7362,7395,7398-7400
- Property svn:mergeinfo changed
-
code/trunk/src/modules/notifications/NotificationQueue.cc
r7401 r7403 28 28 29 29 /** 30 @file 30 @file NotificationQueue.cc 31 31 @brief Implementation of the NotificationQueue class. 32 32 */ … … 34 34 #include "NotificationQueue.h" 35 35 36 #include <map> 37 #include <sstream> 38 39 #include "core/CoreIncludes.h" 40 #include "core/GUIManager.h" 41 #include "core/LuaState.h" 36 42 #include "util/Convert.h" 37 #include "core/CoreIncludes.h" 38 #include "core/XMLPort.h" 39 #include "NotificationOverlay.h" 40 #include "NotificationManager.h" 43 #include "util/SubString.h" 44 45 #include "Notification.h" 41 46 42 47 namespace orxonox 43 48 { 44 49 45 CreateFactory(NotificationQueue);46 47 const std::string NotificationQueue::DEFAULT_FONT("VeraMono");48 const Vector2 NotificationQueue::DEFAULT_POSITION(0.0,0.0);49 const float NotificationQueue::DEFAULT_FONT_SIZE = 0.025f;50 51 50 /** 52 51 @brief 53 52 Constructor. Creates and initializes the object. 54 */ 55 NotificationQueue::NotificationQueue(BaseObject* creator) : OverlayGroup(creator) 53 @param name 54 The name of the new NotificationQueue. 55 @param senders 56 The senders that are targets of this NotificationQueue, i.e. the names of senders whose Notifications this NotificationQueue displays. 57 The senders need to be seperated by commas. 58 @param size 59 The size (the maximum number of displayed Notifications) of this NotificationQueue. 60 @param displayTime 61 The time during which a Notification is (at most) displayed. 62 */ 63 NotificationQueue::NotificationQueue(const std::string& name, const std::string& senders, unsigned int size, unsigned int displayTime) 56 64 { 57 65 this->registered_ = false; 58 66 59 RegisterObject(NotificationQueue); 60 this->initialize(); 61 } 62 63 /** 64 @brief 65 Destructor. 66 */ 67 NotificationQueue::~NotificationQueue() 68 { 69 this->targets_.clear(); 70 this->clear(); 71 72 if(this->registered_) 73 NotificationManager::getInstance().unregisterListener(this); 74 } 75 76 /** 77 @brief 78 Initializes the object. 79 Registers the object, initializes variables, sets default values and registers the queue with the NotificationManager. 80 */ 81 void NotificationQueue::initialize(void) 82 { 67 RegisterRootObject(NotificationQueue); 68 69 // Initialize. 83 70 this->size_ = 0; 84 71 this->tickTime_ = 0.0; 85 72 86 NotificationManager::getInstance().registerListener(this); 73 // Sets the input values. 74 this->setTargets(senders); 75 this->name_ = name; 76 this->maxSize_ = size; 77 this->setDisplayTime(displayTime); 78 79 //TODO: Destroy if registration fails? 80 81 // Register the NotificationQueue with the NotificationManager. 82 bool queueRegistered = NotificationManager::getInstance().registerQueue(this); 87 83 this->registered_ = true; 88 } 89 90 /** 91 @brief 92 Sets the defaults. 93 */ 94 void NotificationQueue::setDefaults(void) 95 { 96 this->setMaxSize(DEFAULT_SIZE); 97 this->setNotificationLength(DEFAULT_LENGTH); 98 this->setDisplayTime(DEFAULT_DISPLAY_TIME); 99 this->setPosition(DEFAULT_POSITION); 100 101 this->setTargets(NotificationManager::ALL); 102 103 this->setFontSize(DEFAULT_FONT_SIZE); 104 this->setFont(DEFAULT_FONT); 105 } 106 107 /** 108 @brief 109 Method for creating a NotificationQueue object through XML. 110 */ 111 void NotificationQueue::XMLPort(Element& xmlelement, XMLPort::Mode mode) 112 { 113 SUPER(NotificationQueue, XMLPort, xmlelement, mode); 114 115 this->setDefaults(); 116 117 XMLPortParam(NotificationQueue, "maxSize", setMaxSize, getMaxSize, xmlelement, mode); 118 XMLPortParam(NotificationQueue, "notificationLength", setNotificationLength, getNotificationLength, xmlelement, mode); 119 XMLPortParam(NotificationQueue, "displayTime", setDisplayTime, getDisplayTime, xmlelement, mode); 120 XMLPortParam(NotificationQueue, "targets", setTargets, getTargets, xmlelement, mode); 121 XMLPortParam(NotificationQueue, "font", setFont, getFont, xmlelement, mode); 122 XMLPortParam(NotificationQueue, "fontSize", setFontSize, getFontSize, xmlelement, mode); 123 XMLPortParam(NotificationQueue, "position", setPosition, getPosition, xmlelement, mode); 84 if(!queueRegistered) // If the registration has failed. 85 { 86 this->registered_ = false; 87 COUT(1) << "Error: Notification Queue '" << this->getName() << "' could not be registered." << std::endl; 88 return; 89 } 90 91 this->create(); // Creates the NotificationQueue in lua. 92 93 // register the NotificationQueue as NotificationListener with the NotificationManager. 94 bool listenerRegistered = NotificationManager::getInstance().registerListener(this); 95 if(!listenerRegistered) // If the registration has failed. 96 { 97 this->registered_ = false; 98 // Remove the NotificationQueue in lua. 99 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() + "\")"); 100 NotificationManager::getInstance().unregisterQueue(this); 101 COUT(1) << "Error: Notification Queue '" << this->getName() << "' could not be registered." << std::endl; 102 return; 103 } 124 104 125 105 COUT(3) << "NotificationQueue '" << this->getName() << "' created." << std::endl; 106 } 107 108 /** 109 @brief 110 Destructor. 111 */ 112 NotificationQueue::~NotificationQueue() 113 { 114 this->targets_.clear(); 115 116 if(this->registered_) // If the 117 { 118 this->clear(); 119 120 // Unregister with the NotificationManager. 121 NotificationManager::getInstance().unregisterListener(this); 122 NotificationManager::getInstance().unregisterQueue(this); 123 124 // Remove the NotificationQueue in lua. 125 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeQueue(\"" + this->getName() + "\")"); 126 } 127 } 128 129 /** 130 @brief 131 Creates the NotificationQueue in lua. 132 */ 133 void NotificationQueue::create(void) 134 { 135 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.createQueue(\"" + this->getName() + "\", " + multi_cast<std::string>(this->getMaxSize()) + ")"); 126 136 } 127 137 … … 134 144 void NotificationQueue::tick(float dt) 135 145 { 136 this->tickTime_ += dt; // !<Add the time interval that has passed to the time counter.137 if(this->tickTime_ >= 1.0) // !<If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick.138 { 139 this->timeLimit_.time = std::time(0)-this->displayTime_; // !<Container containig the current time.140 141 std::multiset<Notification OverlayContainer*, NotificationOverlayContainerCompare>::iterator it;142 it = this->containers_.begin();143 while(it != this-> containers_.upper_bound(&this->timeLimit_)) //!< Iterate through all elements whose creation time is smaller than the current time minus the display time.146 this->tickTime_ += dt; // Add the time interval that has passed to the time counter. 147 if(this->tickTime_ >= 1.0) // If the time counter is greater than 1s all Notifications that have expired are removed, if it is smaller we wait to the next tick. 148 { 149 this->timeLimit_.time = std::time(0)-this->displayTime_; // Container containig the current time. 150 151 std::multiset<NotificationContainer*, NotificationContainerCompare>::iterator it = this->ordering_.begin(); 152 // Iterate through all elements whose creation time is smaller than the current time minus the display time. 153 while(it != this->ordering_.upper_bound(&this->timeLimit_)) 144 154 { 145 this->removeContainer(*it);146 this->scroll(Vector2(0.0f,-(1.1f*this->getFontSize())));147 it = this->containers_.begin(); //TODO: Needed?155 NotificationContainer* temp = *it; 156 it++; 157 this->remove(temp); // Remove the Notifications that have expired. 148 158 } 149 159 150 this->tickTime_ = 0.0f; //!<Reset time counter.160 this->tickTime_ = this->tickTime_ - (int)this->tickTime_; // Reset time counter. 151 161 } 152 162 } … … 155 165 @brief 156 166 Updates the NotificationQueue. 157 Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting the inthe queue.167 Updates by clearing the queue and requesting all relevant Notifications from the NotificationManager and inserting them into the queue. 158 168 */ 159 169 void NotificationQueue::update(void) … … 161 171 this->clear(); 162 172 163 std::multimap<std::time_t,Notification*>* notifications = new std::multimap<std::time_t,Notification*>; 164 if(!NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_)) //!< Get the Notifications sent in the interval form now to minus the display time. 165 { 166 COUT(1) << "NotificationQueue update failed due to undetermined cause." << std::endl; 167 return; 168 } 169 170 if(notifications->empty()) 171 return; 172 173 for(std::multimap<std::time_t,Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++) //!> Add all Notifications. 174 { 175 this->addNotification(it->second, it->first); 173 std::multimap<std::time_t, Notification*>* notifications = new std::multimap<std::time_t, Notification*>; 174 // Get the Notifications sent in the interval from now to now minus the display time. 175 NotificationManager::getInstance().getNotifications(this, notifications, this->displayTime_); 176 177 if(!notifications->empty()) 178 { 179 // Add all Notifications. 180 for(std::multimap<std::time_t, Notification*>::iterator it = notifications->begin(); it != notifications->end(); it++) 181 this->push(it->second, it->first); 176 182 } 177 183 … … 191 197 void NotificationQueue::update(Notification* notification, const std::time_t & time) 192 198 { 193 this->addNotification(notification, time); 194 195 std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it; 196 while(this->getSize() > this->getMaxSize()) 197 { 198 it = this->containers_.begin(); 199 this->removeContainer(*it); 200 this->scroll(Vector2(0.0f,-(1.1f*this->getFontSize()))); 201 } 202 203 COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notifications has been added." << std::endl; 199 this->push(notification, time); 200 201 COUT(4) << "NotificationQueue '" << this->getName() << "' updated. A new Notification has been added." << std::endl; 202 } 203 204 /** 205 @brief 206 Adds (pushes) a Notification to the NotificationQueue. 207 It inserts it into the storage containers, creates a corresponding container and pushes the Notification message to the GUI. 208 @param notification 209 The Notification to be pushed. 210 @param time 211 The time when the Notification has been sent. 212 */ 213 void NotificationQueue::push(Notification* notification, const std::time_t & time) 214 { 215 NotificationContainer* container = new NotificationContainer; 216 container->notification = notification; 217 container->time = time; 218 219 // If the maximum size of the NotificationQueue has been reached the last (least recently added) Notification is removed. 220 if(this->getSize() >= this->getMaxSize()) 221 this->pop(); 222 223 this->size_++; 224 225 this->ordering_.insert(container); 226 // Insert the Notification at the begin of the list (vector, actually). 227 this->notifications_.insert(this->notifications_.begin(), container); 228 229 // Push the Notification to the GUI. 230 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.pushNotification(\"" + this->getName() + "\", \"" + notification->getMessage() + "\")"); 231 } 232 233 /** 234 @brief 235 Removes (pops) the least recently added Notification form the NotificationQueue. 236 */ 237 void NotificationQueue::pop(void) 238 { 239 NotificationContainer* container = this->notifications_.back(); 240 this->ordering_.erase(container); 241 this->notifications_.pop_back(); 242 243 this->size_--; 244 245 delete container; 246 247 // Pops the Notification from the GUI. 248 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.popNotification(\"" + this->getName() + "\")"); 249 } 250 251 /** 252 @brief 253 Removes the Notification that is stored in the input NotificationContainer. 254 @param container 255 The NotificationContainer with the Notification to be removed. 256 */ 257 void NotificationQueue::remove(NotificationContainer* container) 258 { 259 std::vector<NotificationContainer*>::iterator it = std::find(this->notifications_.begin(), this->notifications_.end(), container); 260 // Get the index at which the Notification is. 261 std::vector<NotificationContainer*>::difference_type index = it - this->notifications_.begin (); 262 this->ordering_.erase(container); 263 this->notifications_.erase(it); 264 265 this->size_--; 266 267 delete container; 268 269 // Removes the Notification from the GUI. 270 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.removeNotification(\"" + this->getName() + "\", " + multi_cast<std::string>(index) + ")"); 271 } 272 273 /** 274 @brief 275 Clears the NotificationQueue by removing all NotificationContainers. 276 */ 277 void NotificationQueue::clear(void) 278 { 279 this->ordering_.clear(); 280 // Delete all NotificationContainers in the list. 281 for(std::vector<NotificationContainer*>::iterator it = this->notifications_.begin(); it != this->notifications_.end(); it++) 282 delete *it; 283 284 this->notifications_.clear(); 285 286 this->size_ = 0; 287 288 // Clear the NotificationQueue in the GUI. 289 GUIManager::getInstance().getLuaState()->doString("NotificationLayer.clearQueue(\"" + this->getName() + "\")"); 290 } 291 292 /** 293 @brief 294 Sets the name of the NotificationQueue. 295 @param name 296 The name to be set. 297 */ 298 void NotificationQueue::setName(const std::string& name) 299 { 300 this->name_ = name; 204 301 } 205 302 … … 209 306 @param size 210 307 The size to be set. 211 @return 212 Returns true if successful. 213 */ 214 bool NotificationQueue::setMaxSize(int size) 215 { 216 if(size < 0) 217 return false; 308 */ 309 void NotificationQueue::setMaxSize(unsigned int size) 310 { 311 if(this->maxSize_ == size) 312 return; 313 218 314 this->maxSize_ = size; 219 this->update(); 220 return true; 221 } 222 223 /** 224 @brief 225 Sets the maximum number of characters a Notification message displayed by this queue is allowed to have. 226 @param length 227 The length to be set. 228 @return 229 Returns true if successful. 230 */ 231 bool NotificationQueue::setNotificationLength(int length) 232 { 233 if(length < 0) 234 return false; 235 this->notificationLength_ = length; 236 this->update(); 237 return true; 315 316 if(this->registered_) 317 this->update(); 238 318 } 239 319 … … 246 326 Returns true if successful. 247 327 */ 248 bool NotificationQueue::setDisplayTime(int time) 249 { 250 if(time < 0) 251 return false; 328 void NotificationQueue::setDisplayTime(unsigned int time) 329 { 330 if(this->displayTime_ == time) 331 return; 332 252 333 this->displayTime_ = time; 253 this->update(); 254 return true; 255 } 256 257 /** 258 @brief 259 Produces all targets concatinated as string, with kommas (',') as seperators. 260 @param string 261 Pointer to a string which will be used by the method to fill with the concatination of the targets. 334 335 if(this->registered_) 336 this->update(); 337 } 338 339 /** 340 @brief 341 Produces all targets of the NotificationQueue concatinated as string, with kommas (',') as seperators. 262 342 @return 263 Returns true if successful. 264 */ 265 bool NotificationQueue::getTargets(std::string* string) const 266 { 267 if(string == NULL) 268 { 269 COUT(4) << "Input string must have memory allocated." << std::endl; 270 return false; 271 } 272 string->clear(); 343 Returns the targets as a string. 344 */ 345 const std::string& NotificationQueue::getTargets(void) const 346 { 347 std::stringstream stream; 273 348 bool first = true; 274 for(std::set<std::string>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++) //!< Iterate through the set of targets. 349 // Iterate through the set of targets. 350 for(std::set<std::string, NotificationListenerStringCompare>::const_iterator it = this->targets_.begin(); it != this->targets_.end(); it++) 275 351 { 276 352 if(!first) 277 { 278 *string += ','; 279 } 353 stream << ", "; 280 354 else 281 {282 355 first = false; 283 } 284 *string += *it; 285 } 286 287 return true; 288 } 289 290 /** 291 @brief 292 Sets the targets of the queue. 356 stream << *it; 357 } 358 359 return *(new std::string(stream.str())); 360 } 361 362 /** 363 @brief 364 Sets the targets of the NotificationQueue. 293 365 The targets are the senders whose Notifications are displayed in this queue. 294 366 @param targets 295 367 Accepts a string of targets, each seperated by commas (','), spaces are ignored. 296 @return 297 Returns true if successful. 298 */ 299 bool NotificationQueue::setTargets(const std::string & targets) 368 */ 369 void NotificationQueue::setTargets(const std::string & targets) 300 370 { 301 371 this->targets_.clear(); 302 372 303 std::string* pTemp; 304 unsigned int index = 0; 305 while( index < targets.size() ) //!< Go through the string, character by character until the end is reached. 306 { 307 pTemp = new std::string(); 308 while(index < targets.size() && targets[index] != ',' && targets[index] != ' ') 309 { 310 *pTemp += targets[index]; 311 index++; 312 } 313 index++; 314 this->targets_.insert(*pTemp); 315 } 316 317 return true; 318 } 319 320 /** 321 @brief 322 Sets the font size. 323 @param size 324 The font size. 325 @return 326 Returns true if successful. 327 */ 328 bool NotificationQueue::setFontSize(float size) 329 { 330 if(size <= 0) 331 return false; 332 this->fontSize_ = size; 333 for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); it++) //!< Set the font size for each overlay. 334 { 335 it->second->overlay->setFontSize(size); 336 } 337 return true; 338 } 339 340 /** 341 @brief 342 Sets the font. 343 @param font 344 The font. 345 @return 346 Returns true if successful. 347 */ 348 bool NotificationQueue::setFont(const std::string & font) 349 { 350 this->font_ = font; 351 for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); it++) //!< Set the font for each overlay. 352 { 353 it->second->overlay->setFont(font); 354 } 355 return true; 356 } 357 358 /** 359 @brief 360 Scrolls the NotificationQueue, meaning all NotificationOverlays are moved the input vector. 361 @param pos 362 The vector the NotificationQueue is scrolled. 363 */ 364 void NotificationQueue::scroll(const Vector2 pos) 365 { 366 for (std::map<Notification*, NotificationOverlayContainer*>::iterator it = this->overlays_.begin(); it != this->overlays_.end(); ++it) //!< Scroll each overlay. 367 { 368 it->second->overlay->scroll(pos); 369 } 370 } 371 372 /** 373 @brief 374 Aligns all the Notifications to the position of the NotificationQueue. 375 */ 376 void NotificationQueue::positionChanged(void) 377 { 378 int counter = 0; 379 for (std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it = this->containers_.begin(); it != this->containers_.end(); it++) //!< Set the position for each overlay. 380 { 381 (*it)->overlay->setPosition(this->getPosition()); 382 (*it)->overlay->scroll(Vector2(0.0f,(1.1f*this->getFontSize())*counter)); 383 counter++; 384 } 385 } 386 387 /** 388 @brief 389 Adds a Notification, to the queue. 390 It inserts it into the storage containers, creates an corresponding overlay and a container. 391 @param notification 392 The Notification. 393 @param time 394 The time. 395 */ 396 void NotificationQueue::addNotification(Notification* notification, const std::time_t & time) 397 { 398 NotificationOverlayContainer* container = new NotificationOverlayContainer; 399 container->overlay = new NotificationOverlay(this, notification); 400 container->notification = notification; 401 container->time = time; 402 std::string timeString = std::ctime(&time); 403 timeString.erase(timeString.length()-1); 404 const std::string& addressString = multi_cast<std::string>(reinterpret_cast<unsigned long>(notification)); 405 container->name = "NotificationOverlay(" + timeString + ")&" + addressString; 406 407 this->containers_.insert(container); 408 this->overlays_[notification] = container; 409 this->addElement(container->overlay); 410 this->size_= this->size_+1; 411 412 container->overlay->scroll(Vector2(0.0f,(1.1f*this->getFontSize())*(this->getSize()-1))); 413 } 414 415 /** 416 @brief 417 Removes a container from the queue. 418 @param container 419 A pointer to the container. 420 @return 421 Returns true if successful. 422 */ 423 bool NotificationQueue::removeContainer(NotificationOverlayContainer* container) 424 { 425 if(this->size_ == 0) //!< You cannot remove anything if the queue is empty. 426 return false; 427 428 // Unregister the NotificationQueue with the NotificationManager. 429 NotificationManager::getInstance().unregisterNotification(container->notification, this); 430 431 this->removeElement(container->overlay); 432 this->containers_.erase(container); 433 this->overlays_.erase(container->notification); 434 container->overlay->destroy(); 435 delete container; 436 this->size_= this->size_-1; 437 438 return true; 439 } 440 441 /** 442 @brief 443 Clears the queue by removing all containers. 444 */ 445 void NotificationQueue::clear(void) 446 { 447 std::multiset<NotificationOverlayContainer*, NotificationOverlayContainerCompare>::iterator it = this->containers_.begin(); 448 while(it != this->containers_.end()) 449 { 450 this->removeContainer(*it); 451 it = this->containers_.begin(); 373 SubString string = SubString(targets, ",", " ", false); 374 for(unsigned int i = 0; i < string.size(); i++) 375 this->targets_.insert(string[i]); 376 377 if(this->registered_) 378 { 379 NotificationManager::getInstance().unregisterListener(this); 380 NotificationManager::getInstance().registerListener(this); 452 381 } 453 382 } 454 383 455 384 } 385
Note: See TracChangeset
for help on using the changeset viewer.