Ticket #1245: notifications1.patch
File notifications1.patch, 84.8 KB (added by , 15 years ago) |
---|
-
headers/os/app/Notification.h
diff --git a/headers/os/app/Notification.h b/headers/os/app/Notification.h index 22d61ab..d11e4b1 100644
a b 6 6 #define _NOTIFICATION_H 7 7 8 8 9 #include <Archivable.h> 9 10 #include <Entry.h> 10 11 #include <List.h> 11 12 #include <String.h> … … enum notification_type { 22 23 class BBitmap; 23 24 24 25 25 class BNotification {26 class BNotification : public BArchivable { 26 27 public: 27 28 BNotification(notification_type type); 28 ~BNotification(); 29 BNotification(BMessage* archive); 30 virtual ~BNotification(); 31 32 status_t InitCheck() const; 33 34 static BArchivable* Instantiate(BMessage* archive); 35 virtual status_t Archive(BMessage* archive, bool deep = true) const; 29 36 30 37 notification_type Type() const; 31 38 32 const char* Application() const;33 void Set Application(const BString& app);39 const char* Group() const; 40 void SetGroup(const BString& group); 34 41 35 42 const char* Title() const; 36 43 void SetTitle(const BString& title); … … public: 61 68 const BBitmap* Icon() const; 62 69 status_t SetIcon(const BBitmap* icon); 63 70 71 status_t Send(bigtime_t timeout = -1); 72 64 73 private: 74 status_t fInitStatus; 75 65 76 notification_type fType; 66 BString f AppName;77 BString fGroup; 67 78 BString fTitle; 68 79 BString fContent; 69 80 BString fID; -
headers/os/app/Roster.h
diff --git a/headers/os/app/Roster.h b/headers/os/app/Roster.h index e55e518..50a6612 100644
a b 13 13 class BFile; 14 14 class BMimeType; 15 15 class BNodeInfo; 16 class BNotification;17 16 18 17 19 18 struct app_info { … … class BRoster { 117 116 void AddToRecentFolders(const entry_ref *folder, 118 117 const char *appSig = 0) const; 119 118 120 // notifications121 status_t Notify(const BNotification& notification,122 bigtime_t timeout = -1) const;123 124 119 // private/reserved stuff starts here 125 120 class Private; 126 121 -
headers/private/notification/AppUsage.h
diff --git a/headers/private/notification/AppUsage.h b/headers/private/notification/AppUsage.h index c245c77..2c42961 100644
a b 19 19 class BMessage; 20 20 class NotificationReceived; 21 21 22 typedef std::map<BString, NotificationReceived*> notif y_t;22 typedef std::map<BString, NotificationReceived*> notification_t; 23 23 24 24 class AppUsage : public BFlattenable { 25 25 public: 26 26 AppUsage(); 27 AppUsage( entry_ref ref,const char* name,27 AppUsage(const char* name, 28 28 bool allow = true); 29 29 ~AppUsage(); 30 30 … … public: 36 36 virtual status_t Unflatten(type_code code, const void* buffer, 37 37 ssize_t numBytes); 38 38 39 entry_ref Ref();40 39 const char* Name(); 41 40 bool Allowed(const char* title, notification_type type); 42 41 bool Allowed(); … … public: 45 44 void AddNotification(NotificationReceived* notification); 46 45 47 46 private: 48 entry_ref fRef;49 47 BString fName; 50 48 bool fAllow; 51 notif y_tfNotifications;49 notification_t fNotifications; 52 50 }; 53 51 54 52 #endif // _APP_USAGE_H -
headers/private/notification/Notifications.h
diff --git a/headers/private/notification/Notifications.h b/headers/private/notification/Notifications.h index 964b026..99a5dc4 100644
a b 12 12 // Messages 13 13 const uint32 kNotificationMessage = 'nssm'; 14 14 15 // Notification layout16 enum infoview_layout {17 TitleAboveIcon = 0,18 AllTextRightOfIcon = 119 };20 21 15 // Settings constants 22 16 extern const char* kSettingsDirectory; 23 17 extern const char* kFiltersSettings; … … extern const char* kLayoutName; 40 34 // Display default settings 41 35 const float kDefaultWidth = 300.0f; 42 36 const icon_size kDefaultIconSize = B_LARGE_ICON; 43 const infoview_layout kDefaultLayout = TitleAboveIcon;44 37 45 38 #endif // _NOTIFICATIONS_H -
src/bin/notify.cpp
diff --git a/src/bin/notify.cpp b/src/bin/notify.cpp index 7ad9170..c2030b6 100644
a b 10 10 11 11 #include <stdio.h> 12 12 #include <stdlib.h> 13 #include <string.h>14 13 15 14 #include <Application.h> 16 15 #include <Bitmap.h> … … 19 18 #include <Mime.h> 20 19 #include <Notification.h> 21 20 #include <Path.h> 22 #include <Roster.h>23 21 #include <TranslationUtils.h> 24 22 25 23 const char* kSignature = "application/x-vnd.Haiku-notify"; … … public: 52 50 private: 53 51 bool fHasGoodArguments; 54 52 notification_type fType; 55 char* fAppName;56 char*fTitle;57 char*fMsgId;53 BString fGroup; 54 BString fTitle; 55 BString fMsgId; 58 56 float fProgress; 59 57 bigtime_t fTimeout; 60 char*fIconFile;58 BString fIconFile; 61 59 entry_ref fFileRef; 62 char* fMessage;63 char* fApp;60 BString fContent; 61 BString fOnClickApp; 64 62 bool fHasFile; 65 63 entry_ref fFile; 66 64 BList* fRefs; … … NotifyApp::NotifyApp() 76 74 BApplication(kSignature), 77 75 fHasGoodArguments(false), 78 76 fType(B_INFORMATION_NOTIFICATION), 79 fAppName(NULL),80 fTitle(NULL),81 fMsgId(NULL),82 77 fProgress(0.0f), 83 fTimeout(0), 84 fIconFile(NULL), 85 fMessage(NULL), 86 fApp(NULL), 78 fTimeout(-1), 87 79 fHasFile(false) 88 80 { 89 81 fRefs = new BList(); … … NotifyApp::NotifyApp() 93 85 94 86 NotifyApp::~NotifyApp() 95 87 { 96 free(fAppName);97 free(fTitle);98 free(fMsgId);99 free(fIconFile);100 free(fMessage);101 free(fApp);102 103 88 for (int32 i = 0; void* item = fRefs->ItemAt(i); i++) 104 89 delete (BEntry*)item; 105 90 delete fRefs; 106 91 107 92 for (int32 i = 0; void* item = fArgv->ItemAt(i); i++) 108 free(item);93 delete (BString*)item; 109 94 delete fArgv; 110 95 } 111 96 … … NotifyApp::ArgvReceived(int32 argc, char** argv) 134 119 if (strncmp(kTypeNames[i], argument, strlen(argument)) == 0) 135 120 fType = (notification_type)i; 136 121 } 137 } else if (strcmp(option, " app") == 0)138 f AppName = strdup(argument);122 } else if (strcmp(option, "group") == 0) 123 fGroup = argument; 139 124 else if (strcmp(option, "title") == 0) 140 fTitle = strdup(argument);125 fTitle = argument; 141 126 else if (strcmp(option, "messageID") == 0) 142 fMsgId = strdup(argument);127 fMsgId = argument; 143 128 else if (strcmp(option, "progress") == 0) 144 129 fProgress = atof(argument); 145 130 else if (strcmp(option, "timeout") == 0) 146 131 fTimeout = atol(argument) * 1000000; 147 132 else if (strcmp(option, "icon") == 0) { 148 fIconFile = strdup(argument);133 fIconFile = argument; 149 134 150 if (get_ref_for_path(fIconFile , &fFileRef) < B_OK) {135 if (get_ref_for_path(fIconFile.String(), &fFileRef) < B_OK) { 151 136 fprintf(stderr, "Bad icon path!\n\n"); 152 137 return; 153 138 } 154 139 } else if (strcmp(option, "onClickApp") == 0) 155 f App = strdup(argument);140 fOnClickApp = argument; 156 141 else if (strcmp(option, "onClickFile") == 0) { 157 142 if (get_ref_for_path(argument, &fFile) != B_OK) { 158 143 fprintf(stderr, "Bad path for --onClickFile!\n\n"); … … NotifyApp::ArgvReceived(int32 argc, char** argv) 170 155 171 156 fRefs->AddItem(new BEntry(&ref)); 172 157 } else if (strcmp(option, "onClickArgv") == 0) 173 fArgv->AddItem( strdup(argument));158 fArgv->AddItem(new BString(argument)); 174 159 else { 175 160 // Unrecognized option 176 161 fprintf(stderr, "Unrecognized option --%s\n\n", option); … … NotifyApp::ArgvReceived(int32 argc, char** argv) 188 173 } 189 174 } 190 175 191 // Check for missing arguments 192 if (fAppName == NULL) { 193 fprintf(stderr, "Missing --app argument!\n\n"); 194 return; 195 } 196 if (fTitle == NULL) { 197 fprintf(stderr, "Missing --title argument!\n\n"); 198 return; 199 } 200 201 fMessage = strdup(argv[index]); 176 fContent = argv[index]; 202 177 fHasGoodArguments = true; 203 178 } 204 179 … … NotifyApp::_Usage() const 208 183 fprintf(stderr, "Usage: notify [OPTION]... [MESSAGE]\n" 209 184 "Send notifications to notification_server.\n" 210 185 " --type <type>\tNotification type,\n" 211 " \t <type> : ");186 " \t <type> - \"information\" is assumed by default: "); 212 187 213 188 for (int32 i = 0; kTypeNames[i]; i++) 214 189 fprintf(stderr, kTypeNames[i + 1] ? "%s|" : "%s\n", kTypeNames[i]); 215 190 216 191 fprintf(stderr, 217 " -- app <app name>\tApplication name\n"192 " --group <group>\tGroup\n" 218 193 " --title <title>\tMessage title\n" 219 194 " --messageID <msg id>\tMessage ID\n" 220 195 " --progress <float>\tProgress, value between 0.0 and 1.0 - if type is set to progress\n" … … NotifyApp::ReadyToRun() 256 231 { 257 232 if (HasGoodArguments()) { 258 233 BNotification notification(fType); 259 notification.SetApplication(fAppName); 260 notification.SetTitle(fTitle); 261 notification.SetContent(fMessage); 262 263 if (fMsgId != NULL) 234 if (fGroup != "") 235 notification.SetGroup(fGroup); 236 if (fTitle != "") 237 notification.SetTitle(fTitle); 238 if (fContent != "") 239 notification.SetContent(fContent); 240 241 if (fMsgId != "") 264 242 notification.SetMessageID(fMsgId); 265 243 266 244 if (fType == B_PROGRESS_NOTIFICATION) 267 245 notification.SetProgress(fProgress); 268 246 269 if (fIconFile != NULL) {247 if (fIconFile != "") { 270 248 BBitmap* bitmap = _GetBitmap(&fFileRef); 271 249 if (bitmap) { 272 250 notification.SetIcon(bitmap); … … NotifyApp::ReadyToRun() 274 252 } 275 253 } 276 254 277 if (f App != NULL)278 notification.SetOnClickApp(f App);255 if (fOnClickApp != "") 256 notification.SetOnClickApp(fOnClickApp); 279 257 280 258 if (fHasFile) 281 259 notification.SetOnClickFile(&fFile); … … NotifyApp::ReadyToRun() 289 267 } 290 268 291 269 for (int32 i = 0; void* item = fArgv->ItemAt(i); i++) { 292 const char* arg = (const char*)item;293 notification.AddOnClickArg(arg );270 BString* arg = (BString*)item; 271 notification.AddOnClickArg(arg->String()); 294 272 } 295 273 296 status_t ret = be_roster->Notify(notification,fTimeout);274 status_t ret = notification.Send(fTimeout); 297 275 if (ret != B_OK) { 298 276 fprintf(stderr, "Failed to deliver notification: %s\n", 299 277 strerror(ret)); -
src/kits/app/Jamfile
diff --git a/src/kits/app/Jamfile b/src/kits/app/Jamfile index cf85c79..d8008c1 100644
a b if $(RUN_WITHOUT_APP_SERVER) != 0 { 17 17 SubDirC++Flags $(defines) ; 18 18 } 19 19 20 UseLibraryHeaders icon ; 20 21 UsePrivateHeaders shared app interface kernel notification ; 21 22 UsePrivateSystemHeaders ; 22 23 -
src/kits/app/Notification.cpp
diff --git a/src/kits/app/Notification.cpp b/src/kits/app/Notification.cpp index 90c4f14..9d05f55 100644
a b 4 4 * 5 5 * Authors: 6 6 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 7 * Stephan Aßmus <superstippi@gmx.de>7 * Stephan Aßmus, superstippi@gmx.de 8 8 */ 9 9 10 10 … … 13 13 #include <new> 14 14 15 15 #include <stdlib.h> 16 #include <string.h> 16 17 #include <notification/Notifications.h> 17 18 18 19 #include <Bitmap.h> 19 20 #include <Message.h> 20 21 21 22 23 /*! \brief Creates a notification that's ready to be used. 24 25 \param type Notification type. 26 */ 22 27 BNotification::BNotification(notification_type type) 23 28 : 29 BArchivable(), 30 fInitStatus(B_OK), 24 31 fType(type), 32 fProgress(0.0f), 33 fFile(NULL), 34 fBitmap(NULL) 35 { 36 } 37 38 39 /*! \brief Creates a notification that's ready to be used. 40 41 \param archive Archived BNotification object. 42 */ 43 BNotification::BNotification(BMessage* archive) 44 : 45 BArchivable(archive), 46 fInitStatus(B_OK), 47 fProgress(0.0f), 25 48 fFile(NULL), 26 49 fBitmap(NULL) 27 50 { 51 int32 type; 52 if (archive->FindInt32("_type", &type) == B_OK) 53 fType = (notification_type)type; 54 else 55 fInitStatus = B_ERROR; 56 57 BString group; 58 if (archive->FindString("_group", &group) == B_OK) 59 SetGroup(group); 60 61 BString title; 62 if (archive->FindString("_title", &title) == B_OK) 63 SetTitle(title); 64 65 BString content; 66 if (archive->FindString("_content", &content) == B_OK) 67 SetContent(content); 68 69 BString messageID; 70 if (archive->FindString("_messageID", &messageID) == B_OK) 71 SetMessageID(messageID); 72 73 float progress; 74 if (type == B_PROGRESS_NOTIFICATION 75 && archive->FindFloat("_progress", &progress) == B_OK) 76 SetProgress(progress); 77 78 BString onClickApp; 79 if (archive->FindString("_onClickApp", &onClickApp) == B_OK) 80 SetOnClickApp(onClickApp); 81 82 entry_ref onClickFile; 83 if (archive->FindRef("_onClickFile", &onClickFile) == B_OK) 84 SetOnClickFile(&onClickFile); 85 86 status_t ret = B_OK; 87 BMessage icon; 88 if ((ret = archive->FindMessage("_icon", &icon)) == B_OK) { 89 BBitmap bitmap(&icon); 90 ret = bitmap.InitCheck(); 91 if (ret == B_OK) 92 ret = SetIcon(&bitmap); 93 } 28 94 } 29 95 30 96 97 /*! \brief Standard destructor. 98 */ 31 99 BNotification::~BNotification() 32 100 { 33 101 delete fFile; … … BNotification::~BNotification() 41 109 } 42 110 43 111 112 /*! \brief Returns initialization status. 113 */ 114 status_t 115 BNotification::InitCheck() const 116 { 117 return fInitStatus; 118 } 119 120 121 /*! \brief Returns a new BNotification object from @archive. 122 123 Returns a new BNotification object, allocated by new and created 124 with the version of the constructor that takes BMessage archive. 125 However, if the message doesn't contain an archived data for a 126 BNotification object, this method returns NULL. 127 128 \return BNotification object from @archive or NULL if it doesn't 129 contain a valid BNotification object. 130 */ 131 BArchivable* 132 BNotification::Instantiate(BMessage* archive) 133 { 134 if (validate_instantiation(archive, "BNotification")) 135 return new(std::nothrow) BNotification(archive); 136 137 return NULL; 138 } 139 140 141 /*! \brief Archives the BNotification in the BMessages @archive. 142 143 \sa BArchivable::Archive(), Instantiate() static function. 144 \return 145 - \c B_OK: Everything went fine. 146 - \c Other errors: Archiving has failed. 147 */ 148 status_t 149 BNotification::Archive(BMessage* archive, bool deep) const 150 { 151 status_t status = BArchivable::Archive(archive, deep); 152 153 if (status == B_OK) 154 status = archive->AddInt32("_type", (int32)fType); 155 156 if (status == B_OK && Group() != NULL) 157 status = archive->AddString("_group", Group()); 158 159 if (status == B_OK && Title() != NULL) 160 status = archive->AddString("_title", Title()); 161 162 if (status == B_OK && Content() != NULL) 163 status = archive->AddString("_content", Content()); 164 165 if (status == B_OK && MessageID() != NULL) 166 status = archive->AddString("_messageID", MessageID()); 167 168 if (status == B_OK && Type() == B_PROGRESS_NOTIFICATION) 169 status = archive->AddFloat("_progress", Progress()); 170 171 if (status == B_OK && OnClickApp() != NULL) 172 status = archive->AddString("_onClickApp", OnClickApp()); 173 174 if (status == B_OK && OnClickFile() != NULL) 175 status = archive->AddRef("_onClickFile", OnClickFile()); 176 177 if (status == B_OK) { 178 for (int32 i = 0; i < CountOnClickRefs(); i++) { 179 status = archive->AddRef("_onClickRef", OnClickRefAt(i)); 180 if (status != B_OK) 181 break; 182 } 183 } 184 185 if (status == B_OK) { 186 for (int32 i = 0; i < CountOnClickArgs(); i++) { 187 status = archive->AddString("_onClickArgv", OnClickArgAt(i)); 188 if (status != B_OK) 189 break; 190 } 191 } 192 193 if (status == B_OK) { 194 const BBitmap* icon = Icon(); 195 if (icon != NULL) { 196 BMessage iconArchive; 197 status = icon->Archive(&iconArchive); 198 if (status == B_OK) 199 archive->AddMessage("_icon", &iconArchive); 200 } 201 } 202 203 return status; 204 } 205 206 207 /*! \brief Notification's type. 208 209 \return A value of the notification_type enum that represents 210 notification type. 211 */ 44 212 notification_type 45 213 BNotification::Type() const 46 214 { … … BNotification::Type() const 48 216 } 49 217 50 218 219 /*! \brief Returns notification's group. 220 221 \return Notification's group. 222 */ 51 223 const char* 52 BNotification:: Application() const224 BNotification::Group() const 53 225 { 54 return fAppName; 226 if (fGroup == "") 227 return NULL; 228 return fGroup; 55 229 } 56 230 57 231 232 /*! \brief Sets notification's group. 233 234 Notifications can be grouped together setting the same group. 235 */ 58 236 void 59 BNotification::Set Application(const BString& app)237 BNotification::SetGroup(const BString& group) 60 238 { 61 f AppName = app;239 fGroup = group; 62 240 } 63 241 64 242 243 /*! \brief Returns notification's title. 244 245 \return Notification's title. 246 */ 65 247 const char* 66 248 BNotification::Title() const 67 249 { 250 if (fTitle == "") 251 return NULL; 68 252 return fTitle; 69 253 } 70 254 71 255 256 /*! \brief Set notification's title. 257 */ 72 258 void 73 259 BNotification::SetTitle(const BString& title) 74 260 { … … BNotification::SetTitle(const BString& title) 76 262 } 77 263 78 264 265 /*! \brief Returns notification's message. 266 267 \return Notification's message. 268 */ 79 269 const char* 80 270 BNotification::Content() const 81 271 { 272 if (fContent == "") 273 return NULL; 82 274 return fContent; 83 275 } 84 276 85 277 278 /*! \brief Sets notification's message. 279 */ 86 280 void 87 281 BNotification::SetContent(const BString& content) 88 282 { … … BNotification::SetContent(const BString& content) 90 284 } 91 285 92 286 287 /*! \brief Returns notification's message identifier. 288 289 \return Notification's message identifier. 290 */ 93 291 const char* 94 292 BNotification::MessageID() const 95 293 { 294 if (fID == "") 295 return NULL; 96 296 return fID; 97 297 } 98 298 99 299 300 /*! \brief Sets notification's message identifier. 301 */ 100 302 void 101 303 BNotification::SetMessageID(const BString& id) 102 304 { … … BNotification::SetMessageID(const BString& id) 104 306 } 105 307 106 308 309 /*! \brief Returns progress information. 310 311 If notification's type is \c B_PROGRESS_NOTIFICATION, returns a value 312 between 0.0 and 1.0 that represent progress percentage. 313 314 If notification's type is not \c B_PROGRESS_NOTIFICATION, returns -1. 315 316 \return Percentage if notification's type is B_PROGRESS_NOTIFICATION 317 or otherwise -1. 318 */ 107 319 float 108 320 BNotification::Progress() const 109 321 { 322 if (fType != B_PROGRESS_NOTIFICATION) 323 return -1; 110 324 return fProgress; 111 325 } 112 326 113 327 328 /*! \brief Sets progress information. 329 330 Sets progress percentage, this information will be used only 331 if notification's type is \c B_PROGRESS_NOTIFICATION. 332 333 The value of @progress must be between 0.0 and 1.0. 334 */ 114 335 void 115 336 BNotification::SetProgress(float progress) 116 337 { 117 fProgress = progress; 338 if (progress < 0) 339 fProgress = 0; 340 else if (progress > 1) 341 fProgress = 1; 342 else 343 fProgress = progress; 118 344 } 119 345 120 346 121 347 const char* 122 348 BNotification::OnClickApp() const 123 349 { 350 if (fApp == "") 351 return NULL; 124 352 return fApp; 125 353 } 126 354 … … BNotification::OnClickArgAt(int32 index) const 208 436 } 209 437 210 438 439 /*! \brief Notification's icon. 440 441 \return Notification's icon. 442 */ 211 443 const BBitmap* 212 444 BNotification::Icon() const 213 445 { … … BNotification::Icon() const 215 447 } 216 448 217 449 450 /*! \brief Sets notification's icon. 451 452 Sets notification's icon. 453 This method takes ownership of @icon. 454 455 \param icon Icon 456 \return 457 - \c B_OK: Everything went fine. 458 - \c B_NO_MEMORY: Allocation of @icon copy has failed. 459 - \c Other errors: Creation of @icon copy failed for some reason. 460 */ 218 461 status_t 219 462 BNotification::SetIcon(const BBitmap* icon) 220 463 { … … BNotification::SetIcon(const BBitmap* icon) 230 473 fBitmap = NULL; 231 474 return B_OK; 232 475 } 476 477 478 /*! \brief Sends a notification to the notification_server. 479 480 The notification is delivered asynchronously to the notification_server, 481 which will display it according to its settings and filters. 482 483 \param timeout Microseconds after the message fades out. 484 \return 485 - \c B_OK: Everything went fine. 486 - \c B_BAD_PORT_ID: A connection to notification_server could not be 487 established or the server is not up and running anymore. 488 - \c Other errors: Building the message from the notification failed. 489 */ 490 status_t 491 BNotification::Send(bigtime_t timeout) 492 { 493 BMessage msg(kNotificationMessage); 494 495 // Archive notification 496 status_t ret = Archive(&msg); 497 498 // Custom time out 499 if (ret == B_OK && timeout > 0) 500 ret = msg.AddInt64("timeout", timeout); 501 502 // Send message 503 if (ret == B_OK) { 504 BMessenger server(kNotificationServerSignature); 505 ret = server.SendMessage(&msg); 506 } 507 508 return ret; 509 } -
src/kits/app/Roster.cpp
diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index 9e354cb..36390b8 100644
a b 36 36 #include <Mime.h> 37 37 #include <Node.h> 38 38 #include <NodeInfo.h> 39 #include <Notification.h>40 #include <notification/Notifications.h>41 39 #include <OS.h> 42 40 #include <Path.h> 43 41 #include <Query.h> … … BRoster::AddToRecentFolders(const entry_ref* folder, const char* appSig) const 1653 1651 DBG(OUT("WARNING: BRoster::AddToRecentDocuments() failed with error 0x%lx\n", err)); 1654 1652 } 1655 1653 1656 /*! \brief Sends a notification to the notification_server.1657 1658 The notification is delivered asynchronously to the notification_server,1659 which will displays it according to its settings and filters.1660 1661 \param notification Notification message.1662 \param timeout Seconds after the message fades out.1663 \return1664 - \c B_OK: Everything went fine.1665 - \c B_BAD_PORT_ID: A connection to notification_server could not be1666 established or the server is not up and running anymore.1667 - \c Other errors: Building the message from the notification failed.1668 */1669 status_t1670 BRoster::Notify(const BNotification& notification, bigtime_t timeout) const1671 {1672 // TODO: Add BArchivable support to BNotification and use it here.1673 BMessage msg(kNotificationMessage);1674 status_t ret = msg.AddInt32("type", (int32)notification.Type());1675 if (ret == B_OK)1676 ret = msg.AddString("app", notification.Application());1677 if (ret == B_OK)1678 ret = msg.AddString("title", notification.Title());1679 if (ret == B_OK)1680 ret = msg.AddString("content", notification.Content());1681 1682 if (ret == B_OK && notification.MessageID() != NULL)1683 ret = msg.AddString("messageID", notification.MessageID());1684 1685 if (ret == B_OK && notification.Type() == B_PROGRESS_NOTIFICATION)1686 ret = msg.AddFloat("progress", notification.Progress());1687 1688 if (ret == B_OK && notification.OnClickApp() != NULL)1689 ret = msg.AddString("onClickApp", notification.OnClickApp());1690 if (ret == B_OK && notification.OnClickFile() != NULL)1691 ret = msg.AddRef("onClickFile", notification.OnClickFile());1692 1693 if (ret == B_OK) {1694 for (int32 i = 0; i < notification.CountOnClickRefs(); i++) {1695 ret = msg.AddRef("onClickRef", notification.OnClickRefAt(i));1696 if (ret != B_OK)1697 break;1698 }1699 }1700 1701 if (ret == B_OK) {1702 for (int32 i = 0; i < notification.CountOnClickArgs(); i++) {1703 ret = msg.AddString("onClickArgv", notification.OnClickArgAt(i));1704 if (ret != B_OK)1705 break;1706 }1707 }1708 1709 if (ret == B_OK) {1710 const BBitmap* icon = notification.Icon();1711 if (icon != NULL) {1712 BMessage archive;1713 ret = icon->Archive(&archive);1714 if (ret == B_OK)1715 ret = msg.AddMessage("icon", &archive);1716 }1717 }1718 1719 // Custom time out1720 if (ret == B_OK && timeout > 0)1721 ret = msg.AddInt64("timeout", timeout);1722 1723 // Send message1724 if (ret == B_OK) {1725 BMessenger server(kNotificationServerSignature);1726 ret = server.SendMessage(&msg);1727 }1728 1729 return ret;1730 }1731 1732 1733 1654 // #pragma mark - Private or reserved 1734 1655 1735 1656 -
src/kits/notification/AppUsage.cpp
diff --git a/src/kits/notification/AppUsage.cpp b/src/kits/notification/AppUsage.cpp index 7310796..2e1cb72 100644
a b AppUsage::AppUsage() 27 27 } 28 28 29 29 30 AppUsage::AppUsage( entry_ref ref,const char* name, bool allow)30 AppUsage::AppUsage(const char* name, bool allow) 31 31 : 32 fRef(ref),33 32 fName(name), 34 33 fAllow(allow) 35 34 { … … AppUsage::AppUsage(entry_ref ref, const char* name, bool allow) 38 37 39 38 AppUsage::~AppUsage() 40 39 { 41 notif y_t::iterator nIt;40 notification_t::iterator nIt; 42 41 for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) 43 42 delete nIt->second; 44 43 } … … status_t 55 54 AppUsage::Flatten(void* buffer, ssize_t numBytes) const 56 55 { 57 56 BMessage msg; 58 msg.AddString("app_name", fName); 59 msg.AddRef("app_ref", &fRef); 60 msg.AddBool("app_allow", fAllow); 57 msg.AddString("signature", fName); 58 msg.AddBool("allow", fAllow); 61 59 62 notif y_t::const_iterator nIt;60 notification_t::const_iterator nIt; 63 61 for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) 64 msg.AddFlat("notif y", nIt->second);62 msg.AddFlat("notification", nIt->second); 65 63 66 64 if (numBytes < msg.FlattenedSize()) 67 65 return B_ERROR; … … ssize_t 74 72 AppUsage::FlattenedSize() const 75 73 { 76 74 BMessage msg; 77 msg.AddString("app_name", fName); 78 msg.AddRef("app_ref", &fRef); 79 msg.AddBool("app_allow", fAllow); 75 msg.AddString("signature", fName); 76 msg.AddBool("allow", fAllow); 80 77 81 notif y_t::const_iterator nIt;78 notification_t::const_iterator nIt; 82 79 for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) 83 msg.AddFlat("notif y", nIt->second);80 msg.AddFlat("notification", nIt->second); 84 81 85 82 return msg.FlattenedSize(); 86 83 } … … AppUsage::Unflatten(type_code code, const void* buffer, 113 110 status = msg.Unflatten((const char*)buffer); 114 111 115 112 if (status == B_OK) { 116 msg.FindString("app_name", &fName); 117 msg.FindRef("app_ref", &fRef); 118 msg.FindBool("app_allow", &fAllow); 113 msg.FindString("signature", &fName); 114 msg.FindBool("allow", &fAllow); 119 115 120 116 type_code type; 121 117 int32 count = 0; 122 118 123 status = msg.GetInfo("notif y", &type, &count);119 status = msg.GetInfo("notification", &type, &count); 124 120 if (status != B_OK) 125 121 return status; 126 122 127 123 for (int32 i = 0; i < count; i++) { 128 NotificationReceived *notif y= new NotificationReceived();129 msg.FindFlat("notif y", i, notify);130 fNotifications[notif y->Title()] = notify;124 NotificationReceived *notification = new NotificationReceived(); 125 msg.FindFlat("notification", i, notification); 126 fNotifications[notification->Title()] = notification; 131 127 } 132 128 133 129 status = B_OK; … … AppUsage::Unflatten(type_code code, const void* buffer, 137 133 } 138 134 139 135 140 entry_ref141 AppUsage::Ref()142 {143 return fRef;144 }145 146 147 136 const char* 148 137 AppUsage::Name() 149 138 { … … AppUsage::Allowed(const char* title, notification_type type) 157 146 bool allowed = fAllow; 158 147 159 148 if (allowed) { 160 notif y_t::iterator nIt = fNotifications.find(title);149 notification_t::iterator nIt = fNotifications.find(title); 161 150 if (nIt == fNotifications.end()) { 162 151 allowed = true; 163 152 fNotifications[title] = new NotificationReceived(title, type); … … AppUsage::Allowed() 182 171 NotificationReceived* 183 172 AppUsage::NotificationAt(int32 index) 184 173 { 185 notif y_t::iterator nIt = fNotifications.begin();174 notification_t::iterator nIt = fNotifications.begin(); 186 175 for (int32 i = 0; i < index; i++) 187 176 nIt++; 188 177 -
src/kits/notification/Notifications.cpp
diff --git a/src/kits/notification/Notifications.cpp b/src/kits/notification/Notifications.cpp index e386d74..cfc390f 100644
a b 3 3 * Distributed under the terms of the MIT License. 4 4 */ 5 5 6 7 6 #include <Notifications.h> 8 7 9 8 … … const char* kTimeoutName = "timeout"; 20 19 // Display settings 21 20 const char* kWidthName = "width"; 22 21 const char* kIconSizeName = "icon size"; 23 const char* kLayoutName = "layout";24 -
src/preferences/notifications/DisplayView.cpp
diff --git a/src/preferences/notifications/DisplayView.cpp b/src/preferences/notifications/DisplayView.cpp index fca5fca..f1fffbd 100644
a b DisplayView::DisplayView(SettingsHost* host) 49 49 fIconSize->SetLabelFromMarked(true); 50 50 fIconSizeField = new BMenuField(_T("Icon size:"), fIconSize); 51 51 52 // Title position53 fTitlePosition = new BMenu("titlePosition");54 fTitlePosition->AddItem(new BMenuItem(_T("Above icon"),55 new BMessage(kSettingChanged)));56 fTitlePosition->AddItem(new BMenuItem(_T("Right of icon"),57 new BMessage(kSettingChanged)));58 fTitlePosition->SetLabelFromMarked(true);59 fTitlePositionField = new BMenuField(_T("Title position:"), fTitlePosition);60 61 52 // Load settings 62 53 Load(); 63 54 … … DisplayView::DisplayView(SettingsHost* host) 70 61 .Add(fWindowWidth->CreateTextViewLayoutItem(), 1, 0) 71 62 .Add(fIconSizeField->CreateLabelLayoutItem(), 0, 1) 72 63 .Add(fIconSizeField->CreateMenuBarLayoutItem(), 1, 1) 73 .Add(fTitlePositionField->CreateLabelLayoutItem(), 0, 2) 74 .Add(fTitlePositionField->CreateMenuBarLayoutItem(), 1, 2) 75 .Add(BSpaceLayoutItem::CreateGlue(), 0, 3, 2, 1) 64 .Add(BSpaceLayoutItem::CreateGlue(), 0, 2, 2, 1) 76 65 ); 77 66 } 78 67 … … DisplayView::AttachedToWindow() 82 71 { 83 72 fWindowWidth->SetTarget(this); 84 73 fIconSize->SetTargetForItems(this); 85 fTitlePosition->SetTargetForItems(this);86 74 } 87 75 88 76 … … DisplayView::Load() 146 134 if (item) 147 135 item->SetMarked(true); 148 136 149 infoview_layout layout;150 if (settings.FindInt32(kLayoutName, &setting) != B_OK)151 layout = kDefaultLayout;152 else {153 switch (setting) {154 case 0:155 layout = TitleAboveIcon;156 break;157 case 1:158 layout = AllTextRightOfIcon;159 break;160 default:161 layout = kDefaultLayout;162 }163 }164 item = fTitlePosition->ItemAt(layout);165 if (item)166 item->SetMarked(true);167 168 137 return B_OK; 169 138 } 170 139 … … DisplayView::Save() 195 164 } 196 165 settings.AddInt32(kIconSizeName, (int32)iconSize); 197 166 198 int32 layout = fTitlePosition->IndexOf(fTitlePosition->FindMarked());199 if (layout == B_ERROR)200 layout = (int32)kDefaultLayout;201 settings.AddInt32(kLayoutName, layout);202 203 167 // Save settings file 204 168 BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 205 169 status_t ret = settings.Flatten(&file); -
src/preferences/notifications/DisplayView.h
diff --git a/src/preferences/notifications/DisplayView.h b/src/preferences/notifications/DisplayView.h index ddf528c..8c0ebe1 100644
a b private: 28 28 BTextControl* fWindowWidth; 29 29 BMenu* fIconSize; 30 30 BMenuField* fIconSizeField; 31 BMenu* fTitlePosition;32 BMenuField* fTitlePositionField;33 31 34 32 }; 35 33 -
src/servers/notification/AppGroupView.cpp
diff --git a/src/servers/notification/AppGroupView.cpp b/src/servers/notification/AppGroupView.cpp index 9612f54..114f392 100644
a b 13 13 14 14 #include <algorithm> 15 15 16 #include <GroupLayout.h> 17 #include <GroupView.h> 18 16 19 #include "AppGroupView.h" 17 20 18 21 #include "NotificationWindow.h" … … 21 24 22 25 AppGroupView::AppGroupView(NotificationWindow* win, const char* label) 23 26 : 24 BView(BRect(0, 0, win->ViewWidth(), 1), label, B_FOLLOW_LEFT_RIGHT, 25 B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_FRAME_EVENTS), 27 BBox(B_FANCY_BORDER, (fView = new BGroupView(B_VERTICAL, 10))), 26 28 fLabel(label), 27 29 fParent(win), 28 30 fCollapsed(false) 29 31 { 30 Show(); 32 // If no group was specified we don't have any border or label 33 if (label == NULL) 34 SetBorder(B_NO_BORDER); 35 else 36 SetLabel(label); 31 37 } 32 38 33 39 … … AppGroupView::~AppGroupView() 37 43 38 44 39 45 void 40 AppGroupView::AttachedToWindow()41 {42 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));43 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));44 SetHighColor(ui_color(B_PANEL_TEXT_COLOR));45 }46 47 48 void49 AppGroupView::Draw(BRect updateRect)50 {51 FillRect(Bounds(), B_SOLID_LOW);52 53 BString label = fLabel;54 if (fCollapsed)55 label << " (" << fInfo.size() << ")";56 57 font_height fh;58 be_bold_font->GetHeight(&fh);59 float labelOffset = fh.ascent + fh.leading;60 61 BRect borderRect = Bounds().InsetByCopy(kEdgePadding, kEdgePadding);62 borderRect.top = labelOffset;63 64 BRect textRect = borderRect;65 textRect.left = kEdgePadding * 2;66 textRect.right = textRect.left + be_bold_font->StringWidth(label.String())67 + (kEdgePadding * 3);68 textRect.bottom = labelOffset;69 70 BRect closeCross = fCloseRect;71 closeCross.InsetBy(kSmallPadding, kSmallPadding);72 73 rgb_color detailCol = ui_color(B_CONTROL_BORDER_COLOR);74 detailCol = tint_color(detailCol, B_LIGHTEN_2_TINT);75 // detailCol = tint_color(detailCol, B_LIGHTEN_1_TINT);76 77 if (fCollapsed) {78 PushState();79 SetFont(be_bold_font);80 SetPenSize(kPenSize);81 float linePos = textRect.top + textRect.Height() / 2;82 83 // Draw the line to the expand widget84 PushState();85 SetHighColor(detailCol);86 StrokeLine(BPoint(kEdgePadding, linePos), BPoint(fCollapseRect.left, linePos));87 PopState();88 89 // Draw the expand widget90 PushState();91 SetHighColor(detailCol);92 StrokeRoundRect(fCollapseRect, kSmallPadding, kSmallPadding);93 94 BPoint expandHorStart(fCollapseRect.left + kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);95 BPoint expandHorEnd(fCollapseRect.right - kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);96 StrokeLine(expandHorStart, expandHorEnd);97 98 BPoint expandVerStart(fCollapseRect.Width() / 2 + fCollapseRect.left, fCollapseRect.top + kSmallPadding);99 BPoint expandVerEnd(fCollapseRect.Width() / 2 + fCollapseRect.left, fCollapseRect.bottom - kSmallPadding);100 StrokeLine(expandVerStart, expandVerEnd);101 PopState();102 103 // Draw the app title104 DrawString(label.String(), BPoint(fCollapseRect.right + kEdgePadding, labelOffset + kEdgePadding));105 106 // Draw the line from the label to the close widget107 PushState();108 SetHighColor(detailCol);109 110 BPoint lineSeg2Start(textRect.right + kSmallPadding / 2, linePos);111 BPoint lineSeg2End(fCloseRect.left, linePos);112 StrokeLine(lineSeg2Start, lineSeg2End);113 PopState();114 115 // Draw the dismiss widget116 PushState();117 SetHighColor(detailCol);118 119 StrokeRoundRect(fCloseRect, kSmallPadding, kSmallPadding);120 121 StrokeLine(closeCross.LeftTop(), closeCross.RightBottom());122 StrokeLine(closeCross.RightTop(), closeCross.LeftBottom());123 PopState();124 125 // Draw the line from the dismiss widget126 PushState();127 SetHighColor(detailCol);128 129 BPoint lineSeg3Start(fCloseRect.right, linePos);130 BPoint lineSeg3End(borderRect.right, linePos);131 StrokeLine(lineSeg3Start, lineSeg3End);132 PopState();133 134 PopState();135 } else {136 PushState();137 SetFont(be_bold_font);138 SetPenSize(kPenSize);139 140 // Draw the border141 PushState();142 SetHighColor(detailCol);143 // StrokeRoundRect(borderRect, kEdgePadding, kEdgePadding * 2);144 StrokeRect(borderRect);145 PopState();146 147 FillRect(textRect, B_SOLID_LOW);148 149 // Draw the collapse widget150 PushState();151 SetHighColor(detailCol);152 StrokeRoundRect(fCollapseRect, kSmallPadding, kSmallPadding);153 154 BPoint expandHorStart(fCollapseRect.left + kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);155 BPoint expandHorEnd(fCollapseRect.right - kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);156 157 StrokeLine(expandHorStart, expandHorEnd);158 PopState();159 160 // Draw the dismiss widget161 PushState();162 SetHighColor(detailCol);163 FillRect(fCloseRect, B_SOLID_LOW);164 165 StrokeRoundRect(fCloseRect, kSmallPadding, kSmallPadding);166 167 StrokeLine(closeCross.LeftTop(), closeCross.RightBottom());168 StrokeLine(closeCross.RightTop(), closeCross.LeftBottom());169 PopState();170 171 // Draw the label172 DrawString(label.String(), BPoint(fCollapseRect.right + kEdgePadding, labelOffset + kEdgePadding));173 PopState();174 }175 176 Sync();177 }178 179 180 void181 46 AppGroupView::MouseDown(BPoint point) 182 47 { 183 48 bool changed = false; 49 50 // User is closing all the children 184 51 if (fCloseRect.Contains(point)) { 185 52 changed = true; 186 53 187 54 int32 children = fInfo.size(); 55 188 56 for (int32 i = 0; i < children; i++) { 189 f Info[i]->RemoveSelf();57 fView->GetLayout()->RemoveView(fInfo[i]); 190 58 delete fInfo[i]; 191 59 } 60 192 61 fInfo.clear(); 193 62 } 194 63 64 // User is collapsing this group box 195 65 if (fCollapseRect.Contains(point)) { 196 66 fCollapsed = !fCollapsed; 197 67 changed = true; 198 68 } 199 69 200 if (changed) { 201 ResizeViews(); 202 Invalidate(); 203 } 204 } 205 206 207 void 208 AppGroupView::GetPreferredSize(float* width, float* height) 209 { 210 font_height fh; 211 be_bold_font->GetHeight(&fh); 212 213 float h = fh.ascent + fh.leading + fh.leading; 214 h += kEdgePadding * 2; // Padding between top and bottom of label 215 216 if (!fCollapsed) { 217 int32 children = fInfo.size(); 218 219 for (int32 i = 0; i < children; i++) { 220 float childHeight = 0; 221 float childWidth = 0; 222 223 fInfo[i]->GetPreferredSize(&childWidth, &childHeight); 224 225 h += childHeight; 226 } 227 } 228 229 h += kEdgePadding; 230 231 *width = fParent->ViewWidth(); 232 *height = h; 70 if (changed) 71 _ResizeViews(); 233 72 } 234 73 235 74 … … AppGroupView::MessageReceived(BMessage* msg) 247 86 248 87 if (vIt != fInfo.end()) { 249 88 fInfo.erase(vIt); 250 view->RemoveSelf();89 fView->GetLayout()->RemoveView(view); 251 90 delete view; 252 91 } 253 92 254 ResizeViews();255 Invalidate();93 if (Window() != NULL) 94 Window()->PostMessage(msg); 256 95 257 // When all the views are destroy, save app filters 258 if (fInfo.size() == 0) 259 dynamic_cast<NotificationWindow*>(Window())->SaveAppFilters(); 96 _ResizeViews(); 260 97 break; 261 98 } 262 99 default: … … AppGroupView::MessageReceived(BMessage* msg) 265 102 } 266 103 267 104 105 bool 106 AppGroupView::HasChildren() 107 { 108 return !fInfo.empty(); 109 } 110 111 268 112 void 269 113 AppGroupView::AddInfo(NotificationView* view) 270 114 { 271 115 BString id = view->MessageID(); 116 bool found = false; 117 272 118 if (id.Length() > 0) { 273 119 int32 children = fInfo.size(); 274 bool found = false;275 120 276 121 for (int32 i = 0; i < children; i++) { 277 if (fInfo[i]->HasMessageID(id.String())) { 278 fInfo[i]->RemoveSelf(); 122 // Replace a child with the same message identifier 123 if (id == fInfo[i]->MessageID()) { 124 fView->GetLayout()->RemoveView(fInfo[i]); 279 125 delete fInfo[i]; 280 126 281 127 fInfo[i] = view; 282 128 found = true; 283 284 129 break; 285 130 } 286 131 } 132 } 287 133 288 if (!found) 289 fInfo.push_back(view); 290 } else 134 // Add child to the list if it's a new one 135 if (!found) 291 136 fInfo.push_back(view); 292 137 138 #if 0 293 139 if (fParent->IsHidden()) 294 140 fParent->Show(); 141 #endif 142 143 // Add the new child 144 fView->GetLayout()->AddView(view); 145 146 // Show this group and child if hidden 295 147 if (IsHidden()) 296 148 Show(); 297 149 if (view->IsHidden()) 298 150 view->Show(); 299 151 300 AddChild(view); 301 302 ResizeViews(); 303 Invalidate(); 152 _ResizeViews(); 304 153 } 305 154 306 155 307 156 void 308 AppGroupView:: ResizeViews()157 AppGroupView::_ResizeViews() 309 158 { 310 font_height fh;311 be_bold_font->GetHeight(&fh);312 313 float offset = fh.ascent + fh.leading + fh.descent;314 159 int32 children = fInfo.size(); 315 160 316 161 if (!fCollapsed) { 317 offset += kEdgePadding + kPenSize;318 319 162 for (int32 i = 0; i < children; i++) { 320 fInfo[i]->ResizeToPreferred();321 fInfo[i]->MoveTo(kEdgePadding + kPenSize, offset);322 323 offset += fInfo[i]->Bounds().Height();324 163 if (fInfo[i]->IsHidden()) 325 164 fInfo[i]->Show(); 326 fInfo[i]->SetPosition(false, false); 327 }; 165 } 328 166 } else { 329 167 for (int32 i = 0; i < children; i++) 330 168 if (!fInfo[i]->IsHidden()) 331 169 fInfo[i]->Hide(); 332 170 } 333 171 334 if (children == 1) 335 fInfo[0]->SetPosition(true, true); 336 else if (children > 1) { 337 fInfo[0]->SetPosition(true, false); 338 fInfo[children - 1]->SetPosition(false, true); 339 } 340 341 ResizeTo(fParent->ViewWidth(), offset); 172 #if 0 342 173 float labelOffset = fh.ascent + fh.leading; 343 174 344 175 BRect borderRect = Bounds().InsetByCopy(kEdgePadding, kEdgePadding); … … AppGroupView::ResizeViews() 354 185 fCloseRect.left = fCloseRect.right - kCloseSize; 355 186 fCloseRect.bottom = fCloseRect.top + kCloseSize; 356 187 fCloseRect.OffsetTo(fCloseRect.left, kEdgePadding * 1.5); 357 358 fParent->ResizeAll(); 359 } 360 361 362 bool 363 AppGroupView::HasChildren() 364 { 365 return !fInfo.empty(); 188 #endif 366 189 } -
src/servers/notification/AppGroupView.h
diff --git a/src/servers/notification/AppGroupView.h b/src/servers/notification/AppGroupView.h index eeb9a81..d0ec478 100644
a b 1 1 /* 2 * Copyright 2005-2008, Mikael Eiman. 3 * Copyright 2005-2008, Michael Davidson. 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved. 4 * Copyright 2004-2008, Michael Davidson. All Rights Reserved. 5 * Copyright 2004-2007, Mikael Eiman. All Rights Reserved. 4 6 * Distributed under the terms of the MIT License. 5 *6 * Authors:7 * Mikael Eiman <mikael@eiman.tv>8 * Michael Davidson <slaad@bong.com.au>9 7 */ 10 11 #ifndef APPGROUPVIEW_H 12 #define APPGROUPVIEW_H 8 #ifndef _APP_GROUP_VIEW_H 9 #define _APP_GROUP_VIEW_H 13 10 14 11 #include <vector> 15 12 13 #include <Box.h> 16 14 #include <String.h> 17 #include <View.h> 15 16 class BGroupView; 18 17 19 18 class NotificationWindow; 20 19 class NotificationView; 21 20 22 typedef std::vector<NotificationView *> infoview_t; 23 24 class AppGroupView : public BView { 25 public: 26 AppGroupView(NotificationWindow *win, const char *label); 27 ~AppGroupView(void); 28 29 // Hooks 30 void AttachedToWindow(void); 31 void Draw(BRect bounds); 32 void MouseDown(BPoint point); 33 void GetPreferredSize(float *width, float *height); 34 void MessageReceived(BMessage *msg); 35 36 // Public 37 void AddInfo(NotificationView *view); 38 void ResizeViews(void); 39 bool HasChildren(void); 40 41 private: 42 BString fLabel; 43 NotificationWindow *fParent; 44 infoview_t fInfo; 45 bool fCollapsed; 46 BRect fCloseRect; 47 BRect fCollapseRect; 21 typedef std::vector<NotificationView*> infoview_t; 22 23 class AppGroupView : public BBox { 24 public: 25 AppGroupView(NotificationWindow* win, const char* label); 26 ~AppGroupView(); 27 28 virtual void MouseDown(BPoint point); 29 virtual void MessageReceived(BMessage* msg); 30 31 bool HasChildren(); 32 33 void AddInfo(NotificationView* view); 34 35 private: 36 void _ResizeViews(); 37 38 BString fLabel; 39 NotificationWindow* fParent; 40 BGroupView* fView; 41 infoview_t fInfo; 42 bool fCollapsed; 43 BRect fCloseRect; 44 BRect fCollapseRect; 48 45 }; 49 46 50 #endif 47 #endif // _APP_GROUP_VIEW_H -
src/servers/notification/Jamfile
diff --git a/src/servers/notification/Jamfile b/src/servers/notification/Jamfile index 26d0652..5babfb4 100644
a b 1 1 SubDir HAIKU_TOP src servers notification ; 2 2 3 3 UsePrivateHeaders notification ; 4 UseLibraryHeaders icon ;5 4 6 5 Server notification_server : 7 6 AppGroupView.cpp 8 BorderView.cpp9 7 NotificationServer.cpp 10 8 NotificationView.cpp 11 9 NotificationWindow.cpp 12 : be $(TARGET_LIBSTDC++) libicon.alibnotification.a10 : be translation $(TARGET_LIBSTDC++) libnotification.a 13 11 : notification_server.rdef 14 12 ; 15 13 16 Depends notification_server : libicon.a ;17 14 Depends notification_server : libnotification.a ; -
src/servers/notification/NotificationServer.cpp
diff --git a/src/servers/notification/NotificationServer.cpp b/src/servers/notification/NotificationServer.cpp index bd874e3..0b528c2 100644
a b const char* kSoundNames[] = { 24 24 NotificationServer::NotificationServer() 25 25 : BApplication(kNotificationServerSignature) 26 26 { 27 fWindow = new NotificationWindow();28 27 } 29 28 30 29 … … NotificationServer::~NotificationServer() 34 33 35 34 36 35 void 36 NotificationServer::ReadyToRun() 37 { 38 fWindow = new NotificationWindow(); 39 } 40 41 42 void 37 43 NotificationServer::MessageReceived(BMessage* message) 38 44 { 39 45 switch (message->what) { … … NotificationServer::MessageReceived(BMessage* message) 61 67 } 62 68 63 69 64 bool65 NotificationServer::QuitRequested()66 {67 if (fWindow && fWindow->Lock()) {68 fWindow->Quit();69 fWindow = NULL;70 }71 return true;72 }73 74 75 70 status_t 76 71 NotificationServer::GetSupportedSuites(BMessage* msg) 77 72 { … … main(int argc, char* argv[]) 110 105 add_system_beep_event(kSoundNames[i++], 0); 111 106 112 107 // Start! 113 NotificationServer * server = new NotificationServer();114 server ->Run();108 NotificationServer server; 109 server.Run(); 115 110 116 111 return 0; 117 112 } -
src/servers/notification/NotificationServer.h
diff --git a/src/servers/notification/NotificationServer.h b/src/servers/notification/NotificationServer.h index aff0da1..7a504fb 100644
a b public: 14 14 NotificationServer(); 15 15 virtual ~NotificationServer(); 16 16 17 virtual void ReadyToRun(); 17 18 virtual void MessageReceived(BMessage* message); 18 virtual bool QuitRequested();19 19 20 20 virtual status_t GetSupportedSuites(BMessage* msg); 21 21 virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, -
src/servers/notification/NotificationView.cpp
diff --git a/src/servers/notification/NotificationView.cpp b/src/servers/notification/NotificationView.cpp index f5671f1..2e4ba93 100644
a b 9 9 * Michael Davidson, slaad@bong.com.au 10 10 * Mikael Eiman, mikael@eiman.tv 11 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 * Stephan Aßmus <superstippi@gmx.de>12 * Stephan Aßmus, superstippi@gmx.de 13 13 */ 14 14 15 #include <stdlib.h> 16 17 #include <Font.h> 18 #include <IconUtils.h> 15 #include <ControlLook.h> 16 #include <LayoutUtils.h> 19 17 #include <Messenger.h> 20 #include <Picture.h> 21 #include <PropertyInfo.h> 22 #include <Region.h> 23 #include <Resources.h> 18 #include <Path.h> 24 19 #include <Roster.h> 25 #include <StringView.h>26 #include <TranslationUtils.h>27 20 28 21 #include "NotificationView.h" 29 22 #include "NotificationWindow.h" 30 23 31 const char* kSmallIconAttribute = "BEOS:M:STD_ICON";32 const char* kLargeIconAttribute = "BEOS:L:STD_ICON";33 const char* kIconAttribute = "BEOS:ICON";34 35 24 property_info message_prop_list[] = { 36 { "type", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 37 {B_DIRECT_SPECIFIER, 0}, "get the notification type"}, 38 { "app", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 39 {B_DIRECT_SPECIFIER, 0}, "get notification's app"}, 40 { "title", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 41 {B_DIRECT_SPECIFIER, 0}, "get notification's title"}, 42 { "content", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 43 {B_DIRECT_SPECIFIER, 0}, "get notification's contents"}, 44 { "icon", {B_GET_PROPERTY, 0}, 45 {B_DIRECT_SPECIFIER, 0}, "get icon as an archived bitmap"}, 46 { "progress", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 47 {B_DIRECT_SPECIFIER, 0}, "get the progress (between 0.0 and 1.0)"}, 48 { NULL } 25 { 26 "type", 27 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 28 { B_DIRECT_SPECIFIER, 0 }, 29 "get the notification type" 30 }, 31 { 32 "group", 33 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 34 { B_DIRECT_SPECIFIER, 0 }, 35 "get notification's group" 36 }, 37 { 38 "title", 39 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 40 { B_DIRECT_SPECIFIER, 0 }, 41 "get notification's title" 42 }, 43 { 44 "content", 45 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 46 { B_DIRECT_SPECIFIER, 0 }, 47 "get notification's contents" 48 }, 49 { 50 "icon", 51 { B_GET_PROPERTY, 0 }, 52 { B_DIRECT_SPECIFIER, 0 }, 53 "get icon as an archived bitmap" 54 }, 55 { 56 "progress", 57 { B_GET_PROPERTY, B_SET_PROPERTY, 0 }, 58 { B_DIRECT_SPECIFIER, 0 }, 59 "get the progress (between 0.0 and 1.0)" 60 }, 61 { 0, { 0 }, { 0 }, 0 } 49 62 }; 50 63 51 64 52 65 NotificationView::NotificationView(NotificationWindow* win, 53 notification_type type, const char* app, const char* title, const char* text, 54 BMessage* details) 66 BNotification* notification, bigtime_t timeout) 55 67 : 56 BView(BRect(0, 0, win->ViewWidth(), 1), "NotificationView", 57 B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE 68 BView("NotificationView", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE 58 69 | B_FRAME_EVENTS), 59 70 fParent(win), 60 fType(type), 71 fNotification(notification), 72 fTimeout(timeout), 61 73 fRunner(NULL), 62 fProgress(0.0f), 63 fMessageID(""), 64 fDetails(details), 65 fBitmap(NULL), 66 fIsFirst(false), 67 fIsLast(false) 74 fBitmap(NULL) 68 75 { 69 BMessage iconMsg; 70 if (fDetails->FindMessage("icon", &iconMsg) == B_OK) 71 fBitmap = new BBitmap(&iconMsg); 72 73 if (!fBitmap) 74 _LoadIcon(); 75 76 const char* messageID = NULL; 77 if (fDetails->FindString("messageID", &messageID) == B_OK) 78 fMessageID = messageID; 76 if (fNotification->Icon() != NULL) 77 fBitmap = new BBitmap(fNotification->Icon()); 79 78 80 if (f Details->FindFloat("progress", &fProgress) != B_OK)81 f Progress = 0.0f;79 if (fTimeout <= 0) 80 fTimeout = fParent->Timeout() * 1000000; 82 81 83 // Progress is between 0 and 1 84 if (fProgress < 0.0f) 85 fProgress = 0.0f; 86 if (fProgress > 1.0f) 87 fProgress = 1.0f; 82 SetText(); 88 83 89 SetText(app, title, text); 90 ResizeToPreferred(); 91 92 switch (type) { 84 switch (fNotification->Type()) { 93 85 case B_IMPORTANT_NOTIFICATION: 94 86 SetViewColor(255, 255, 255); 95 87 SetLowColor(255, 255, 255); … … NotificationView::NotificationView(NotificationWindow* win, 101 93 default: 102 94 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 103 95 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 104 break;105 96 } 106 97 } 107 98 … … NotificationView::NotificationView(NotificationWindow* win, 109 100 NotificationView::~NotificationView() 110 101 { 111 102 delete fRunner; 112 delete fDetails;113 103 delete fBitmap; 104 delete fNotification; 114 105 115 106 LineInfoList::iterator lIt; 116 107 for (lIt = fLines.begin(); lIt != fLines.end(); lIt++) … … NotificationView::AttachedToWindow() 123 114 { 124 115 BMessage msg(kRemoveView); 125 116 msg.AddPointer("view", this); 126 bigtime_t timeout = -1;127 117 128 if (fDetails->FindInt64("timeout", &timeout) != B_OK) 129 timeout = fParent->Timeout() * 1000000; 130 131 if (timeout > 0) 132 fRunner = new BMessageRunner(BMessenger(Parent()), &msg, timeout, 1); 118 fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1); 133 119 } 134 120 135 121 … … NotificationView::MessageReceived(BMessage* msg) 151 137 152 138 if (msgOkay) { 153 139 if (strcmp(property, "type") == 0) 154 reply.AddInt32("result", f Type);140 reply.AddInt32("result", fNotification->Type()); 155 141 156 if (strcmp(property, " app") == 0)157 reply.AddString("result", f App);142 if (strcmp(property, "group") == 0) 143 reply.AddString("result", fNotification->Group()); 158 144 159 145 if (strcmp(property, "title") == 0) 160 reply.AddString("result", f Title);146 reply.AddString("result", fNotification->Title()); 161 147 162 148 if (strcmp(property, "content") == 0) 163 reply.AddString("result", f Text);149 reply.AddString("result", fNotification->Content()); 164 150 165 151 if (strcmp(property, "progress") == 0) 166 reply.AddFloat("result", f Progress);152 reply.AddFloat("result", fNotification->Progress()); 167 153 168 154 if ((strcmp(property, "icon") == 0) && fBitmap) { 169 155 BMessage archive; … … NotificationView::MessageReceived(BMessage* msg) 193 179 msgOkay = false; 194 180 195 181 if (msgOkay) { 196 if (strcmp(property, "app") == 0) 197 msg->FindString("data", &fApp); 182 const char* value = NULL; 183 184 if (strcmp(property, "group") == 0) 185 if (msg->FindString("data", &value) == B_OK) 186 fNotification->SetGroup(value); 198 187 199 188 if (strcmp(property, "title") == 0) 200 msg->FindString("data", &fTitle); 189 if (msg->FindString("data", &value) == B_OK) 190 fNotification->SetTitle(value); 201 191 202 192 if (strcmp(property, "content") == 0) 203 msg->FindString("data", &fText); 193 if (msg->FindString("data", &value) == B_OK) 194 fNotification->SetContent(value); 204 195 205 196 if (strcmp(property, "icon") == 0) { 206 197 BMessage archive; … … NotificationView::MessageReceived(BMessage* msg) 210 201 } 211 202 } 212 203 213 SetText( Application(), Title(), Text());204 SetText(); 214 205 Invalidate(); 215 206 216 207 reply.AddInt32("error", B_OK); … … NotificationView::MessageReceived(BMessage* msg) 222 213 msg->SendReply(&reply); 223 214 break; 224 215 } 225 case kRemoveView:226 {227 BMessage remove(kRemoveView);228 remove.AddPointer("view", this);229 BMessenger msgr(Window());230 msgr.SendMessage( &remove );231 break;232 }233 216 default: 234 217 BView::MessageReceived(msg); 235 218 } … … NotificationView::MessageReceived(BMessage* msg) 237 220 238 221 239 222 void 240 NotificationView::GetPreferredSize(float* w, float* h)241 {242 // Parent width, minus the edge padding, minus the pensize243 *w = fParent->ViewWidth() - (kEdgePadding * 2) - (kPenSize * 2);244 *h = fHeight;245 246 if (fType == B_PROGRESS_NOTIFICATION) {247 font_height fh;248 be_plain_font->GetHeight(&fh);249 float fontHeight = fh.ascent + fh.descent + fh.leading;250 *h += (kSmallPadding * 2) + (kEdgePadding * 1) + fontHeight;251 }252 }253 254 255 void256 223 NotificationView::Draw(BRect updateRect) 257 224 { 258 225 BRect progRect; 259 226 260 227 // Draw progress background 261 if (fType == B_PROGRESS_NOTIFICATION) { 262 PushState(); 263 228 if (fNotification->Type() == B_PROGRESS_NOTIFICATION) { 264 229 font_height fh; 265 230 be_plain_font->GetHeight(&fh); 231 266 232 float fontHeight = fh.ascent + fh.descent + fh.leading; 267 233 268 234 progRect = Bounds(); 269 235 progRect.InsetBy(kEdgePadding, kEdgePadding); 270 236 progRect.top = progRect.bottom - (kSmallPadding * 2) - fontHeight; 271 StrokeRect(progRect);272 237 273 BRect barRect = progRect; 274 barRect.InsetBy(1.0, 1.0); 275 barRect.right *= fProgress; 276 SetHighColor(ui_color(B_CONTROL_HIGHLIGHT_COLOR)); 277 FillRect(barRect); 238 // Progress bar 239 rgb_color barColor = {50, 150, 255, 255}; 278 240 279 SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); 241 float progress = fNotification->Progress() * 100; 242 BRect barFrame(2, 2, progRect.right - 2, 2 + progRect.Height() - 4); 243 244 float barPos = 0; 245 if (progress == 0) 246 barPos = barFrame.left - 1; 247 else 248 barPos = roundf(barFrame.left - 1 249 + (progress * (barFrame.Width() + 3) / 100)); 250 251 PushState(); 252 be_control_look->DrawStatusBar(this, progRect, updateRect, 253 ui_color(B_PANEL_BACKGROUND_COLOR), barColor, barPos); 254 PopState(); 280 255 281 BString label = ""; 282 label << (int)(fProgress * 100) << " %"; 256 // Progress text 257 BString label; 258 label << progress << " %"; 283 259 284 260 float labelWidth = be_plain_font->StringWidth(label.String()); 285 261 float labelX = progRect.left + (progRect.IntegerWidth() / 2) - (labelWidth / 2); 286 262 263 SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); 287 264 SetLowColor(B_TRANSPARENT_COLOR); 288 265 SetDrawingMode(B_OP_ALPHA); 266 289 267 DrawString(label.String(), label.Length(), 290 268 BPoint(labelX, progRect.top + fh.ascent + fh.leading + kSmallPadding)); 291 292 PopState();293 269 } 294 270 295 SetDrawingMode(B_OP_ALPHA);296 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);297 298 271 // Icon size 299 272 float iconSize = (float)fParent->IconSize(); 300 273 … … NotificationView::Draw(BRect updateRect) 307 280 font_height fh; 308 281 appLine->font.GetHeight(&fh); 309 282 310 float title_bottom = appLine->location.y + fh.descent;311 312 283 float ix = kEdgePadding; 313 float iy = 0; 314 if (fParent->Layout() == TitleAboveIcon) 315 iy = title_bottom + kEdgePadding + (Bounds().Height() - title_bottom 316 - kEdgePadding * 2 - iconSize) / 2; 317 else 318 iy = (Bounds().Height() - iconSize) / 2.0; 284 float iy = (Bounds().Height() - iconSize) / 2.0; 319 285 320 if (f Type== B_PROGRESS_NOTIFICATION)286 if (fNotification->Type() == B_PROGRESS_NOTIFICATION) 321 287 // Move icon up by half progress bar height if it's present 322 288 iy -= (progRect.Height() + kEdgePadding) / 2.0; 323 289 … … NotificationView::Draw(BRect updateRect) 326 292 iconRect.right = ix + iconSize; 327 293 iconRect.bottom = iy + iconSize; 328 294 295 SetDrawingMode(B_OP_ALPHA); 296 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 297 329 298 DrawBitmapAsync(fBitmap, fBitmap->Bounds(), 330 299 iconRect, B_FILTER_BITMAP_BILINEAR); 331 300 } … … NotificationView::Draw(BRect updateRect) 348 317 closeRect.left = closeRect.right - kCloseSize; 349 318 closeRect.bottom = closeRect.top + kCloseSize; 350 319 351 PushState(); 352 SetHighColor(detailCol); 353 StrokeRoundRect(closeRect, kSmallPadding, kSmallPadding); 354 BRect closeCross = closeRect.InsetByCopy(kSmallPadding, kSmallPadding); 355 StrokeLine(closeCross.LeftTop(), closeCross.RightBottom()); 356 StrokeLine(closeCross.LeftBottom(), closeCross.RightTop()); 357 PopState(); 358 359 Sync(); 320 SetHighColor(detailCol); 321 StrokeRoundRect(closeRect, kSmallPadding, kSmallPadding); 322 BRect closeCross = closeRect.InsetByCopy(kSmallPadding, kSmallPadding); 323 StrokeLine(closeCross.LeftTop(), closeCross.RightBottom()); 324 StrokeLine(closeCross.LeftBottom(), closeCross.RightTop()); 360 325 } 361 326 362 327 … … NotificationView::MouseDown(BPoint point) 366 331 int32 buttons; 367 332 Window()->CurrentMessage()->FindInt32("buttons", &buttons); 368 333 369 switch (buttons) { 370 case B_PRIMARY_MOUSE_BUTTON: 371 { 372 BRect closeRect = Bounds().InsetByCopy(2,2); 373 closeRect.left = closeRect.right - kCloseSize; 374 closeRect.bottom = closeRect.top + kCloseSize; 375 376 if (!closeRect.Contains(point)) { 377 entry_ref launchRef; 378 BString launchString; 379 BMessage argMsg(B_ARGV_RECEIVED); 380 BMessage refMsg(B_REFS_RECEIVED); 381 entry_ref appRef; 382 bool useArgv = false; 383 BList messages; 384 entry_ref ref; 385 386 if (fDetails->FindString("onClickApp", &launchString) == B_OK) 387 if (be_roster->FindApp(launchString.String(), &appRef) == B_OK) 388 useArgv = true; 389 if (fDetails->FindRef("onClickFile", &launchRef) == B_OK) { 390 if (be_roster->FindApp(&launchRef, &appRef) == B_OK) 391 useArgv = true; 392 } 393 394 if (fDetails->FindRef("onClickRef", &ref) == B_OK) { 395 for (int32 i = 0; fDetails->FindRef("onClickRef", i, &ref) == B_OK; i++) 396 refMsg.AddRef("refs", &ref); 397 398 messages.AddItem((void*)&refMsg); 399 } 334 if ((buttons & B_PRIMARY_MOUSE_BUTTON) == 0) 335 return; 400 336 401 if (useArgv) { 402 type_code type; 403 int32 argc = 0; 404 BString arg; 337 BRect closeRect = Bounds().InsetByCopy(2, 2); 338 closeRect.left = closeRect.right - kCloseSize; 339 closeRect.bottom = closeRect.top + kCloseSize; 340 341 if (!closeRect.Contains(point)) { 342 BMessage argMsg(B_ARGV_RECEIVED); 343 BMessage refMsg(B_REFS_RECEIVED); 344 entry_ref appRef; 345 bool useArgv = false; 346 BList messages; 347 entry_ref ref; 348 349 if (fNotification->OnClickApp() != NULL) 350 if (be_roster->FindApp(fNotification->OnClickApp(), &appRef) == B_OK) 351 useArgv = true; 352 if (fNotification->OnClickFile() != NULL) 353 if (be_roster->FindApp((entry_ref*)fNotification->OnClickFile(), &appRef) == B_OK) 354 useArgv = true; 355 356 for (int32 i = 0; i < fNotification->CountOnClickRefs(); i++) 357 refMsg.AddRef("refs", fNotification->OnClickRefAt(i)); 358 messages.AddItem((void*)&refMsg); 359 360 if (useArgv) { 361 BString arg; 362 363 BPath p(&appRef); 364 argMsg.AddString("argv", p.Path()); 365 366 int32 argc = fNotification->CountOnClickArgs() + 1; 367 argMsg.AddInt32("argc", argc); 368 369 for (int32 i = 0; i < fNotification->CountOnClickArgs(); i++) 370 argMsg.AddString("argv", fNotification->OnClickArgAt(i)); 371 messages.AddItem((void*)&argMsg); 372 } 405 373 406 BPath p(&appRef); 407 argMsg.AddString("argv", p.Path()); 374 #if 0 375 BMessage tmp; 376 for (int32 i = 0; fDetails->FindMessage("onClickMsg", i, &tmp) == B_OK; i++) 377 messages.AddItem((void*)&tmp); 378 #endif 408 379 409 fDetails->GetInfo("onClickArgv", &type, &argc); 410 argMsg.AddInt32("argc", argc + 1); 380 if (fNotification->OnClickApp() != NULL) 381 be_roster->Launch(fNotification->OnClickApp(), &messages); 382 else 383 be_roster->Launch(fNotification->OnClickFile(), &messages); 384 } 411 385 412 for (int32 i = 0; fDetails->FindString("onClickArgv", i, &arg) == B_OK; i++) 413 argMsg.AddString("argv", arg); 386 // Remove the info view after a click 387 BMessage remove_msg(kRemoveView); 388 remove_msg.AddPointer("view", this); 414 389 415 messages.AddItem((void*)&argMsg); 416 } 390 BMessenger msgr(Parent()); 391 msgr.SendMessage(&remove_msg); 392 } 417 393 418 BMessage tmp;419 for (int32 i = 0; fDetails->FindMessage("onClickMsg", i, &tmp) == B_OK; i++)420 messages.AddItem((void*)&tmp);421 394 422 if (fDetails->FindString("onClickApp", &launchString) == B_OK) 423 be_roster->Launch(launchString.String(), &messages); 424 else 425 be_roster->Launch(&launchRef, &messages);426 395 BSize 396 NotificationView::MinSize() 397 { 398 return BLayoutUtils::ComposeSize(ExplicitMinSize(), _CalculateSize()); 399 } 427 400 428 // Remove the info view after a click429 BMessage remove_msg(kRemoveView);430 remove_msg.AddPointer("view", this);431 401 432 BMessenger msgr(Parent()); 433 msgr.SendMessage(&remove_msg); 434 break; 435 } 436 } 402 BSize 403 NotificationView::MaxSize() 404 { 405 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), _CalculateSize()); 437 406 } 438 407 439 408 440 void 441 NotificationView:: FrameResized( float w, float /*h*/)409 BSize 410 NotificationView::PreferredSize() 442 411 { 443 SetText(Application(), Title(), Text()); 412 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), 413 _CalculateSize()); 444 414 } 445 415 446 416 447 417 BHandler* 448 NotificationView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, int32 form, const char* prop) 418 NotificationView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, 419 int32 form, const char* prop) 449 420 { 450 421 BPropertyInfo prop_info(message_prop_list); 451 422 if (prop_info.FindMatch(msg, index, spec, form, prop) >= 0) { … … NotificationView::GetSupportedSuites(BMessage* msg) 467 438 } 468 439 469 440 470 const char*471 NotificationView::Application() const472 {473 return fApp.Length() > 0 ? fApp.String() : NULL;474 }475 476 477 const char*478 NotificationView::Title() const479 {480 return fTitle.Length() > 0 ? fTitle.String() : NULL;481 }482 483 484 const char*485 NotificationView::Text() const486 {487 return fText.Length() > 0 ? fText.String() : NULL;488 }489 490 491 441 void 492 NotificationView::SetText(const char* app, const char* title, const char* text, 493 float newMaxWidth) 442 NotificationView::SetText(float newMaxWidth) 494 443 { 495 444 if (newMaxWidth < 0) 496 445 newMaxWidth = Bounds().Width() - (kEdgePadding * 2); … … NotificationView::SetText(const char* app, const char* title, const char* text, 501 450 delete (*lIt); 502 451 fLines.clear(); 503 452 504 fApp = app;505 fTitle = title;506 fText = text;507 508 453 float iconRight = kEdgePadding + kEdgePadding; 509 454 if (fBitmap != NULL) 510 455 iconRight += fParent->IconSize(); … … NotificationView::SetText(const char* app, const char* title, const char* text, 517 462 518 463 // Title 519 464 LineInfo* titleLine = new LineInfo; 520 titleLine->text = f Title;465 titleLine->text = fNotification->Title(); 521 466 titleLine->font = *be_bold_font; 522 523 if (fParent->Layout() == AllTextRightOfIcon) 524 titleLine->location = BPoint(iconRight, y); 525 else 526 titleLine->location = BPoint(kEdgePadding, y); 467 titleLine->location = BPoint(iconRight, y); 527 468 528 469 fLines.push_front(titleLine); 529 470 y += fontHeight; 530 471 531 // Rest of text is rendered with be_plain_font .472 // Rest of text is rendered with be_plain_font 532 473 be_plain_font->GetHeight(&fh); 533 474 fontHeight = ceilf(fh.leading) + ceilf(fh.descent) 534 475 + ceilf(fh.ascent); 535 476 536 // Split text into chunks between certain characters and compose the lines .477 // Split text into chunks between certain characters and compose the lines 537 478 const char kSeparatorCharacters[] = " \n-\\/"; 538 BString textBuffer = f Text;479 BString textBuffer = fNotification->Content(); 539 480 textBuffer.ReplaceAll("\t", " "); 540 481 const char* chunkStart = textBuffer.String(); 541 482 float maxWidth = newMaxWidth - kEdgePadding - iconRight; … … NotificationView::SetText(const char* app, const char* title, const char* text, 544 485 while (chunkStart - textBuffer.String() < length) { 545 486 size_t chunkLength = strcspn(chunkStart, kSeparatorCharacters) + 1; 546 487 547 // Start a new line if either we didn't start one before, 548 // the current offset 488 // Start a new line if we didn't start one before 549 489 BString tempText; 550 490 if (line != NULL) 551 491 tempText.SetTo(line->text); … … NotificationView::SetText(const char* app, const char* title, const char* text, 560 500 fLines.push_front(line); 561 501 y += fontHeight; 562 502 563 // Skip the eventual new-line character at the beginning of this 564 // chunk. 503 // Skip the eventual new-line character at the beginning of this chunk 565 504 if (chunkStart[0] == '\n') { 566 505 chunkStart++; 567 506 chunkLength--; 568 507 } 569 // Skip more new-line characters and move the line further down. 508 509 // Skip more new-line characters and move the line further down 570 510 while (chunkStart[0] == '\n') { 571 511 chunkStart++; 572 512 chunkLength--; 573 513 line->location.y += fontHeight; 574 514 y += fontHeight; 575 515 } 576 // Strip space at beginning of a new line. 516 517 // Strip space at beginning of a new line 577 518 while (chunkStart[0] == ' ') { 578 519 chunkLength--; 579 520 chunkStart++; … … NotificationView::SetText(const char* app, const char* title, const char* text, 584 525 break; 585 526 586 527 // Append the chunk to the current line, which was either a new 587 // line or the one from the previous iteration .528 // line or the one from the previous iteration 588 529 line->text.Append(chunkStart, chunkLength); 589 530 590 531 chunkStart += chunkLength; … … NotificationView::SetText(const char* app, const char* title, const char* text, 594 535 595 536 // Make sure icon fits 596 537 if (fBitmap != NULL) { 597 float minHeight = 0; 598 if (fParent->Layout() == TitleAboveIcon) { 599 LineInfo* appLine = fLines.back(); 600 font_height fh; 601 appLine->font.GetHeight(&fh); 602 minHeight = appLine->location.y + fh.descent; 603 } 538 float minHeight = fBitmap->Bounds().Height() + 2 * kEdgePadding; 604 539 605 minHeight += fBitmap->Bounds().Height() + 2 * kEdgePadding;606 540 if (fHeight < minHeight) 607 541 fHeight = minHeight; 608 542 } 609 610 BMessenger messenger(Parent());611 messenger.SendMessage(kResizeToFit);612 }613 614 615 bool616 NotificationView::HasMessageID(const char* id)617 {618 return fMessageID == id;619 543 } 620 544 621 545 622 546 const char* 623 NotificationView::MessageID() 624 { 625 return fMessageID.String(); 626 } 627 628 629 void 630 NotificationView::SetPosition(bool first, bool last) 631 { 632 fIsFirst = first; 633 fIsLast = last; 634 } 635 636 637 BBitmap* 638 NotificationView::_ReadNodeIcon(const char* fileName, icon_size size) 547 NotificationView::MessageID() const 639 548 { 640 BEntry entry(fileName, true); 641 642 entry_ref ref; 643 entry.GetRef(&ref); 644 645 BNode node(BPath(&ref).Path()); 646 647 BBitmap* ret = new BBitmap(BRect(0, 0, (float)size - 1, (float)size - 1), B_RGBA32); 648 if (BIconUtils::GetIcon(&node, kIconAttribute, kSmallIconAttribute, 649 kLargeIconAttribute, size, ret) != B_OK) { 650 delete ret; 651 ret = NULL; 652 } 653 654 return ret; 549 return fNotification->MessageID(); 655 550 } 656 551 657 552 658 void 659 NotificationView::_ LoadIcon()553 BSize 554 NotificationView::_CalculateSize() 660 555 { 661 // First try to get the icon from the caller application 662 app_info info; 663 BMessenger msgr = fDetails->ReturnAddress(); 556 BSize size; 664 557 665 if (msgr.IsValid()) 666 be_roster->GetRunningAppInfo(msgr.Team(), &info); 667 else if (fType == B_PROGRESS_NOTIFICATION) 668 be_roster->GetAppInfo("application/x-vnd.Haiku-notification_server", 669 &info); 670 671 BPath path; 672 path.SetTo(&info.ref); 673 674 fBitmap = _ReadNodeIcon(path.Path(), fParent->IconSize()); 675 if (fBitmap) 676 return; 677 678 // If that failed get icons from app_server 679 if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) != B_OK) 680 return; 681 682 path.Append("app_server"); 683 684 BFile file(path.Path(), B_READ_ONLY); 685 if (file.InitCheck() != B_OK) 686 return; 687 688 BResources res(&file); 689 if (res.InitCheck() != B_OK) 690 return; 691 692 // Which one should we choose? 693 const char* iconName = ""; 694 switch (fType) { 695 case B_INFORMATION_NOTIFICATION: 696 iconName = "info"; 697 break; 698 case B_ERROR_NOTIFICATION: 699 iconName = "stop"; 700 break; 701 case B_IMPORTANT_NOTIFICATION: 702 iconName = "warn"; 703 break; 704 default: 705 return; 706 } 558 // Parent width, minus the edge padding, minus the pensize 559 size.width = fParent->Width() - (kEdgePadding * 2) - (kPenSize * 2); 560 size.height = fHeight; 707 561 708 // Allocate the bitmap 709 fBitmap = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1, 710 (float)B_LARGE_ICON - 1), B_RGBA32); 711 if (!fBitmap || fBitmap->InitCheck() != B_OK) { 712 fBitmap = NULL; 713 return; 562 if (fNotification->Type() == B_PROGRESS_NOTIFICATION) { 563 font_height fh; 564 be_plain_font->GetHeight(&fh); 565 float fontHeight = fh.ascent + fh.descent + fh.leading; 566 size.height += (kSmallPadding * 2) + (kEdgePadding * 1) + fontHeight; 714 567 } 715 568 716 // Load raw icon data 717 size_t size = 0; 718 const uint8* data = (const uint8*)res.LoadResource(B_VECTOR_ICON_TYPE, 719 iconName, &size); 720 if ((data == NULL 721 || BIconUtils::GetVectorIcon(data, size, fBitmap) != B_OK)) 722 fBitmap = NULL; 569 return size; 723 570 } -
src/servers/notification/NotificationView.h
diff --git a/src/servers/notification/NotificationView.h b/src/servers/notification/NotificationView.h index fb2fa07..46588a5 100644
a b 11 11 #include <list> 12 12 13 13 #include <Bitmap.h> 14 #include <Entry.h>15 #include <Message.h>16 14 #include <MessageRunner.h> 17 #include <MimeType.h>18 15 #include <Notification.h> 19 #include <Path.h>20 #include <Roster.h>21 #include <String.h>22 #include <TextView.h>23 16 #include <View.h> 24 17 25 18 class NotificationWindow; … … const uint32 kRemoveView = 'ReVi'; 29 22 class NotificationView : public BView { 30 23 public: 31 24 NotificationView(NotificationWindow* win, 32 notification_type type, 33 const char* app, const char* title, 34 const char* text, BMessage* details); 25 BNotification* notification, 26 bigtime_t timeout = -1); 35 27 virtual ~NotificationView(); 36 28 37 29 virtual void AttachedToWindow(); 38 30 virtual void MessageReceived(BMessage* message); 39 virtual void GetPreferredSize(float* width, float* height);40 31 virtual void Draw(BRect updateRect); 41 32 virtual void MouseDown(BPoint point); 42 virtual void FrameResized(float width, float height); 33 34 virtual BSize MinSize(); 35 virtual BSize MaxSize(); 36 virtual BSize PreferredSize(); 43 37 44 38 virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index, 45 39 BMessage* specifier, int32 form, 46 40 const char* property); 47 41 virtual status_t GetSupportedSuites(BMessage* msg); 48 42 49 const char* Application() const; 50 const char* Title() const; 51 const char* Text() const; 43 void SetText(float newMaxWidth = -1); 52 44 53 void SetText(const char* app, const char* title, 54 const char* text, float newMaxWidth = -1); 55 bool HasMessageID(const char* id); 56 const char* MessageID(); 57 void SetPosition(bool first, bool last); 45 const char* MessageID() const; 58 46 59 47 private: 60 BBitmap* _ReadNodeIcon(const char* fileName, 61 icon_size size); 62 void _LoadIcon(); 48 BSize _CalculateSize(); 63 49 64 private:65 50 struct LineInfo { 66 51 BFont font; 67 52 BString text; … … private: 70 55 71 56 typedef std::list<LineInfo*> LineInfoList; 72 57 73 74 58 NotificationWindow* fParent; 59 BNotification* fNotification; 60 bigtime_t fTimeout; 75 61 76 notification_type fType;77 62 BMessageRunner* fRunner; 78 float fProgress;79 BString fMessageID;80 63 81 BMessage* fDetails;82 64 BBitmap* fBitmap; 83 65 84 66 LineInfoList fLines; 85 67 86 BString fApp;87 BString fTitle;88 BString fText;89 90 68 float fHeight; 91 92 bool fIsFirst;93 bool fIsLast;94 69 }; 95 70 96 71 #endif // _NOTIFICATION_VIEW_H -
src/servers/notification/NotificationWindow.cpp
diff --git a/src/servers/notification/NotificationWindow.cpp b/src/servers/notification/NotificationWindow.cpp index 74b54be..6a20d1e 100644
a b 15 15 16 16 #include <Alert.h> 17 17 #include <Application.h> 18 #include <Debug.h>19 18 #include <File.h> 19 #include <GroupLayout.h> 20 #include <GroupLayoutBuilder.h> 20 21 #include <NodeMonitor.h> 22 #include <Path.h> 21 23 #include <PropertyInfo.h> 22 24 23 25 #include "AppGroupView.h" 24 26 #include "AppUsage.h" 25 #include "BorderView.h"26 27 #include "NotificationWindow.h" 27 28 28 29 property_info main_prop_list[] = { 29 { "message", {B_GET_PROPERTY, 0}, {B_INDEX_SPECIFIER, 0}, "get a message"}, 30 { "message", {B_COUNT_PROPERTIES, 0}, {B_DIRECT_SPECIFIER, 0}, "count messages"}, 31 { "message", {B_CREATE_PROPERTY, 0}, {B_DIRECT_SPECIFIER, 0}, "create a message"}, 32 { "message", {B_SET_PROPERTY, 0}, {B_INDEX_SPECIFIER, 0 }, "modify a message" }, 33 0 30 { 31 "message", 32 { B_GET_PROPERTY, 0 }, 33 { B_INDEX_SPECIFIER, 0 }, 34 "get a message" 35 }, 36 { 37 "message", 38 { B_COUNT_PROPERTIES, 0 }, 39 { B_DIRECT_SPECIFIER, 0 }, 40 "count messages" 41 }, 42 { 43 "message", 44 { B_CREATE_PROPERTY, 0 }, 45 { B_DIRECT_SPECIFIER, 0 }, 46 "create a message" 47 }, 48 { 49 "message", 50 { B_SET_PROPERTY, 0 }, 51 { B_INDEX_SPECIFIER, 0 }, 52 "modify a message" 53 }, 54 { 0, { 0 }, { 0 }, 0, 0 } 34 55 }; 35 56 36 const float kCloseSize 37 const float kExpandSize 38 const float kPenSize 39 const float kEdgePadding 40 const float kSmallPadding 57 const float kCloseSize = 8; 58 const float kExpandSize = 8; 59 const float kPenSize = 1; 60 const float kEdgePadding = 5; 61 const float kSmallPadding = 2; 41 62 42 63 43 64 NotificationWindow::NotificationWindow() 44 65 : 45 BWindow(BRect( 10, 10, 30, 30), "Notification", B_BORDERED_WINDOW,66 BWindow(BRect(0, 0, -1, -1), "Notification", B_BORDERED_WINDOW, 46 67 B_AVOID_FRONT | B_AVOID_FOCUS | B_NOT_CLOSABLE | B_NOT_ZOOMABLE 47 | B_NOT_MINIMIZABLE | B_NOT_RESIZABLE, B_ALL_WORKSPACES) 68 | B_NOT_MINIMIZABLE | B_NOT_RESIZABLE | B_AUTO_UPDATE_SIZE_LIMITS, 69 B_ALL_WORKSPACES) 48 70 { 49 fBorder = new BorderView(Bounds(), "Notification"); 71 BGroupLayout* layout = new BGroupLayout(B_VERTICAL, 10); 72 layout->SetInsets(5, 5, 5, 5); 50 73 51 AddChild(fBorder); 74 fView = new BView("top", B_WILL_DRAW, layout); 75 fView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 52 76 77 SetLayout(new BGroupLayout(B_VERTICAL)); 78 AddChild(BGroupLayoutBuilder(B_VERTICAL) 79 .Add(fView) 80 ); 81 82 // The first Show() starts the loop so we have to call Show() and Hide(), 83 // after moving the window out of sight - I'm not sure if Run() is more 84 // appropriate 85 MoveTo(-1, -1); 53 86 Show(); 54 87 Hide(); 55 88 56 LoadSettings(true);57 LoadAppFilters(true);89 _LoadSettings(true); 90 _LoadAppFilters(true); 58 91 } 59 92 60 93 61 94 NotificationWindow::~NotificationWindow() 62 95 { 63 appfilter_t::iterator aIt; 64 for (aIt = fAppFilters.begin(); aIt != fAppFilters.end(); aIt++) 65 delete aIt->second; 96 appfilter_t::iterator fIt; 97 for (fIt = fAppFilters.begin(); fIt != fAppFilters.end(); ++fIt) 98 delete fIt->second; 99 100 appview_t::iterator gIt; 101 for (gIt = fAppViews.begin(); gIt != fAppViews.end(); ++gIt) { 102 fView->GetLayout()->RemoveView(gIt->second); 103 delete gIt->second; 104 } 66 105 } 67 106 68 107 69 108 bool 70 109 NotificationWindow::QuitRequested() 71 110 { 72 appview_t::iterator aIt; 73 for (aIt = fAppViews.begin(); aIt != fAppViews.end(); aIt++) { 74 aIt->second->RemoveSelf(); 75 delete aIt->second; 76 } 77 78 BMessenger(be_app).SendMessage(B_QUIT_REQUESTED); 79 return BWindow::QuitRequested(); 111 be_app_messenger.SendMessage(B_QUIT_REQUESTED); 112 return true; 80 113 } 81 114 82 115 83 116 void 84 NotificationWindow::WorkspaceActivated(int32 /*workspace*/, bool active)117 NotificationWindow::WorkspaceActivated(int32 workspace, bool active) 85 118 { 86 // Ensure window is in the correct position87 119 if (active) 88 ResizeAll(); 120 // Ensure window is in the current position 121 _ResizeAll(); 89 122 } 90 123 91 124 … … NotificationWindow::MessageReceived(BMessage* message) 95 128 switch (message->what) { 96 129 case B_NODE_MONITOR: 97 130 { 98 LoadSettings();99 LoadAppFilters();131 _LoadSettings(); 132 _LoadAppFilters(); 100 133 break; 101 134 } 102 case kResizeToFit:103 ResizeAll();104 break;105 135 case B_COUNT_PROPERTIES: 106 136 { 107 137 BMessage reply(B_REPLY); … … NotificationWindow::MessageReceived(BMessage* message) 129 159 case B_CREATE_PROPERTY: 130 160 case kNotificationMessage: 131 161 { 132 int32 type;133 const char* content = NULL;134 const char* title = NULL;135 const char* app = NULL;136 162 BMessage reply(B_REPLY); 137 bool messageOkay = true;163 BNotification* notification = new BNotification(message); 138 164 139 if (message->FindInt32("type", &type) != B_OK) 140 type = B_INFORMATION_NOTIFICATION; 141 if (message->FindString("content", &content) != B_OK) 142 messageOkay = false; 143 if (message->FindString("title", &title) != B_OK) 144 messageOkay = false; 145 if (message->FindString("app", &app) != B_OK && message->FindString("appTitle", &app) != B_OK) 146 messageOkay = false; 165 if (notification->InitCheck() == B_OK) { 166 // Time out 167 bigtime_t timeout; 168 if (message->FindInt64("timeout", &timeout) != B_OK) 169 timeout = -1; 147 170 148 if (messageOkay) {149 NotificationView* view = new NotificationView(this, (notification_type)type, app,150 title, content, new BMessage(*message));171 // Determine sender's signature 172 BMessenger messenger = message->ReturnAddress(); 173 app_info info; 151 174 152 appfilter_t::iterator fIt = fAppFilters.find(app); 153 bool allow = false; 154 if (fIt == fAppFilters.end()) { 155 app_info info; 156 BMessenger messenger = message->ReturnAddress(); 157 if (messenger.IsValid()) 158 be_roster->GetRunningAppInfo(messenger.Team(), &info); 159 else 160 be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info); 175 if (messenger.IsValid()) 176 be_roster->GetRunningAppInfo(messenger.Team(), &info); 177 else 178 be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info); 161 179 162 AppUsage* appUsage = new AppUsage(info.ref, app, true);163 fAppFilters[app] = appUsage;180 NotificationView* view = new NotificationView(this, notification, 181 timeout); 164 182 165 appUsage->Allowed(title, (notification_type)type); 183 bool allow = false; 184 appfilter_t::iterator it = fAppFilters.find(info.signature); 166 185 186 if (it == fAppFilters.end()) { 187 AppUsage* appUsage = new AppUsage(notification->Group(), true); 188 appUsage->Allowed(notification->Title(), notification->Type()); 189 fAppFilters[info.signature] = appUsage; 167 190 allow = true; 168 191 } else 169 allow = fIt->second->Allowed(title, (notification_type)type); 192 allow = it->second->Allowed(notification->Title(), notification->Type()); 193 _SaveAppFilters(); 170 194 171 195 if (allow) { 172 appview_t::iterator aIt = fAppViews.find(app); 173 AppGroupView *group = NULL; 196 BString groupName(notification->Group()); 197 AppGroupView* group = NULL; 198 appview_t::iterator aIt = fAppViews.find(groupName); 199 174 200 if (aIt == fAppViews.end()) { 175 group = new AppGroupView(this, app); 176 fAppViews[app] = group; 177 fBorder->AddChild(group); 178 } else { 201 group = new AppGroupView(this, 202 groupName == "" ? NULL : groupName.String()); 203 fAppViews[groupName] = group; 204 fView->GetLayout()->AddView(group); 205 } else 179 206 group = aIt->second; 180 }; 181 group->AddInfo(view); 182 183 ResizeAll(); 184 207 208 if (group) { 209 group->AddInfo(view); 210 fViews.push_back(view); 211 } 212 213 _ResizeAll(); 214 185 215 reply.AddInt32("error", B_OK); 186 216 } else 187 reply.AddInt32(" Error", B_ERROR);217 reply.AddInt32("error", B_ERROR); 188 218 } else { 189 219 reply.what = B_MESSAGE_NOT_UNDERSTOOD; 190 220 reply.AddInt32("error", B_ERROR); … … NotificationWindow::MessageReceived(BMessage* message) 195 225 } 196 226 case kRemoveView: 197 227 { 198 void* _ptr; 199 message->FindPointer("view", &_ptr); 200 201 NotificationView* info 202 = reinterpret_cast<NotificationView*>(_ptr); 228 NotificationView* view = NULL; 229 if (message->FindPointer("view", (void**)&view) != B_OK) 230 return; 203 231 204 fBorder->RemoveChild(info);232 views_t::iterator it = find(fViews.begin(), fViews.end(), view); 205 233 206 std::vector<NotificationView*>::iterator i 207 = find(fViews.begin(), fViews.end(), info); 208 if (i != fViews.end()) 209 fViews.erase(i); 234 if (it != fViews.end()) 235 fViews.erase(it); 210 236 211 delete info; 212 213 ResizeAll(); 237 _ResizeAll(); 214 238 break; 215 239 } 216 240 default: … … NotificationWindow::ResolveSpecifier(BMessage *msg, int32 index, 266 290 267 291 268 292 icon_size 269 NotificationWindow::IconSize() 293 NotificationWindow::IconSize() const 270 294 { 271 295 return fIconSize; 272 296 } 273 297 274 298 275 299 int32 276 NotificationWindow::Timeout() 300 NotificationWindow::Timeout() const 277 301 { 278 302 return fTimeout; 279 303 } 280 304 281 305 282 306 283 infoview_layout284 NotificationWindow::Layout()285 {286 return fLayout;287 }288 289 290 307 float 291 NotificationWindow:: ViewWidth()308 NotificationWindow::Width() const 292 309 { 293 310 return fWidth; 294 311 } 295 312 296 313 297 314 void 298 NotificationWindow:: ResizeAll()315 NotificationWindow::_ResizeAll() 299 316 { 317 // Hide if no group views are available 300 318 if (fAppViews.empty()) { 301 319 if (!IsHidden()) 302 320 Hide(); … … NotificationWindow::ResizeAll() 307 325 bool shouldHide = true; 308 326 309 327 for (aIt = fAppViews.begin(); aIt != fAppViews.end(); aIt++) { 310 AppGroupView *app = aIt->second; 311 if (app->HasChildren()) { 328 AppGroupView* groupView = aIt->second; 329 330 // We should not hide the notification window if at least 331 // one group view has children 332 if (groupView->HasChildren()) 312 333 shouldHide = false; 313 break;314 }334 else if (!groupView->IsHidden()) 335 groupView->Hide(); 315 336 } 316 337 317 if (shouldHide) { 318 if (!IsHidden()) 319 Hide(); 338 if (shouldHide && !IsHidden()) { 339 Hide(); 320 340 return; 321 341 } 322 342 323 if (IsHidden()) 324 Show(); 325 326 float width = 0; 327 float height = 0; 328 329 for (aIt = fAppViews.begin(); aIt != fAppViews.end(); aIt++) { 330 AppGroupView* view = aIt->second; 331 float w = -1; 332 float h = -1; 333 334 if (!view->HasChildren()) { 335 if (!view->IsHidden()) 336 view->Hide(); 337 } else { 338 view->GetPreferredSize(&w, &h); 339 width = max_c(width, h); 340 341 view->ResizeToPreferred(); 342 view->MoveTo(0, height); 343 344 height += h; 345 346 if (view->IsHidden()) 347 view->Show(); 348 } 349 } 350 351 ResizeTo(ViewWidth(), height); 352 PopupAnimation(Bounds().Width(), Bounds().Height()); 343 _PopupAnimation(); 353 344 } 354 345 355 346 356 347 void 357 NotificationWindow:: PopupAnimation(float width, float height)348 NotificationWindow::_PopupAnimation() 358 349 { 350 float width = Width(); 351 float height = fView->Bounds().Height(); 352 359 353 float x = 0, y = 0, sx, sy; 360 354 float pad = 0; 361 355 BDeskbar deskbar; … … NotificationWindow::PopupAnimation(float width, float height) 365 359 case B_DESKBAR_TOP: 366 360 // Put it just under, top right corner 367 361 sx = frame.right; 368 sy = frame.bottom +pad;362 sy = frame.bottom + pad; 369 363 y = sy; 370 x = sx -width-pad;364 x = sx - width - pad; 371 365 break; 372 366 case B_DESKBAR_BOTTOM: 373 367 // Put it just above, lower left corner 374 368 sx = frame.right; 375 sy = frame.top -height-pad;369 sy = frame.top - height - pad; 376 370 y = sy; 377 x = sx - width -pad;371 x = sx - width - pad; 378 372 break; 379 373 case B_DESKBAR_LEFT_TOP: 380 374 // Put it just to the right of the deskbar 381 sx = frame.right +pad;382 sy = frame.top -height;375 sx = frame.right + pad; 376 sy = frame.top - height; 383 377 x = sx; 384 y = frame.top +pad;378 y = frame.top + pad; 385 379 break; 386 380 case B_DESKBAR_RIGHT_TOP: 387 381 // Put it just to the left of the deskbar 388 sx = frame.left -width-pad;389 sy = frame.top -height;382 sx = frame.left - width - pad; 383 sy = frame.top - height; 390 384 x = sx; 391 y = frame.top +pad;385 y = frame.top + pad; 392 386 break; 393 387 case B_DESKBAR_LEFT_BOTTOM: 394 388 // Put it to the right of the deskbar. 395 sx = frame.right +pad;389 sx = frame.right + pad; 396 390 sy = frame.bottom; 397 391 x = sx; 398 y = sy -height-pad;392 y = sy - height - pad; 399 393 break; 400 394 case B_DESKBAR_RIGHT_BOTTOM: 401 395 // Put it to the left of the deskbar. 402 sx = frame.left -width-pad;396 sx = frame.left - width - pad; 403 397 sy = frame.bottom; 404 y = sy -height-pad;398 y = sy - height - pad; 405 399 x = sx; 406 400 break; 407 401 default: … … NotificationWindow::PopupAnimation(float width, float height) 409 403 } 410 404 411 405 MoveTo(x, y); 412 413 if (IsHidden() && fViews.size() != 0)406 407 if (IsHidden()) 414 408 Show(); 415 //Activate();// it hides floaters from apps :-(416 409 } 417 410 418 411 419 412 void 420 NotificationWindow:: LoadSettings(bool startMonitor)413 NotificationWindow::_LoadSettings(bool startMonitor) 421 414 { 422 415 _LoadGeneralSettings(startMonitor); 423 416 _LoadDisplaySettings(startMonitor); … … NotificationWindow::LoadSettings(bool startMonitor) 425 418 426 419 427 420 void 428 NotificationWindow:: LoadAppFilters(bool startMonitor)421 NotificationWindow::_LoadAppFilters(bool startMonitor) 429 422 { 430 423 BPath path; 431 424 … … NotificationWindow::LoadAppFilters(bool startMonitor) 471 464 472 465 473 466 void 474 NotificationWindow:: SaveAppFilters()467 NotificationWindow::_SaveAppFilters() 475 468 { 476 469 BPath path; 477 470 … … NotificationWindow::_LoadGeneralSettings(bool startMonitor) 516 509 views_t::iterator it; 517 510 for (it = fViews.begin(); it != fViews.end(); ++it) { 518 511 NotificationView* view = (*it); 519 view->SetText(view->Application(), view->Title(), view->Text());520 512 view->Invalidate(); 521 513 } 522 514 … … NotificationWindow::_LoadGeneralSettings(bool startMonitor) 526 518 entry.GetNodeRef(&nref); 527 519 528 520 if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) { 529 BAlert* alert = new BAlert("", " Couldn't start general settings"530 " monitor.\nLive filter changes disabled.", "OK");521 BAlert* alert = new BAlert("", "Notification service: Couldn't start " 522 "general settings monitor.\nLive filter changes disabled.", "OK"); 531 523 alert->Go(); 532 524 } 533 525 } … … NotificationWindow::_LoadDisplaySettings(bool startMonitor) 561 553 else 562 554 fIconSize = (icon_size)setting; 563 555 564 if (settings.FindInt32(kLayoutName, &setting) != B_OK)565 fLayout = kDefaultLayout;566 else {567 switch (setting) {568 case 0:569 fLayout = TitleAboveIcon;570 break;571 case 1:572 fLayout = AllTextRightOfIcon;573 break;574 default:575 fLayout = kDefaultLayout;576 }577 }578 579 556 // Notify the view about the change 580 557 views_t::iterator it; 581 558 for (it = fViews.begin(); it != fViews.end(); ++it) { 582 559 NotificationView* view = (*it); 583 view->SetText(view->Application(), view->Title(), view->Text());584 560 view->Invalidate(); 585 561 } 586 562 … … NotificationWindow::_LoadDisplaySettings(bool startMonitor) 590 566 entry.GetNodeRef(&nref); 591 567 592 568 if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) { 593 BAlert* alert = new BAlert("", " Couldn't start display settings"594 " monitor.\nLive filter changes disabled.", "OK");569 BAlert* alert = new BAlert("", "Notification service: Couldn't start " 570 "display settings monitor.\nLive filter changes disabled.", "OK"); 595 571 alert->Go(); 596 572 } 597 573 } -
src/servers/notification/NotificationWindow.h
diff --git a/src/servers/notification/NotificationWindow.h b/src/servers/notification/NotificationWindow.h index a246f7e..29ed9b3 100644
a b 26 26 27 27 class AppGroupView; 28 28 class AppUsage; 29 class BorderView;30 class SettingsFile;31 29 32 30 typedef std::map<BString, AppGroupView*> appview_t; 33 31 typedef std::map<BString, AppUsage*> appfilter_t; … … extern const float kCloseSize; 39 37 extern const float kExpandSize; 40 38 extern const float kPenSize; 41 39 42 const uint32 kResizeToFit = 'IWrf';43 44 40 class NotificationWindow : public BWindow { 45 41 public: 46 42 NotificationWindow(); … … public: 48 44 49 45 virtual bool QuitRequested(); 50 46 virtual void MessageReceived(BMessage*); 51 virtual void WorkspaceActivated(int32, bool);47 virtual void WorkspaceActivated(int32 workspace, bool active); 52 48 virtual BHandler* ResolveSpecifier(BMessage*, int32, BMessage*, 53 49 int32, const char*); 54 50 55 icon_size IconSize(); 56 int32 Timeout(); 57 infoview_layout Layout(); 58 float ViewWidth(); 59 60 void ResizeAll(); 51 icon_size IconSize() const; 52 int32 Timeout() const; 53 float Width() const; 61 54 62 55 private: 63 friend class AppGroupView; 56 void _ResizeAll(); 57 58 void _PopupAnimation(); 64 59 65 void PopupAnimation(float, float); 66 void LoadSettings(bool startMonitor = false); 67 void LoadAppFilters(bool startMonitor = false); 68 void SaveAppFilters(); 60 void _LoadSettings(bool startMonitor = false); 61 void _LoadAppFilters(bool startMonitor = false); 62 void _SaveAppFilters(); 69 63 void _LoadGeneralSettings(bool startMonitor); 70 64 void _LoadDisplaySettings(bool startMonitor); 71 65 72 views_t fViews; 73 BorderView* fBorder; 66 BView* fView; 74 67 68 views_t fViews; 75 69 appview_t fAppViews; 76 70 77 71 BString fStatusText; … … private: 80 74 float fWidth; 81 75 icon_size fIconSize; 82 76 int32 fTimeout; 83 infoview_layout fLayout;84 77 85 78 appfilter_t fAppFilters; 86 79 };