Ticket #1245: infopopper.patch
File infopopper.patch, 141.6 KB (added by , 15 years ago) |
---|
-
build/jam/HaikuImage
diff --git a/build/jam/HaikuImage b/build/jam/HaikuImage index 9e9cd66..24f585a 100644
a b SYSTEM_BIN = "[" addattr alert arp base64 basename bash bc beep bootman bzip2 44 44 listport listres listsem listusb ln locate logger login logname ls lsindex 45 45 mail2mbox makebootable mbox2mail md5sum merge message mimeset mkdos mkdir 46 46 mkfifo mkfs mkindex mktemp modifiers mount mount_nfs mountvolume mv 47 netcat netstat nl nohup n proc47 netcat netstat nl nohup notify nproc 48 48 od open 49 49 passwd paste patch pathchk pc ping play playfile playsound playwav pr prio 50 50 printenv printf profile ps ptx pwd … … SYSTEM_APPS = AboutSystem ActivityMonitor CharacterMap CodyCam DeskCalc Devices 70 70 ; 71 71 SYSTEM_PREFERENCES = Appearance Backgrounds CPUFrequency DataTranslations 72 72 <preference>Deskbar E-mail FileTypes Fonts Keyboard Keymap Locale Media 73 Mouse Network OpenGL Printers Screen ScreenSaver Shortcuts Sounds Time73 Mouse Network Notifications OpenGL Printers Screen ScreenSaver Shortcuts Sounds Time 74 74 Touchpad <preference>Tracker VirtualMemory 75 75 ; 76 76 SYSTEM_DEMOS = BSnow Chart Clock Cortex FontDemo … … PRIVATE_SYSTEM_LIBS = 103 103 ; 104 104 SYSTEM_SERVERS = app_server cddb_daemon debug_server input_server mail_daemon 105 105 media_addon_server media_server midi_server mount_server net_server 106 print_server registrar syslog_daemon106 notification_server print_server registrar syslog_daemon 107 107 ; 108 108 109 109 SYSTEM_NETWORK_DEVICES = ethernet loopback ; -
new file headers/os/app/Notification.h
diff --git a/headers/os/app/Notification.h b/headers/os/app/Notification.h new file mode 100644 index 0000000..6f9c100
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _NOTIFICATION_H 6 #define _NOTIFICATION_H 7 8 #include <Entry.h> 9 10 // notification types 11 enum notification_type { 12 B_INFORMATION_NOTIFICATION, 13 B_IMPORTANT_NOTIFICATION, 14 B_ERROR_NOTIFICATION, 15 B_PROGRESS_NOTIFICATION 16 }; 17 18 class BBitmap; 19 class BList; 20 21 class BNotification { 22 public: 23 BNotification(notification_type type); 24 ~BNotification(); 25 26 notification_type Type() const; 27 28 const char* Application() const; 29 void SetApplication(const char* app); 30 31 const char* Title() const; 32 void SetTitle(const char* title); 33 34 const char* Content() const; 35 void SetContent(const char* content); 36 37 const char* MessageID() const; 38 void SetMessageID(const char* id); 39 40 float Progress() const; 41 void SetProgress(float progress); 42 43 const char* OnClickApp() const; 44 void SetOnClickApp(const char* app); 45 46 entry_ref* OnClickFile() const; 47 void SetOnClickFile(const entry_ref* file); 48 49 BList* OnClickRefs() const; 50 void AddOnClickRef(const entry_ref* ref); 51 52 BList* OnClickArgv() const; 53 void AddOnClickArg(const char* arg); 54 55 BBitmap* Icon() const; 56 void SetIcon(BBitmap* icon); 57 58 private: 59 notification_type fType; 60 char* fAppName; 61 char* fTitle; 62 char* fContent; 63 char* fID; 64 float fProgress; 65 char* fApp; 66 entry_ref* fFile; 67 BList* fRefs; 68 BList* fArgv; 69 BBitmap* fBitmap; 70 }; 71 72 #endif // _NOTIFICATION_H -
headers/os/app/Roster.h
diff --git a/headers/os/app/Roster.h b/headers/os/app/Roster.h index 50a6612..641c9c6 100644
a b 13 13 class BFile; 14 14 class BMimeType; 15 15 class BNodeInfo; 16 class BNotification; 16 17 17 18 18 19 struct app_info { … … class BRoster { 116 117 void AddToRecentFolders(const entry_ref *folder, 117 118 const char *appSig = 0) const; 118 119 120 // notifications 121 status_t Notify(BNotification* notification, 122 int32 timeout = -1) const; 123 119 124 // private/reserved stuff starts here 120 125 class Private; 121 126 -
new file headers/private/notification/AppUsage.h
diff --git a/headers/private/notification/AppUsage.h b/headers/private/notification/AppUsage.h new file mode 100644 index 0000000..c245c77
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 */ 8 #ifndef _APP_USAGE_H 9 #define _APP_USAGE_H 10 11 #include <map> 12 13 #include <Entry.h> 14 #include <Flattenable.h> 15 #include <Notification.h> 16 #include <Roster.h> 17 #include <String.h> 18 19 class BMessage; 20 class NotificationReceived; 21 22 typedef std::map<BString, NotificationReceived*> notify_t; 23 24 class AppUsage : public BFlattenable { 25 public: 26 AppUsage(); 27 AppUsage(entry_ref ref, const char* name, 28 bool allow = true); 29 ~AppUsage(); 30 31 virtual bool AllowsTypeCode(type_code code) const; 32 virtual status_t Flatten(void* buffer, ssize_t numBytes) const; 33 virtual ssize_t FlattenedSize() const; 34 virtual bool IsFixedSize() const; 35 virtual type_code TypeCode() const; 36 virtual status_t Unflatten(type_code code, const void* buffer, 37 ssize_t numBytes); 38 39 entry_ref Ref(); 40 const char* Name(); 41 bool Allowed(const char* title, notification_type type); 42 bool Allowed(); 43 NotificationReceived* NotificationAt(int32 index); 44 int32 Notifications(); 45 void AddNotification(NotificationReceived* notification); 46 47 private: 48 entry_ref fRef; 49 BString fName; 50 bool fAllow; 51 notify_t fNotifications; 52 }; 53 54 #endif // _APP_USAGE_H -
new file headers/private/notification/NotificationReceived.h
diff --git a/headers/private/notification/NotificationReceived.h b/headers/private/notification/NotificationReceived.h new file mode 100644 index 0000000..9d8a88f
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 */ 8 #ifndef _NOTIFICATION_RECEIVED_H 9 #define _NOTIFICATION_RECEIVED_H 10 11 #include <Flattenable.h> 12 #include <Roster.h> 13 #include <String.h> 14 15 class NotificationReceived : public BFlattenable { 16 public: 17 NotificationReceived(); 18 NotificationReceived(const char* title, notification_type type, 19 bool enabled = true); 20 ~NotificationReceived(); 21 22 virtual bool AllowsTypeCode(type_code code) const; 23 virtual status_t Flatten(void *buffer, ssize_t numBytes) const; 24 virtual ssize_t FlattenedSize() const; 25 virtual bool IsFixedSize() const; 26 virtual type_code TypeCode() const; 27 virtual status_t Unflatten(type_code code, const void *buffer, 28 ssize_t numBytes); 29 30 const char* Title(); 31 notification_type Type(); 32 void SetType(notification_type type); 33 time_t LastReceived(); 34 bool Allowed(); 35 36 void SetTimeStamp(time_t time); 37 void UpdateTimeStamp(); 38 39 private: 40 BString fTitle; 41 notification_type fType; 42 bool fEnabled; 43 time_t fLastReceived; 44 }; 45 46 #endif // _NOTIFICATION_RECEIVED_H -
new file headers/private/notification/Notifications.h
diff --git a/headers/private/notification/Notifications.h b/headers/private/notification/Notifications.h new file mode 100644 index 0000000..964b026
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _NOTIFICATIONS_H 6 #define _NOTIFICATIONS_H 7 8 #include <Mime.h> 9 10 #define kNotificationServerSignature "application/x-vnd.Haiku-notification_server" 11 12 // Messages 13 const uint32 kNotificationMessage = 'nssm'; 14 15 // Notification layout 16 enum infoview_layout { 17 TitleAboveIcon = 0, 18 AllTextRightOfIcon = 1 19 }; 20 21 // Settings constants 22 extern const char* kSettingsDirectory; 23 extern const char* kFiltersSettings; 24 extern const char* kGeneralSettings; 25 extern const char* kDisplaySettings; 26 27 // General settings 28 extern const char* kAutoStartName; 29 extern const char* kTimeoutName; 30 31 // General default settings 32 const float kDefaultAutoStart = false; 33 const int32 kDefaultTimeout = 10; 34 35 // Display settings 36 extern const char* kWidthName; 37 extern const char* kIconSizeName; 38 extern const char* kLayoutName; 39 40 // Display default settings 41 const float kDefaultWidth = 300.0f; 42 const icon_size kDefaultIconSize = B_LARGE_ICON; 43 const infoview_layout kDefaultLayout = TitleAboveIcon; 44 45 #endif // _NOTIFICATIONS_H -
src/bin/Jamfile
diff --git a/src/bin/Jamfile b/src/bin/Jamfile index 03e8ebd..5425646 100644
a b UsePrivateSystemHeaders ; 9 9 SubDirHdrs $(HAIKU_TOP) src add-ons kernel file_cache ; 10 10 UseLibraryHeaders ncurses ; 11 11 UseLibraryHeaders termcap ; 12 UseLibraryHeaders icon ; 12 13 13 14 local haiku-utils_rsrc = [ FGristFiles haiku-utils.rsrc ] ; 14 15 … … StdBinCommands 157 158 translate.cpp 158 159 : be translation $(TARGET_LIBSUPC++) : $(haiku-utils_rsrc) ; 159 160 161 # standard commands that need libbe.so, libtranslation.so, libicon.a, libstdc++.so 162 StdBinCommands 163 notify.cpp 164 : be translation libicon.a $(TARGET_LIBSTDC++) : $(haiku-utils_rsrc) ; 165 160 166 # standard commands that need libbe.so, libmedia.so 161 167 StdBinCommands 162 168 installsound.cpp -
new file src/bin/notify.cpp
diff --git a/src/bin/notify.cpp b/src/bin/notify.cpp new file mode 100644 index 0000000..1528f39
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All rights reserved. 3 * Copyright 2008, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <string.h> 13 14 #include <Application.h> 15 #include <Bitmap.h> 16 #include <IconUtils.h> 17 #include <List.h> 18 #include <Mime.h> 19 #include <Notification.h> 20 #include <Path.h> 21 #include <Roster.h> 22 #include <TranslationUtils.h> 23 24 const char* kSignature = "application/x-vnd.Haiku-notify"; 25 const char* kSmallIconAttribute = "BEOS:M:STD_ICON"; 26 const char* kLargeIconAttribute = "BEOS:L:STD_ICON"; 27 const char* kIconAttribute = "BEOS:ICON"; 28 29 const char *kTypeNames[] = { 30 "information", 31 "important", 32 "error", 33 "progress", 34 NULL 35 }; 36 37 const int32 kErrorInitFail = 127; 38 const int32 kErrorArgumentsFail = 126; 39 40 class NotifyApp : public BApplication { 41 public: 42 NotifyApp(); 43 virtual ~NotifyApp(); 44 45 virtual void ReadyToRun(); 46 virtual void ArgvReceived(int32 argc, char** argv); 47 48 bool GoodArguments() const { return fOk; } 49 50 private: 51 bool fOk; 52 notification_type fType; 53 const char* fAppName; 54 const char* fTitle; 55 const char* fMsgId; 56 float fProgress; 57 int32 fTimeout; 58 const char* fIconFile; 59 entry_ref fFileRef; 60 const char* fMessage; 61 const char* fApp; 62 bool fHasFile; 63 entry_ref fFile; 64 BList* fRefs; 65 BList* fArgv; 66 67 void _Usage() const; 68 BBitmap* _GetBitmap(const entry_ref* ref) const; 69 }; 70 71 72 NotifyApp::NotifyApp() 73 : 74 BApplication(kSignature), 75 fOk(false), 76 fType(B_INFORMATION_NOTIFICATION), 77 fAppName(NULL), 78 fTitle(NULL), 79 fMsgId(NULL), 80 fProgress(0.0f), 81 fTimeout(0), 82 fIconFile(NULL), 83 fMessage(NULL), 84 fApp(NULL), 85 fHasFile(false) 86 { 87 fRefs = new BList(); 88 fArgv = new BList(); 89 } 90 91 92 NotifyApp::~NotifyApp() 93 { 94 if (fAppName) 95 free((void*)fAppName); 96 if (fTitle) 97 free((void*)fTitle); 98 if (fMsgId) 99 free((void*)fMsgId); 100 if (fIconFile) 101 free((void*)fIconFile); 102 if (fMessage) 103 free((void*)fMessage); 104 if (fApp) 105 free((void*)fApp); 106 107 int32 i; 108 void* item; 109 110 for (i = 0; item = fRefs->ItemAt(i); i++) 111 delete item; 112 delete fRefs; 113 114 for (i = 0; item = fArgv->ItemAt(i); i++) { 115 if (item != NULL) 116 free(item); 117 } 118 delete fArgv; 119 } 120 121 122 void 123 NotifyApp::ArgvReceived(int32 argc, char** argv) 124 { 125 const uint32 kArgCount = argc - 1; 126 uint32 index = 1; 127 128 // Look for valid options 129 for (; index <= kArgCount; ++index) { 130 if (argv[index][0] == '-' && argv[index][1] == '-') { 131 const char* option = argv[index] + 2; 132 133 if (++index > kArgCount) { 134 // No argument to option 135 fprintf(stderr, "Missing argument to option --%s\n\n", option); 136 return; 137 } 138 139 const char* argument = argv[index]; 140 141 if (strcmp(option, "type") == 0) { 142 for (int32 i = 0; kTypeNames[i]; i++) { 143 if (strncmp(kTypeNames[i], argument, strlen(argument)) == 0) 144 fType = (notification_type)i; 145 } 146 } else if (strcmp(option, "app") == 0) { 147 fAppName = strdup(argument); 148 } else if (strcmp(option, "title") == 0) { 149 fTitle = strdup(argument); 150 } else if (strcmp(option, "messageID") == 0) { 151 fMsgId = strdup(argument); 152 } else if (strcmp(option, "progress") == 0) { 153 fProgress = atof(argument); 154 } else if (strcmp(option, "timeout") == 0) { 155 fTimeout = atol(argument); 156 } else if (strcmp(option, "icon") == 0) { 157 fIconFile = strdup(argument); 158 159 if (get_ref_for_path(fIconFile, &fFileRef) < B_OK) { 160 fprintf(stderr, "Bad icon path!\n\n"); 161 return; 162 } 163 } else if (strcmp(option, "onClickApp") == 0) 164 fApp = strdup(argument); 165 else if (strcmp(option, "onClickFile") == 0) { 166 if (get_ref_for_path(argument, &fFile) != B_OK) { 167 fprintf(stderr, "Bad path for --onClickFile!\n\n"); 168 return; 169 } 170 171 fHasFile = true; 172 } else if (strcmp(option, "onClickRef") == 0) { 173 entry_ref ref; 174 175 if (get_ref_for_path(argument, &ref) != B_OK) { 176 fprintf(stderr, "Bad path for --onClickRef!\n\n"); 177 return; 178 } 179 180 fRefs->AddItem((void*)new BEntry(&ref)); 181 } else if (strcmp(option, "onClickArgv") == 0) 182 fArgv->AddItem((void*)strdup(argument)); 183 else { 184 // Unrecognized option 185 fprintf(stderr, "Unrecognized option --%s\n\n", option); 186 return; 187 } 188 } else 189 // Option doesn't start with '--' 190 break; 191 192 if (index == kArgCount) { 193 // No text argument provided, only '--' arguments 194 fprintf(stderr, "Missing message argument!\n\n"); 195 return; 196 } 197 } 198 199 // Check for missing arguments 200 if (!fAppName) { 201 fprintf(stderr, "Missing --app argument!\n\n"); 202 return; 203 } 204 if (!fTitle) { 205 fprintf(stderr, "Missing --title argument!\n\n"); 206 return; 207 } 208 209 fMessage = strdup(argv[index]); 210 fOk = true; 211 } 212 213 void 214 NotifyApp::_Usage() const 215 { 216 fprintf(stderr, "Usage: notify [OPTION]... [MESSAGE]\n" 217 "Send notifications to notification_server.\n" 218 " --type <type>\tNotification type,\n" 219 " \t <type>: "); 220 221 for (int32 i = 0; kTypeNames[i]; i++) 222 fprintf(stderr, kTypeNames[i + 1] ? "%s|" : "%s\n", kTypeNames[i]); 223 224 fprintf(stderr, 225 " --app <app name>\tApplication name\n" 226 " --title <title>\tMessage title\n" 227 " --messageID <msg id>\tMessage ID\n" 228 " --progress <float>\tProgress, value between 0.0 and 1.0 - if type is set to progress\n" 229 " --timeout <secs>\tSpecify timeout\n" 230 " --onClickApp <signature>\tApplication to open when notification is clicked\n" 231 " --onClickFile <fullpath>\tFile to open when notification is clicked\n" 232 " --onClickRef <fullpath>\tFile to open with the application when notification is clicked\n" 233 " --onClickArgv <arg>\tArgument to the application when notification is clicked\n" 234 " --icon <icon file> Icon\n"); 235 } 236 237 238 BBitmap* 239 NotifyApp::_GetBitmap(const entry_ref* ref) const 240 { 241 BBitmap* bitmap = NULL; 242 243 // First try by contents 244 bitmap = BTranslationUtils::GetBitmap(ref); 245 if (bitmap) 246 return bitmap; 247 248 // Then, try reading its attribute 249 BNode node(BPath(ref).Path()); 250 bitmap = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1, 251 (float)B_LARGE_ICON - 1), B_RGBA32); 252 if (BIconUtils::GetIcon(&node, kIconAttribute, kSmallIconAttribute, 253 kLargeIconAttribute, B_LARGE_ICON, bitmap) != B_OK) { 254 delete bitmap; 255 bitmap = NULL; 256 } 257 258 return bitmap; 259 } 260 261 262 void 263 NotifyApp::ReadyToRun() 264 { 265 if (GoodArguments()) { 266 BNotification* msg = new BNotification(fType); 267 msg->SetApplication(fAppName); 268 msg->SetTitle(fTitle); 269 msg->SetContent(fMessage); 270 271 if (fMsgId) 272 msg->SetMessageID(fMsgId); 273 274 if (fType == B_PROGRESS_NOTIFICATION) 275 msg->SetProgress(fProgress); 276 277 if (fIconFile) { 278 BBitmap* bitmap = _GetBitmap(&fFileRef); 279 if (bitmap) 280 msg->SetIcon(bitmap); 281 } 282 283 if (fApp) 284 msg->SetOnClickApp(fApp); 285 286 if (fHasFile) 287 msg->SetOnClickFile(&fFile); 288 289 int32 i; 290 void* item; 291 292 for (i = 0; item = fRefs->ItemAt(i); i++) { 293 BEntry* entry = (BEntry*)item; 294 295 entry_ref ref; 296 if (entry->GetRef(&ref) == B_OK) 297 msg->AddOnClickRef(&ref); 298 } 299 300 for (i = 0; item = fArgv->ItemAt(i); i++) { 301 const char* arg = (const char*)item; 302 msg->AddOnClickArg(arg); 303 } 304 305 be_roster->Notify(msg, fTimeout); 306 } else 307 _Usage(); 308 309 Quit(); 310 } 311 312 313 int 314 main(int argc, char** argv) 315 { 316 NotifyApp app; 317 if (app.InitCheck() != B_OK) 318 return kErrorInitFail; 319 320 app.Run(); 321 if (!app.GoodArguments()) 322 return kErrorArgumentsFail; 323 324 return 0; 325 } -
src/kits/Jamfile
diff --git a/src/kits/Jamfile b/src/kits/Jamfile index 5adc2d5..7a09a4c 100644
a b SubInclude HAIKU_TOP src kits media ; 81 81 SubInclude HAIKU_TOP src kits midi ; 82 82 SubInclude HAIKU_TOP src kits midi2 ; 83 83 SubInclude HAIKU_TOP src kits network ; 84 SubInclude HAIKU_TOP src kits notification ; 84 85 SubInclude HAIKU_TOP src kits opengl ; 85 86 SubInclude HAIKU_TOP src kits print ; 86 87 SubInclude HAIKU_TOP src kits screensaver ; -
src/kits/app/Jamfile
diff --git a/src/kits/app/Jamfile b/src/kits/app/Jamfile index 686116d..cf85c79 100644
a b if $(RUN_WITHOUT_APP_SERVER) != 0 { 17 17 SubDirC++Flags $(defines) ; 18 18 } 19 19 20 UsePrivateHeaders shared app interface kernel ;20 UsePrivateHeaders shared app interface kernel notification ; 21 21 UsePrivateSystemHeaders ; 22 22 23 23 SetSubDirSupportedPlatforms haiku libbe_test ; … … MergeObject <libbe>app_kit.o : 45 45 MessageRunner.cpp 46 46 Messenger.cpp 47 47 MessageUtils.cpp 48 Notification.cpp 48 49 PropertyInfo.cpp 49 50 PortLink.cpp 50 51 RegistrarDefs.cpp -
new file src/kits/app/Notification.cpp
diff --git a/src/kits/app/Notification.cpp b/src/kits/app/Notification.cpp new file mode 100644 index 0000000..e39c927
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 7 */ 8 9 #include <stdlib.h> 10 #include <string.h> 11 12 #include <Bitmap.h> 13 #include <List.h> 14 #include <Message.h> 15 #include <Notification.h> 16 17 18 BNotification::BNotification(notification_type type) 19 : 20 fType(type), 21 fAppName(NULL), 22 fTitle(NULL), 23 fContent(NULL), 24 fID(NULL), 25 fApp(NULL), 26 fFile(NULL), 27 fBitmap(NULL) 28 { 29 fRefs = new BList(); 30 fArgv = new BList(); 31 } 32 33 34 BNotification::~BNotification() 35 { 36 if (fAppName) 37 free(fAppName); 38 if (fTitle) 39 free(fTitle); 40 if (fContent) 41 free(fContent); 42 if (fID) 43 free(fID); 44 if (fApp) 45 free(fApp); 46 47 delete fRefs; 48 delete fArgv; 49 } 50 51 52 notification_type 53 BNotification::Type() const 54 { 55 return fType; 56 } 57 58 59 const char* 60 BNotification::Application() const 61 { 62 return fAppName; 63 } 64 65 66 void 67 BNotification::SetApplication(const char* app) 68 { 69 free(fAppName); 70 fAppName = NULL; 71 72 if (app) 73 fAppName = strdup(app); 74 } 75 76 77 const char* 78 BNotification::Title() const 79 { 80 return fTitle; 81 } 82 83 84 void 85 BNotification::SetTitle(const char* title) 86 { 87 free(fTitle); 88 fTitle = NULL; 89 90 if (title) 91 fTitle = strdup(title); 92 } 93 94 95 const char* 96 BNotification::Content() const 97 { 98 return fContent; 99 } 100 101 102 void 103 BNotification::SetContent(const char* content) 104 { 105 free(fContent); 106 fContent = NULL; 107 108 if (content) 109 fContent = strdup(content); 110 } 111 112 113 const char* 114 BNotification::MessageID() const 115 { 116 return fID; 117 } 118 119 120 void 121 BNotification::SetMessageID(const char* id) 122 { 123 free(fID); 124 fID = NULL; 125 126 if (id) 127 fID = strdup(id); 128 } 129 130 131 float 132 BNotification::Progress() const 133 { 134 return fProgress; 135 } 136 137 138 void 139 BNotification::SetProgress(float progress) 140 { 141 fProgress = progress; 142 } 143 144 145 const char* 146 BNotification::OnClickApp() const 147 { 148 return fApp; 149 } 150 151 152 void 153 BNotification::SetOnClickApp(const char* app) 154 { 155 free(fApp); 156 fApp = NULL; 157 158 if (app) 159 fApp = strdup(app); 160 } 161 162 163 entry_ref* 164 BNotification::OnClickFile() const 165 { 166 return fFile; 167 } 168 169 170 void 171 BNotification::SetOnClickFile(const entry_ref* file) 172 { 173 fFile = (entry_ref*)file; 174 } 175 176 177 BList* 178 BNotification::OnClickRefs() const 179 { 180 return fRefs; 181 } 182 183 184 void 185 BNotification::AddOnClickRef(const entry_ref* ref) 186 { 187 fRefs->AddItem((void*)ref); 188 } 189 190 191 BList* 192 BNotification::OnClickArgv() const 193 { 194 return fArgv; 195 } 196 197 198 void 199 BNotification::AddOnClickArg(const char* arg) 200 { 201 fArgv->AddItem((void*)arg); 202 } 203 204 205 BBitmap* 206 BNotification::Icon() const 207 { 208 return fBitmap; 209 } 210 211 212 void 213 BNotification::SetIcon(BBitmap* icon) 214 { 215 fBitmap = icon; 216 } -
src/kits/app/Roster.cpp
diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index d5071ad..2f14cda 100644
a b 25 25 26 26 #include <AppFileInfo.h> 27 27 #include <Application.h> 28 #include <Bitmap.h> 28 29 #include <Directory.h> 29 30 #include <File.h> 30 31 #include <FindDirectory.h> … … 35 36 #include <Mime.h> 36 37 #include <Node.h> 37 38 #include <NodeInfo.h> 39 #include <Notification.h> 40 #include <notification/Notifications.h> 38 41 #include <OS.h> 39 42 #include <Path.h> 40 43 #include <Query.h> … … BRoster::AddToRecentFolders(const entry_ref* folder, const char* appSig) const 1650 1653 DBG(OUT("WARNING: BRoster::AddToRecentDocuments() failed with error 0x%lx\n", err)); 1651 1654 } 1652 1655 1656 /*! \brief Sends a notification to the notification_server. 1657 1658 The notification is delivered synchronously to the notification_server, 1659 that 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 \return 1664 - \c B_OK: Everything went fine. 1665 - \c B_BAD_PORT_ID: A connection to notification_server could not be 1666 established or the server is not up and running anymore. 1667 */ 1668 status_t 1669 BRoster::Notify(BNotification* notification, int32 timeout) const 1670 { 1671 BMessage msg(kNotificationMessage); 1672 msg.AddInt32("type", (int32)notification->Type()); 1673 msg.AddString("app", notification->Application()); 1674 msg.AddString("title", notification->Title()); 1675 msg.AddString("content", notification->Content()); 1676 1677 if (notification->MessageID()) 1678 msg.AddString("messageID", notification->MessageID()); 1679 1680 if (notification->Type() == B_PROGRESS_NOTIFICATION) 1681 msg.AddFloat("progress", notification->Progress()); 1682 1683 if (notification->OnClickApp()) 1684 msg.AddString("onClickApp", notification->OnClickApp()); 1685 if (notification->OnClickFile()) 1686 msg.AddRef("onClickFile", notification->OnClickFile()); 1687 1688 int32 i; 1689 1690 BList* refs = notification->OnClickRefs(); 1691 for (i = 0; i < refs->CountItems(); i++) 1692 msg.AddRef("onClickRef", (entry_ref*)refs->ItemAt(i)); 1693 1694 BList* argv = notification->OnClickArgv(); 1695 for (i = 0; i < argv->CountItems(); i++) 1696 msg.AddString("onClickArgv", (const char*)argv->ItemAt(i)); 1697 1698 BBitmap* icon = notification->Icon(); 1699 1700 BMessage archive; 1701 if (icon && icon->Archive(&archive) == B_OK) 1702 msg.AddMessage("icon", &archive); 1703 1704 // Custom time out 1705 if (timeout > 0) 1706 msg.AddInt32("timeout", timeout); 1707 1708 // Send message 1709 BMessenger server(kNotificationServerSignature); 1710 return server.SendMessage(&msg); 1711 } 1712 1653 1713 1654 1714 // #pragma mark - Private or reserved 1655 1715 -
new file src/kits/notification/AppUsage.cpp
diff --git a/src/kits/notification/AppUsage.cpp b/src/kits/notification/AppUsage.cpp new file mode 100644 index 0000000..7310796
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Michael Davidson, slaad@bong.com.au 10 * Mikael Eiman, mikael@eiman.tv 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 */ 13 14 #include <Message.h> 15 16 #include <AppUsage.h> 17 #include <NotificationReceived.h> 18 19 const type_code kTypeCode = 'ipau'; 20 21 22 AppUsage::AppUsage() 23 : 24 fName(""), 25 fAllow(true) 26 { 27 } 28 29 30 AppUsage::AppUsage(entry_ref ref, const char* name, bool allow) 31 : 32 fRef(ref), 33 fName(name), 34 fAllow(allow) 35 { 36 } 37 38 39 AppUsage::~AppUsage() 40 { 41 notify_t::iterator nIt; 42 for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) 43 delete nIt->second; 44 } 45 46 47 bool 48 AppUsage::AllowsTypeCode(type_code code) const 49 { 50 return code == kTypeCode; 51 } 52 53 54 status_t 55 AppUsage::Flatten(void* buffer, ssize_t numBytes) const 56 { 57 BMessage msg; 58 msg.AddString("app_name", fName); 59 msg.AddRef("app_ref", &fRef); 60 msg.AddBool("app_allow", fAllow); 61 62 notify_t::const_iterator nIt; 63 for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) 64 msg.AddFlat("notify", nIt->second); 65 66 if (numBytes < msg.FlattenedSize()) 67 return B_ERROR; 68 69 return msg.Flatten((char*)buffer, numBytes); 70 } 71 72 73 ssize_t 74 AppUsage::FlattenedSize() const 75 { 76 BMessage msg; 77 msg.AddString("app_name", fName); 78 msg.AddRef("app_ref", &fRef); 79 msg.AddBool("app_allow", fAllow); 80 81 notify_t::const_iterator nIt; 82 for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++) 83 msg.AddFlat("notify", nIt->second); 84 85 return msg.FlattenedSize(); 86 } 87 88 89 bool 90 AppUsage::IsFixedSize() const 91 { 92 return false; 93 } 94 95 96 type_code 97 AppUsage::TypeCode() const 98 { 99 return kTypeCode; 100 } 101 102 103 status_t 104 AppUsage::Unflatten(type_code code, const void* buffer, 105 ssize_t numBytes) 106 { 107 if (code != kTypeCode) 108 return B_ERROR; 109 110 BMessage msg; 111 status_t status = B_ERROR; 112 113 status = msg.Unflatten((const char*)buffer); 114 115 if (status == B_OK) { 116 msg.FindString("app_name", &fName); 117 msg.FindRef("app_ref", &fRef); 118 msg.FindBool("app_allow", &fAllow); 119 120 type_code type; 121 int32 count = 0; 122 123 status = msg.GetInfo("notify", &type, &count); 124 if (status != B_OK) 125 return status; 126 127 for (int32 i = 0; i < count; i++) { 128 NotificationReceived *notify = new NotificationReceived(); 129 msg.FindFlat("notify", i, notify); 130 fNotifications[notify->Title()] = notify; 131 } 132 133 status = B_OK; 134 } 135 136 return status; 137 } 138 139 140 entry_ref 141 AppUsage::Ref() 142 { 143 return fRef; 144 } 145 146 147 const char* 148 AppUsage::Name() 149 { 150 return fName.String(); 151 } 152 153 154 bool 155 AppUsage::Allowed(const char* title, notification_type type) 156 { 157 bool allowed = fAllow; 158 159 if (allowed) { 160 notify_t::iterator nIt = fNotifications.find(title); 161 if (nIt == fNotifications.end()) { 162 allowed = true; 163 fNotifications[title] = new NotificationReceived(title, type); 164 } else { 165 allowed = nIt->second->Allowed(); 166 nIt->second->UpdateTimeStamp(); 167 nIt->second->SetType(type); 168 } 169 } 170 171 return allowed; 172 } 173 174 175 bool 176 AppUsage::Allowed() 177 { 178 return fAllow; 179 } 180 181 182 NotificationReceived* 183 AppUsage::NotificationAt(int32 index) 184 { 185 notify_t::iterator nIt = fNotifications.begin(); 186 for (int32 i = 0; i < index; i++) 187 nIt++; 188 189 return nIt->second; 190 } 191 192 193 int32 194 AppUsage::Notifications() 195 { 196 return fNotifications.size(); 197 } 198 199 200 void 201 AppUsage::AddNotification(NotificationReceived* notification) 202 { 203 fNotifications[notification->Title()] = notification; 204 } -
new file src/kits/notification/Jamfile
diff --git a/src/kits/notification/Jamfile b/src/kits/notification/Jamfile new file mode 100644 index 0000000..6027124
- + 1 SubDir HAIKU_TOP src kits notification ; 2 3 UsePrivateHeaders notification ; 4 5 StaticLibrary libnotification.a : 6 AppUsage.cpp 7 NotificationReceived.cpp 8 Notifications.cpp 9 ; -
new file src/kits/notification/NotificationReceived.cpp
diff --git a/src/kits/notification/NotificationReceived.cpp b/src/kits/notification/NotificationReceived.cpp new file mode 100644 index 0000000..f5d9b01
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Michael Davidson, slaad@bong.com.au 10 * Mikael Eiman, mikael@eiman.tv 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 */ 13 14 #include <Message.h> 15 #include <Notification.h> 16 #include <NotificationReceived.h> 17 18 const type_code kTypeCode = 'ipnt'; 19 20 21 NotificationReceived::NotificationReceived() 22 : 23 fTitle(""), 24 fType(B_INFORMATION_NOTIFICATION), 25 fEnabled(false), 26 fLastReceived(time(NULL)) 27 { 28 } 29 30 31 NotificationReceived::NotificationReceived(const char* title, 32 notification_type type, bool enabled) 33 : 34 fTitle(title), 35 fType(type), 36 fEnabled(enabled), 37 fLastReceived(time(NULL)) 38 { 39 } 40 41 42 NotificationReceived::~NotificationReceived() 43 { 44 } 45 46 47 bool 48 NotificationReceived::AllowsTypeCode(type_code code) const 49 { 50 return code == kTypeCode; 51 } 52 53 54 status_t 55 NotificationReceived::Flatten(void* buffer, ssize_t numBytes) const 56 { 57 BMessage msg; 58 msg.AddString("notify_title", fTitle); 59 msg.AddInt32("notify_type", (int32)fType); 60 msg.AddInt32("notify_lastreceived", (int32)fLastReceived); 61 msg.AddBool("notify_enabled", fEnabled); 62 63 if (numBytes < msg.FlattenedSize()) 64 return B_ERROR; 65 66 return msg.Flatten((char*)buffer, numBytes); 67 } 68 69 70 ssize_t 71 NotificationReceived::FlattenedSize() const 72 { 73 BMessage msg; 74 msg.AddString("notify_title", fTitle); 75 msg.AddInt32("notify_type", (int32)fType); 76 msg.AddInt32("notify_lastreceived", (int32)fLastReceived); 77 msg.AddBool("notify_enabled", fEnabled); 78 79 return msg.FlattenedSize(); 80 } 81 82 83 bool 84 NotificationReceived::IsFixedSize() const 85 { 86 return false; 87 } 88 89 90 type_code 91 NotificationReceived::TypeCode() const 92 { 93 return kTypeCode; 94 } 95 96 97 status_t 98 NotificationReceived::Unflatten(type_code code, const void* buffer, 99 ssize_t numBytes) 100 { 101 if (code != kTypeCode) 102 return B_ERROR; 103 104 BMessage msg; 105 status_t error = msg.Unflatten((const char*)buffer); 106 107 if (error == B_OK) { 108 msg.FindString("notify_title", &fTitle); 109 msg.FindInt32("notify_type", (int32 *)&fType); 110 msg.FindInt32("notify_lastreceived", (int32 *)&fLastReceived); 111 msg.FindBool("notify_enabled", &fEnabled); 112 } 113 114 return error; 115 } 116 117 118 const char* 119 NotificationReceived::Title() 120 { 121 return fTitle.String(); 122 } 123 124 125 notification_type 126 NotificationReceived::Type() 127 { 128 return fType; 129 } 130 131 132 void 133 NotificationReceived::SetType(notification_type type) 134 { 135 fType = type; 136 } 137 138 139 time_t 140 NotificationReceived::LastReceived() 141 { 142 return fLastReceived; 143 } 144 145 146 bool 147 NotificationReceived::Allowed() 148 { 149 return fEnabled; 150 } 151 152 153 void 154 NotificationReceived::UpdateTimeStamp() 155 { 156 fLastReceived = time(NULL); 157 } 158 159 160 void 161 NotificationReceived::SetTimeStamp(time_t time) 162 { 163 fLastReceived = time; 164 } -
src/preferences/Jamfile
diff --git a/src/preferences/Jamfile b/src/preferences/Jamfile index 34253ff..2a42084 100644
a b SubInclude HAIKU_TOP src preferences mail ; 17 17 SubInclude HAIKU_TOP src preferences media ; 18 18 SubInclude HAIKU_TOP src preferences mouse ; 19 19 SubInclude HAIKU_TOP src preferences network ; 20 SubInclude HAIKU_TOP src preferences notifications ; 20 21 SubInclude HAIKU_TOP src preferences opengl ; 21 22 SubInclude HAIKU_TOP src preferences print ; 22 23 SubInclude HAIKU_TOP src preferences screen ; -
new file src/preferences/notifications/DisplayView.cpp
diff --git a/src/preferences/notifications/DisplayView.cpp b/src/preferences/notifications/DisplayView.cpp new file mode 100644 index 0000000..fca5fca
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 13 #include <Alert.h> 14 #include <Directory.h> 15 #include <Message.h> 16 #include <FindDirectory.h> 17 #include <GroupLayout.h> 18 #include <GridLayoutBuilder.h> 19 #include <SpaceLayoutItem.h> 20 #include <TextControl.h> 21 #include <Menu.h> 22 #include <MenuItem.h> 23 #include <MenuField.h> 24 #include <Mime.h> 25 #include <Node.h> 26 #include <notification/Notifications.h> 27 #include <Path.h> 28 29 #include "DisplayView.h" 30 #include "SettingsHost.h" 31 32 #define _T(str) (str) 33 34 35 DisplayView::DisplayView(SettingsHost* host) 36 : 37 SettingsPane("display", host) 38 { 39 // Window width 40 fWindowWidth = new BTextControl(_T("Window width:"), NULL, 41 new BMessage(kSettingChanged)); 42 43 // Icon size 44 fIconSize = new BMenu("iconSize"); 45 fIconSize->AddItem(new BMenuItem(_T("Mini icon"), 46 new BMessage(kSettingChanged))); 47 fIconSize->AddItem(new BMenuItem(_T("Large icon"), 48 new BMessage(kSettingChanged))); 49 fIconSize->SetLabelFromMarked(true); 50 fIconSizeField = new BMenuField(_T("Icon size:"), fIconSize); 51 52 // Title position 53 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 // Load settings 62 Load(); 63 64 // Calculate inset 65 float inset = ceilf(be_plain_font->Size() * 0.7f); 66 67 SetLayout(new BGroupLayout(B_VERTICAL)); 68 AddChild(BGridLayoutBuilder(inset, inset) 69 .Add(fWindowWidth->CreateLabelLayoutItem(), 0, 0) 70 .Add(fWindowWidth->CreateTextViewLayoutItem(), 1, 0) 71 .Add(fIconSizeField->CreateLabelLayoutItem(), 0, 1) 72 .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) 76 ); 77 } 78 79 80 void 81 DisplayView::AttachedToWindow() 82 { 83 fWindowWidth->SetTarget(this); 84 fIconSize->SetTargetForItems(this); 85 fTitlePosition->SetTargetForItems(this); 86 } 87 88 89 void 90 DisplayView::MessageReceived(BMessage* msg) 91 { 92 switch (msg->what) { 93 case kSettingChanged: 94 SettingsPane::MessageReceived(msg); 95 break; 96 default: 97 BView::MessageReceived(msg); 98 } 99 } 100 101 102 status_t 103 DisplayView::Load() 104 { 105 BPath path; 106 107 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 108 return B_ERROR; 109 110 path.Append(kSettingsDirectory); 111 112 if (create_directory(path.Path(), 0755) != B_OK) { 113 BAlert* alert = new BAlert("", 114 _T("There was a problem saving the preferences.\n" 115 "It's possible you don't have write access to the " 116 "settings directory."), "OK", NULL, NULL, 117 B_WIDTH_AS_USUAL, B_STOP_ALERT); 118 (void)alert->Go(); 119 } 120 121 path.Append(kDisplaySettings); 122 123 BFile file(path.Path(), B_READ_ONLY); 124 BMessage settings; 125 settings.Unflatten(&file); 126 127 char buffer[255]; 128 int32 setting; 129 BMenuItem* item = NULL; 130 131 float width; 132 if (settings.FindFloat(kWidthName, &width) != B_OK) 133 width = kDefaultWidth; 134 (void)sprintf(buffer, "%.2f", width); 135 fWindowWidth->SetText(buffer); 136 137 icon_size iconSize; 138 if (settings.FindInt32(kIconSizeName, &setting) != B_OK) 139 iconSize = kDefaultIconSize; 140 else 141 iconSize = (icon_size)setting; 142 if (iconSize == B_MINI_ICON) 143 item = fIconSize->ItemAt(0); 144 else 145 item = fIconSize->ItemAt(1); 146 if (item) 147 item->SetMarked(true); 148 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 return B_OK; 169 } 170 171 172 status_t 173 DisplayView::Save() 174 { 175 BPath path; 176 177 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 178 return B_ERROR; 179 180 path.Append(kSettingsDirectory); 181 path.Append(kDisplaySettings); 182 183 BMessage settings; 184 185 float width = atof(fWindowWidth->Text()); 186 settings.AddFloat(kWidthName, width); 187 188 icon_size iconSize = kDefaultIconSize; 189 switch (fIconSize->IndexOf(fIconSize->FindMarked())) { 190 case 0: 191 iconSize = B_MINI_ICON; 192 break; 193 default: 194 iconSize = B_LARGE_ICON; 195 } 196 settings.AddInt32(kIconSizeName, (int32)iconSize); 197 198 int32 layout = fTitlePosition->IndexOf(fTitlePosition->FindMarked()); 199 if (layout == B_ERROR) 200 layout = (int32)kDefaultLayout; 201 settings.AddInt32(kLayoutName, layout); 202 203 // Save settings file 204 BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 205 status_t ret = settings.Flatten(&file); 206 if (ret != B_OK) { 207 BAlert* alert = new BAlert("", 208 _T("Can't save preferenes, you probably don't have write " 209 "access to the settings directory or the disk is full."), "OK", NULL, NULL, 210 B_WIDTH_AS_USUAL, B_STOP_ALERT); 211 (void)alert->Go(); 212 return ret; 213 } 214 215 return B_OK; 216 } 217 218 219 status_t 220 DisplayView::Revert() 221 { 222 return B_ERROR; 223 } -
new file src/preferences/notifications/DisplayView.h
diff --git a/src/preferences/notifications/DisplayView.h b/src/preferences/notifications/DisplayView.h new file mode 100644 index 0000000..ddf528c
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _DISPLAY_VIEW_H 7 #define _DISPLAY_VIEW_H 8 9 #include "SettingsPane.h" 10 11 class BTextControl; 12 class BMenu; 13 class BMenuField; 14 15 class DisplayView : public SettingsPane { 16 public: 17 DisplayView(SettingsHost* host); 18 19 virtual void AttachedToWindow(); 20 virtual void MessageReceived(BMessage* msg); 21 22 // SettingsPane hooks 23 status_t Load(); 24 status_t Save(); 25 status_t Revert(); 26 27 private: 28 BTextControl* fWindowWidth; 29 BMenu* fIconSize; 30 BMenuField* fIconSizeField; 31 BMenu* fTitlePosition; 32 BMenuField* fTitlePositionField; 33 34 }; 35 36 #endif // _DISPLAY_VIEW_H -
new file src/preferences/notifications/GeneralView.cpp
diff --git a/src/preferences/notifications/GeneralView.cpp b/src/preferences/notifications/GeneralView.cpp new file mode 100644 index 0000000..e8de047
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <stdio.h> 11 #include <stdlib.h> 12 13 #include <vector> 14 15 #include <Roster.h> 16 #include <GroupLayout.h> 17 #include <GroupLayoutBuilder.h> 18 #include <Alert.h> 19 #include <Font.h> 20 #include <Button.h> 21 #include <StringView.h> 22 #include <TextControl.h> 23 #include <CheckBox.h> 24 #include <String.h> 25 #include <FindDirectory.h> 26 #include <Node.h> 27 #include <notification/Notifications.h> 28 #include <Path.h> 29 #include <File.h> 30 #include <Directory.h> 31 #include <VolumeRoster.h> 32 #include <Volume.h> 33 #include <Query.h> 34 #include <SymLink.h> 35 36 #include "GeneralView.h" 37 #include "SettingsHost.h" 38 39 #define _T(str) (str) 40 41 const int32 kServer = '_TSR'; 42 43 const char* kStartServer = _T("Enable notifications"); 44 const char* kStopServer = _T("Disable notifications"); 45 const char* kStarted = _T("Events are notified"); 46 const char* kStopped = _T("Events are not notified"); 47 48 49 GeneralView::GeneralView(SettingsHost* host) 50 : 51 SettingsPane("general", host) 52 { 53 BFont statusFont; 54 55 // Set a smaller font for the status label 56 statusFont.SetSize(be_plain_font->Size() * 0.8); 57 58 // Status button and label 59 fServerButton = new BButton("server", kStartServer, new BMessage(kServer)); 60 fStatusLabel = new BStringView("status", kStopped); 61 fStatusLabel->SetFont(&statusFont); 62 63 // Update status label and server button 64 if (_IsServerRunning()) { 65 fServerButton->SetLabel(kStopServer); 66 fStatusLabel->SetText(kStarted); 67 } else { 68 fServerButton->SetLabel(kStartServer); 69 fStatusLabel->SetText(kStopped); 70 } 71 72 // Autostart 73 fAutoStart = new BCheckBox("autostart", 74 _T("Enable notifications at startup"), new BMessage(kSettingChanged)); 75 76 // Display time 77 fTimeout = new BTextControl(_T("Hide notifications from screen after"), NULL, 78 new BMessage(kSettingChanged)); 79 BStringView* displayTimeLabel = new BStringView("dt_label", 80 _T("seconds of inactivity")); 81 82 // Default position 83 // TODO: Here will come a screen representation with the four corners clickable 84 85 // Load settings 86 Load(); 87 88 // Calculate inset 89 float inset = ceilf(be_plain_font->Size() * 0.7f); 90 91 SetLayout(new BGroupLayout(B_VERTICAL)); 92 AddChild(BGroupLayoutBuilder(B_VERTICAL, inset) 93 .AddGroup(B_HORIZONTAL, inset) 94 .Add(fServerButton) 95 .Add(fStatusLabel) 96 .AddGlue() 97 .End() 98 99 .AddGroup(B_VERTICAL, inset) 100 .Add(fAutoStart) 101 .AddGroup(B_HORIZONTAL) 102 .AddGroup(B_HORIZONTAL, 2) 103 .Add(fTimeout) 104 .Add(displayTimeLabel) 105 .End() 106 .End() 107 .End() 108 109 .AddGlue() 110 ); 111 } 112 113 114 void 115 GeneralView::AttachedToWindow() 116 { 117 fServerButton->SetTarget(this); 118 fAutoStart->SetTarget(this); 119 fTimeout->SetTarget(this); 120 } 121 122 123 void 124 GeneralView::MessageReceived(BMessage* msg) 125 { 126 switch (msg->what) { 127 case kServer: { 128 entry_ref ref; 129 130 // Check if server is available 131 if (!_CanFindServer(&ref)) { 132 BAlert* alert = new BAlert(_T("Notifications"), 133 _T("The notifications server cannot be found, " 134 "this means your InfoPopper installation was not " 135 "successfully completed."), _T("OK"), NULL, 136 NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 137 (void)alert->Go(); 138 return; 139 } 140 141 if (_IsServerRunning()) { 142 // Server team 143 team_id team = be_roster->TeamFor(kNotificationServerSignature); 144 145 // Establish a connection to infopopper_server 146 status_t ret = B_ERROR; 147 BMessenger messenger(kNotificationServerSignature, team, &ret); 148 if (ret != B_OK) { 149 BAlert* alert = new BAlert(_T("Notifications"), 150 _T("Notifications cannot be stopped, because " 151 "the server can't be reached."), 152 _T("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 153 (void)alert->Go(); 154 return; 155 } 156 157 // Send quit message 158 if (messenger.SendMessage(new BMessage(B_QUIT_REQUESTED)) != B_OK) { 159 BAlert* alert = new BAlert(_T("Notifications"), 160 _T("Cannot disable notifications because the server " 161 "can't be reached."), _T("OK"), NULL, 162 NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 163 (void)alert->Go(); 164 return; 165 } 166 167 fServerButton->SetLabel(kStartServer); 168 fStatusLabel->SetText(kStopped); 169 } else { 170 // Start server 171 status_t err = be_roster->Launch(kNotificationServerSignature); 172 if (err != B_OK) { 173 BAlert* alert = new BAlert(_T("Notifications"), 174 _T("Cannot enable notifications because the server " 175 "cannot be found.\nThis means your InfoPopper " 176 "installation was not successfully completed."), 177 _T("OK"), NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 178 (void)alert->Go(); 179 return; 180 } 181 182 fServerButton->SetLabel(kStopServer); 183 fStatusLabel->SetText(kStarted); 184 } 185 } break; 186 case kSettingChanged: 187 SettingsPane::MessageReceived(msg); 188 break; 189 default: 190 BView::MessageReceived(msg); 191 break; 192 } 193 } 194 195 196 status_t 197 GeneralView::Load() 198 { 199 BPath path; 200 201 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 202 return B_ERROR; 203 204 path.Append(kSettingsDirectory); 205 206 if (create_directory(path.Path(), 0755) != B_OK) { 207 BAlert* alert = new BAlert("", 208 _T("There was a problem saving the preferences.\n" 209 "It's possible you don't have write access to the " 210 "settings directory."), "OK", NULL, NULL, 211 B_WIDTH_AS_USUAL, B_STOP_ALERT); 212 (void)alert->Go(); 213 } 214 215 path.Append(kGeneralSettings); 216 217 BMessage settings; 218 BFile file(path.Path(), B_READ_ONLY); 219 settings.Unflatten(&file); 220 221 char buffer[255]; 222 223 bool autoStart; 224 if (settings.FindBool(kAutoStartName, &autoStart) != B_OK) 225 autoStart = kDefaultAutoStart; 226 fAutoStart->SetValue(autoStart ? B_CONTROL_ON : B_CONTROL_OFF); 227 228 int32 timeout; 229 if (settings.FindInt32(kTimeoutName, &timeout) != B_OK) 230 timeout = kDefaultTimeout; 231 (void)sprintf(buffer, "%ld", timeout); 232 fTimeout->SetText(buffer); 233 234 return B_OK; 235 } 236 237 238 status_t 239 GeneralView::Save() 240 { 241 BPath path; 242 243 status_t ret = B_OK; 244 ret = find_directory(B_USER_SETTINGS_DIRECTORY, &path); 245 if (ret != B_OK) 246 return ret; 247 248 path.Append(kSettingsDirectory); 249 path.Append(kGeneralSettings); 250 251 BMessage settings; 252 253 bool autoStart = (fAutoStart->Value() == B_CONTROL_ON); 254 settings.AddBool(kAutoStartName, autoStart); 255 256 int32 timeout = atol(fTimeout->Text()); 257 settings.AddInt32(kTimeoutName, timeout); 258 259 // Save settings file 260 BFile file(path.Path(), B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE); 261 ret = settings.Flatten(&file); 262 if (ret != B_OK) { 263 BAlert* alert = new BAlert("", 264 _T("An error is occurred saving the preferences.\n" 265 "It's possible you are running out of disk space."), 266 "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 267 (void)alert->Go(); 268 return ret; 269 } 270 271 // Find server path 272 entry_ref ref; 273 if (!_CanFindServer(&ref)) { 274 BAlert* alert = new BAlert("", 275 _T("The notifications server cannot be found.\n" 276 "A possible cause is an installation not done correctly"), 277 "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT); 278 (void)alert->Go(); 279 return B_ERROR; 280 } 281 282 // UserBootscript command 283 BPath serverPath(&ref); 284 285 // Start server at boot time 286 ret = find_directory(B_USER_BOOT_DIRECTORY, &path, true); 287 if (ret != B_OK) { 288 BAlert* alert = new BAlert("", 289 _T("Can't save preferences, you probably don't have write " 290 "access to the boot settings directory."), "OK", NULL, NULL, 291 B_WIDTH_AS_USUAL, B_STOP_ALERT); 292 (void)alert->Go(); 293 return ret; 294 } 295 296 path.Append("launch"); 297 BDirectory directory(path.Path()); 298 BEntry entry(&directory, serverPath.Leaf()); 299 300 // Remove symbolic link 301 entry.Remove(); 302 303 if (autoStart) { 304 // Put a symlink into ~/config/boot/launch 305 if ((ret = directory.CreateSymLink(serverPath.Leaf(), 306 serverPath.Path(), NULL) != B_OK)) { 307 BAlert* alert = new BAlert("", 308 _T("Can't enable notifications at startup time, you probably don't have " 309 "write permission to the boot settings directory."), "OK", NULL, NULL, 310 B_WIDTH_AS_USUAL, B_STOP_ALERT); 311 (void)alert->Go(); 312 return ret; 313 } 314 } 315 316 return B_OK; 317 } 318 319 320 status_t 321 GeneralView::Revert() 322 { 323 return B_ERROR; 324 } 325 326 327 bool 328 GeneralView::_CanFindServer(entry_ref* ref) 329 { 330 // Try searching with be_roster 331 if (be_roster->FindApp(kNotificationServerSignature, ref) == B_OK) 332 return true; 333 334 // Try with a query and take the first result 335 BVolumeRoster vroster; 336 BVolume volume; 337 char volName[B_FILE_NAME_LENGTH]; 338 339 vroster.Rewind(); 340 341 while (vroster.GetNextVolume(&volume) == B_OK) { 342 if ((volume.InitCheck() != B_OK) || !volume.KnowsQuery()) 343 continue; 344 345 volume.GetName(volName); 346 347 BQuery *query = new BQuery(); 348 query->SetPredicate("(BEOS:APP_SIG==\""kNotificationServerSignature"\")"); 349 query->SetVolume(&volume); 350 query->Fetch(); 351 352 if (query->GetNextRef(ref) == B_OK) 353 return true; 354 } 355 356 return false; 357 } 358 359 360 bool 361 GeneralView::_IsServerRunning() 362 { 363 return be_roster->IsRunning(kNotificationServerSignature); 364 } -
new file src/preferences/notifications/GeneralView.h
diff --git a/src/preferences/notifications/GeneralView.h b/src/preferences/notifications/GeneralView.h new file mode 100644 index 0000000..12c5f40
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _GENERAL_VIEW_H 7 #define _GENERAL_VIEW_H 8 9 #include "SettingsPane.h" 10 11 class BCheckBox; 12 class BButton; 13 class BStringView; 14 class BTextControl; 15 16 class GeneralView : public SettingsPane { 17 public: 18 GeneralView(SettingsHost* host); 19 20 virtual void AttachedToWindow(); 21 virtual void MessageReceived(BMessage* msg); 22 23 // SettingsPane hooks 24 status_t Load(); 25 status_t Save(); 26 status_t Revert(); 27 28 private: 29 BButton* fServerButton; 30 BStringView* fStatusLabel; 31 BCheckBox* fAutoStart; 32 BTextControl* fTimeout; 33 BCheckBox* fHideAll; 34 35 bool _CanFindServer(entry_ref* ref); 36 bool _IsServerRunning(); 37 }; 38 39 #endif // _GENERAL_VIEW_H -
new file src/preferences/notifications/IconItem.cpp
diff --git a/src/preferences/notifications/IconItem.cpp b/src/preferences/notifications/IconItem.cpp new file mode 100644 index 0000000..58f68a6
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <stdio.h> 11 12 #include <Bitmap.h> 13 14 #include "IconItem.h" 15 #include "IconRule.h" 16 17 const int32 kEdgeOffset = 4; 18 19 20 BIconItem::BIconItem(BView* owner, const char* label, BBitmap* icon) 21 : 22 fIcon(icon), 23 fLabel(label), 24 fSelected(false), 25 fOwner(owner) 26 { 27 } 28 29 30 BIconItem::~BIconItem() 31 { 32 delete fIcon; 33 } 34 35 void BIconItem::Draw() 36 { 37 if (IsSelected()) { 38 rgb_color color; 39 rgb_color origHigh; 40 41 origHigh = fOwner->HighColor(); 42 43 if (IsSelected()) 44 color = ui_color(B_CONTROL_HIGHLIGHT_COLOR); 45 else 46 color = fOwner->ViewColor(); 47 48 fOwner->SetHighColor(color); 49 fOwner->FillRect(fFrame); 50 fOwner->SetHighColor(origHigh); 51 } 52 53 if (fIcon) 54 { 55 fOwner->SetDrawingMode(B_OP_ALPHA); 56 fOwner->DrawBitmap(fIcon, BPoint(fFrame.top + kEdgeOffset, 57 fFrame.left + kEdgeOffset)); 58 fOwner->SetDrawingMode(B_OP_COPY); 59 } 60 61 if (IsSelected()) 62 fOwner->SetDrawingMode(B_OP_OVER); 63 64 #if 0 65 fOwner->MovePenTo(frame.left + kEdgeOffset + fIconWidth + kEdgeOffset, 66 frame.bottom - fFontOffset); 67 #else 68 fOwner->MovePenTo(fFrame.left, fFrame.bottom - 10); 69 #endif 70 fOwner->SetHighColor(ui_color(B_CONTROL_TEXT_COLOR)); 71 fOwner->DrawString(" "); 72 fOwner->DrawString(fLabel.String()); 73 } 74 75 76 const char* 77 BIconItem::Label() const 78 { 79 return fLabel.String(); 80 } 81 82 83 void 84 BIconItem::SetFrame(BRect frame) 85 { 86 fFrame = frame; 87 } 88 89 90 BRect 91 BIconItem::Frame() const 92 { 93 return fFrame; 94 } 95 96 97 void 98 BIconItem::Select() 99 { 100 fSelected = true; 101 Draw(); 102 } 103 104 105 void 106 BIconItem::Deselect() 107 { 108 fSelected = false; 109 Draw(); 110 } 111 112 113 bool 114 BIconItem::IsSelected() const 115 { 116 return fSelected; 117 } -
new file src/preferences/notifications/IconItem.h
diff --git a/src/preferences/notifications/IconItem.h b/src/preferences/notifications/IconItem.h new file mode 100644 index 0000000..e5feba0
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _ICON_ITEM_H 7 #define _ICON_ITEM_H 8 9 #include <View.h> 10 #include <String.h> 11 12 class BBitmap; 13 14 class BIconItem { 15 public: 16 BIconItem(BView* owner, const char* label, BBitmap* icon); 17 virtual ~BIconItem(); 18 19 void Draw(); 20 21 const char* Label() const; 22 23 void SetFrame(BRect frame); 24 BRect Frame() const; 25 26 void Select(); 27 void Deselect(); 28 bool IsSelected() const; 29 30 private: 31 BString fLabel; 32 BBitmap* fIcon; 33 bool fSelected; 34 BView* fOwner; 35 BRect fFrame; 36 }; 37 38 #endif // _ICON_ITEM_H -
new file src/preferences/notifications/IconRule.cpp
diff --git a/src/preferences/notifications/IconRule.cpp b/src/preferences/notifications/IconRule.cpp new file mode 100644 index 0000000..f8912b3
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <stdio.h> 11 12 #include <Message.h> 13 #include <Bitmap.h> 14 #include <Window.h> 15 #include <List.h> 16 17 #include "IconRule.h" 18 #include "IconItem.h" 19 20 const int32 kEdgeOffset = 8; 21 const int32 kBorderOffset = 1; 22 23 // TODO: Do we need to inherit from BControl? 24 25 BIconRule::BIconRule(const char* name) 26 : 27 BView(name, B_WILL_DRAW), 28 fSelIndex(-1) 29 { 30 fIcons = new BList(); 31 } 32 33 34 BIconRule::~BIconRule() 35 { 36 delete fIcons; 37 } 38 39 40 status_t 41 BIconRule::Invoke(BMessage* message) 42 { 43 bool notify = false; 44 uint32 kind = InvokeKind(¬ify); 45 46 BMessage clone(kind); 47 status_t err = B_BAD_VALUE; 48 49 if (!message && !notify) 50 message = Message(); 51 52 if (!message) { 53 if (!IsWatched()) 54 return err; 55 } else 56 clone = *message; 57 58 clone.AddInt64("when", (int64)system_time()); 59 clone.AddPointer("source", this); 60 clone.AddMessenger("be:sender", BMessenger(this)); 61 clone.AddInt32("index", fSelIndex); 62 63 if (message) 64 err = BInvoker::Invoke(&clone); 65 66 SendNotices(kind, &clone); 67 68 return err; 69 } 70 71 72 void 73 BIconRule::AttachedToWindow() 74 { 75 BView::AttachedToWindow(); 76 77 if (!Messenger().IsValid()) 78 SetTarget(Window(), NULL); 79 } 80 81 82 void 83 BIconRule::MouseDown(BPoint point) 84 { 85 if (!IsFocus()) { 86 MakeFocus(); 87 Sync(); 88 Window()->UpdateIfNeeded(); 89 } 90 91 int32 index = IndexOf(point); 92 if (index > -1) 93 SlideToIcon(index); 94 } 95 96 97 void 98 BIconRule::Draw(BRect updateRect) 99 { 100 int32 count = CountIcons(); 101 if (count == 0) 102 return; 103 104 rgb_color panelColor = ui_color(B_PANEL_BACKGROUND_COLOR); 105 rgb_color lightColor = tint_color(panelColor, B_DARKEN_1_TINT); 106 rgb_color darkColor = tint_color(lightColor, B_DARKEN_2_TINT); 107 108 SetHighColor(darkColor); 109 StrokeLine(Bounds().LeftTop(), Bounds().RightTop()); 110 StrokeLine(Bounds().LeftTop(), Bounds().LeftBottom()); 111 112 SetHighColor(lightColor); 113 StrokeLine(Bounds().LeftBottom(), Bounds().RightBottom()); 114 StrokeLine(Bounds().RightTop(), Bounds().RightBottom()); 115 116 BRect itemFrame(kEdgeOffset, kBorderOffset, -1, kBorderOffset + 64); 117 for (int32 i = 0; i < count; i++) { 118 BIconItem* item = static_cast<BIconItem*>(fIcons->ItemAt(i)); 119 float width = StringWidth(item->Label()) + StringWidth(" ") * 2; 120 if (width < 64.0f) 121 width = 64.0f; 122 itemFrame.right = itemFrame.left + width - 1; 123 124 if (itemFrame.Intersects(updateRect)) { 125 item->SetFrame(itemFrame); 126 item->Draw(); 127 } 128 129 itemFrame.left = itemFrame.right + kEdgeOffset + 1; 130 } 131 } 132 133 134 BMessage* 135 BIconRule::SelectionMessage() const 136 { 137 return fMessage; 138 } 139 140 141 void 142 BIconRule::SetSelectionMessage(BMessage* message) 143 { 144 delete fMessage; 145 fMessage = message; 146 } 147 148 149 int32 150 BIconRule::AddIcon(const char* label, const BBitmap* icon) 151 { 152 BIconItem* item = new BIconItem(this, label, (BBitmap*)icon); 153 if (CountIcons() == 0) { 154 item->Select(); 155 fSelIndex = 0; 156 } 157 (void)fIcons->AddItem(item); 158 } 159 160 161 void 162 BIconRule::RemoveIconAt(int32 index) 163 { 164 } 165 166 167 void 168 BIconRule::RemoveAllIcons() 169 { 170 } 171 172 173 int32 174 BIconRule::CountIcons() const 175 { 176 return fIcons->CountItems(); 177 } 178 179 180 void 181 BIconRule::SlideToIcon(int32 index) 182 { 183 // Ignore invalid items 184 if ((index < 0) || (index > CountIcons() - 1)) 185 return; 186 187 BIconItem* item = static_cast<BIconItem*>(fIcons->ItemAt(index)); 188 if (item) { 189 // Deselect previously selected item 190 if (fSelIndex > -1) { 191 BIconItem* selItem = static_cast<BIconItem*>(fIcons->ItemAt(fSelIndex)); 192 selItem->Deselect(); 193 } 194 195 // Select this item 196 item->Select(); 197 fSelIndex = index; 198 Invalidate(); 199 200 // Invoke notification 201 InvokeNotify(fMessage, B_CONTROL_MODIFIED); 202 } 203 } 204 205 206 void 207 BIconRule::SlideToNext() 208 { 209 if (fSelIndex + 1 < CountIcons() - 1) 210 return; 211 SlideToIcon(fSelIndex + 1); 212 } 213 214 215 void 216 BIconRule::SlideToPrevious() 217 { 218 if (fSelIndex <= 0) 219 return; 220 SlideToIcon(fSelIndex - 1); 221 } 222 223 224 int32 225 BIconRule::IndexOf(BPoint point) 226 { 227 int32 low = 0; 228 int32 high = fIcons->CountItems() - 1; 229 int32 mid = -1; 230 float frameLeft = -1.0f; 231 float frameRight = 1.0f; 232 233 // Binary search the list 234 while (high >= low) { 235 mid = (low + high) / 2; 236 BIconItem* item = static_cast<BIconItem*>(fIcons->ItemAt(mid)); 237 frameLeft = item->Frame().left; 238 frameRight = item->Frame().right; 239 if (point.x < frameLeft) 240 high = mid - 1; 241 else if (point.x > frameRight) 242 low = mid + 1; 243 else 244 return mid; 245 } 246 247 return -1; 248 } 249 250 BSize 251 BIconRule::MinSize() 252 { 253 BSize minSize(BView::MinSize()); 254 minSize.height = 64 + (kBorderOffset * 2); 255 return minSize; 256 } 257 258 259 BSize 260 BIconRule::MaxSize() 261 { 262 return BView::MaxSize(); 263 } 264 265 266 BSize 267 BIconRule::PreferredSize() 268 { 269 return BView::PreferredSize(); 270 } -
new file src/preferences/notifications/IconRule.h
diff --git a/src/preferences/notifications/IconRule.h b/src/preferences/notifications/IconRule.h new file mode 100644 index 0000000..854bbc1
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _ICON_RULE_H 7 #define _ICON_RULE_H 8 9 #include <Invoker.h> 10 #include <View.h> 11 12 class BList; 13 class BMessage; 14 15 class BIconRule : public BView, public BInvoker { 16 public: 17 BIconRule(const char* name); 18 virtual ~BIconRule(); 19 20 status_t Invoke(BMessage* message); 21 22 virtual void AttachedToWindow(); 23 24 virtual void MouseDown(BPoint point); 25 virtual void Draw(BRect updateRect); 26 27 BMessage* SelectionMessage() const; 28 void SetSelectionMessage(BMessage* message); 29 30 int32 AddIcon(const char* label, const BBitmap* icon); 31 void RemoveIconAt(int32 index); 32 void RemoveAllIcons(); 33 34 int32 CountIcons() const; 35 36 void SlideToIcon(int32 index); 37 void SlideToNext(); 38 void SlideToPrevious(); 39 40 int32 IndexOf(BPoint point); 41 42 virtual BSize MinSize(); 43 virtual BSize MaxSize(); 44 virtual BSize PreferredSize(); 45 46 private: 47 BList* fIcons; 48 int32 fSelIndex; 49 BMessage* fMessage; 50 }; 51 52 #endif // _ICON_RULE_H -
new file src/preferences/notifications/Jamfile
diff --git a/src/preferences/notifications/Jamfile b/src/preferences/notifications/Jamfile new file mode 100644 index 0000000..48ad097
- + 1 SubDir HAIKU_TOP src preferences notifications ; 2 3 UsePrivateHeaders interface ; 4 5 Application Notifications : 6 Notifications.cpp 7 PrefletWin.cpp 8 PrefletView.cpp 9 SettingsPane.cpp 10 GeneralView.cpp 11 DisplayView.cpp 12 NotificationsView.cpp 13 IconRule.cpp 14 IconItem.cpp 15 : be translation libcolumnlistview.a libnotification.a $(TARGET_LIBSTDC++) 16 : Notifications.rdef 17 ; 18 19 Depends Notifications : libcolumnlistview.a ; 20 Depends Notifications : libnotification.a ; -
new file src/preferences/notifications/Notifications.cpp
diff --git a/src/preferences/notifications/Notifications.cpp b/src/preferences/notifications/Notifications.cpp new file mode 100644 index 0000000..208e72a
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <Application.h> 11 12 #include "PrefletWin.h" 13 14 class PrefletApp : public BApplication { 15 public: 16 PrefletApp(); 17 18 virtual void ReadyToRun(); 19 virtual bool QuitRequested(); 20 21 private: 22 PrefletWin* fWindow; 23 }; 24 25 26 PrefletApp::PrefletApp() 27 : 28 BApplication("application/x-vnd.Haiku-Notifications") 29 { 30 } 31 32 33 void 34 PrefletApp::ReadyToRun() 35 { 36 fWindow = new PrefletWin; 37 } 38 39 40 bool 41 PrefletApp::QuitRequested() 42 { 43 return true; 44 } 45 46 47 int 48 main(int argc, char* argv[]) 49 { 50 PrefletApp app; 51 app.Run(); 52 return 0; 53 } -
new file src/preferences/notifications/Notifications.rdef
diff --git a/src/preferences/notifications/Notifications.rdef b/src/preferences/notifications/Notifications.rdef new file mode 100644 index 0000000..3168bbb
- + 1 2 resource app_signature "application/x-vnd.Haiku-Notifications"; 3 4 resource app_version { 5 major = 1, 6 middle = 0, 7 minor = 0, 8 9 variety = B_APPV_ALPHA, 10 internal = 0, 11 12 short_info = "Notifications", 13 long_info = "Notifications ©2009 Pier Luigi Fiorini ©2010 Haiku" 14 }; 15 16 resource app_flags B_SINGLE_LAUNCH; 17 18 resource vector_icon { 19 $"6E6369661201B0AEB6330200160734E2E73823CEB823CE34E2E74AE8E44C3C6C" 20 $"000020054715732EA251D37EE38F03B89B9B0200160734000B36F73FB6F73F34" 21 $"000B4AF7984C1AC8000020054715732EA251D37EE38F039F9FAA0200160730F6" 22 $"C6343295B4329530F6C64B14D64C04C5000020054715732EA251D37EE38F0200" 23 $"16073104ED343D08B43D083104ED4B14734C02F8000020054715732EA251D37E" 24 $"E38F039F9FBD020116023C322F0000000000003C322F4B471E4AA0B10000FF8F" 25 $"0500020116073C263B0000000000003C263B4AA2864A01D4000020054715732E" 26 $"A251D37EE38F039997AE0312031903B0AEB603292F3D0200160736FA5E3A3533" 27 $"BA353336FA5E4945B24A4CD9000020054715732EA251D37EE38F039B9C9F0400" 28 $"19140204CAC5CED7CAC5CE14CAC5CF99BF00D037CB4CD062B85FD02020CED720" 29 $"CF9920CE14BF00CD76B85FCD76C5A0CD76060B7FF413CACFCF60CACFCF60CACF" 30 $"CF5FCAD0CF5CCAD0CF5DCAD0CF5ACACFCF57CACFCF58CACFCF57CE42C3A0CF66" 31 $"C3A2CF66C3A2CF66C3B8CFDAC738D037C54AD037C926D037CACECF66CAB8CFDA" 32 $"CACECF66CACFCF600204C738CD66C535CD66C93BCD66CAD0CE42CAD0CDC7CAD0" 33 $"CEBDC738CF1DC93BCF1DC535CF1DC3A0CE42C3A0CEBDC3A0CDC7060847FFC914" 34 $"CDEAC914CDECC914CDEACCCCC514CDEBC515CDEBC515CDEBC515CDEDC514CDF1" 35 $"C514CDEFC514CE31C714CE65C5F9CE65C830CE65C915CDF1C915CE31C915CDEF" 36 $"0204C714CC50C5F5CC50C833CC50C915CCC4C915CC83C915CD05C714CD39C833" 37 $"CD39C5F5CD39C514CCC4C514CD05C514CC830204C714CC51C668CC51C7C0CC51" 38 $"C848CC97C848CC70C848CCBEC714CCDCC7C0CCDCC668CCDCC5E1CC97C5E1CCBE" 39 $"C5E1CC700A04C5E1CC67C847CC67C847CC97C5E1CC970204C714CC26C668CC26" 40 $"C7C0CC26C848CC6BC848CC44C848CC92C714CCB1C7C0CCB1C668CCB1C5E1CC6B" 41 $"C5E1CC92C5E1CC440611FEFFEDFF02C394BADFC73EBD9CC613BD06C869BE32CB" 42 $"07BFE3CA26BF02CBE7C0C3CC45C2CFCC45C20ACC45C394CB56C5A4CC23C4D7CA" 43 $"89C671CA0BC6CFCAD0C651C946C74DC82EC865C8A0C7A4C7BCC926C77DCBC4C7" 44 $"7DCA4AC77DCD3ECC61C70CCC7DC762CC7DC6B6CC7DC6A8CC61C681C926C681C9" 45 $"F3C681C859C77DC6DFC6FBC761C7FFC65DC9E4C394CA37C503C991C22AC852C2" 46 $"A8C8F7C271C7ACC2DFC56DC42AC61A4AC4C0C498C385C56D0204C2A9B8AAC14F" 47 $"B8AAC403B8AAC513BFF8C513BBE1C513C40FC2A9C746C403C746C14FC746C03F" 48 $"BFF8C03FC40FC03FBBE10204C298B8E9C15BB8E9C3D6B8E9C4D0BFF8C4D0BC04" 49 $"C4D0C3ECC298C706C3D6C706C15BC706C061BFF8C061C3ECC061BC040607FF3E" 50 $"CAFCC32ACB30C35DCAFCC32ACA65C4DBCAF7C449C9D4C56DC936C5F5C990C5AB" 51 $"C8DBC640C80EC6FEC864C680C7D3C754C77DC875C90BC698C7FCC73EC9A2C63B" 52 $"CB36C4BCCB04C529CB86C40D0205C517C3A4C517C369C517C3A4C817C271C78A" 53 $"C29EC8A8C242C9EBC27CC938C1F7CA40C2BCCA3EC1E7CAADC23EC9BAC17EC6E7" 54 $"C23DC87AC199C5B8C2BA0608FEFAC26DB961C2EBBA45C29CB9CFC33ABABBC41A" 55 $"BCDBC3EFBAB7C446BEFEC3F7C39CC4A0C0FEC34EC63AC30BC67DC31EC690C491" 56 $"BE5DC4FFC3D7C43DBA33C2D7B95DC379B994C236B9260205C186BD52C1BABCA9" 57 $"C186BD52C14BC116C12ABF53C16CC2D9C254C45BC1CAC46BC2DDC44BC2DDC2AC" 58 $"C33FC335C27BC222C1B3C0E5C1B3C1EEC1B3BFDD0205C0EFBD9CC12EBCE8C0EF" 59 $"BD9CC0A8C19DC081BFBEC0CFC37CC1E7C516C142C528C28DC505C28DC34CC303" 60 $"C3DEC216C2BAC126C169C126C282C126C0500205C2B8C588C2D2C5A2C2B8C588" 61 $"C252C68CC252C655C252C6C3C2A4C6D7C281C6D7C2C8C6D7C2F9C6A6C316C6C3" 62 $"C2DBC688C2ACC680C2ACC6A4C2ACC65D0207B7C920B7C920B8BD20B8BDB4A4B8" 63 $"C8B393B8BDB4A4B857BC43B857BC43B84BBD0AB735BDAFB81EBDAFB64CBDAFB6" 64 $"13BC43B61EBD0AB613BC43B5ACB4A4B5ACB4A4B59BB393B6A720B5B220B6A720" 65 $"0208B77FC12CB77FC12CB857C12CB8BDC270B8BDC198B8BDC270B8BDC304B8BD" 66 $"C304B8BDC3DCB77FC448B857C448B77FC448B6EBC448B6EBC448B613C448B5AC" 67 $"C304B5ACC3DCB5ACC304B5ACC270B5ACC270B5ACC198B6EBC12CB613C12CB6EB" 68 $"C12C0204B72ACD68B577CD68B8DDCD68BA33CDE5BA33CD9FBA33CE2CB72ACE63" 69 $"B8DDCE63B577CE63B421CDE5B421CE2CB421CD9F130A000100000A010101000A" 70 $"020102000A030103000A040104000A050105000A060106000A070107000A0801" 71 $"08000A090109000A0A010A000A0B010B000A0C010C000A0D010D000A0E010E00" 72 $"0A0F010F000A100110000A09021112000A11011300" 73 }; -
new file src/preferences/notifications/NotificationsView.cpp
diff --git a/src/preferences/notifications/NotificationsView.cpp b/src/preferences/notifications/NotificationsView.cpp new file mode 100644 index 0000000..bcde7ce
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <Alert.h> 11 #include <Directory.h> 12 #include <FindDirectory.h> 13 #include <GroupLayout.h> 14 #include <GroupLayoutBuilder.h> 15 #include <Window.h> 16 #include <CheckBox.h> 17 #include <TextControl.h> 18 #include <Path.h> 19 #include <Notification.h> 20 #include <notification/Notifications.h> 21 #include <notification/NotificationReceived.h> 22 23 #include <ColumnListView.h> 24 #include <ColumnTypes.h> 25 26 #include "NotificationsView.h" 27 28 #define _T(str) (str) 29 30 const float kEdgePadding = 5.0; 31 const float kCLVTitlePadding = 8.0; 32 33 const int32 kApplicationSelected = '_ASL'; 34 const int32 kNotificationSelected = '_NSL'; 35 36 const int32 kCLVDeleteRow = 'av02'; 37 38 // Applications column indexes 39 const int32 kAppIndex = 0; 40 const int32 kAppEnabledIndex = 1; 41 42 // Notifications column indexes 43 const int32 kTitleIndex = 0; 44 const int32 kDateIndex = 1; 45 const int32 kTypeIndex = 2; 46 const int32 kAllowIndex = 3; 47 48 const int32 kSettingChanged = '_STC'; 49 50 51 NotificationsView::NotificationsView() 52 : 53 BView("apps", B_WILL_DRAW) 54 { 55 BRect rect(0, 0, 100, 100); 56 57 // Search application field 58 fSearch = new BTextControl(_T("Search:"), NULL, 59 new BMessage(kSettingChanged)); 60 61 // Applications list 62 fApplications = new BColumnListView(rect, _T("Applications"), 63 0, B_WILL_DRAW, B_FANCY_BORDER, true); 64 fApplications->SetSelectionMode(B_SINGLE_SELECTION_LIST); 65 66 fAppCol = new BStringColumn(_T("Application"), 200, 67 be_plain_font->StringWidth(_T("Application")) + (kCLVTitlePadding * 2), 68 rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); 69 fApplications->AddColumn(fAppCol, kAppIndex); 70 71 fAppEnabledCol = new BStringColumn(_T("Enabled"), 10, 72 be_plain_font->StringWidth(_T("Enabled")) + (kCLVTitlePadding * 2), 73 rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); 74 fApplications->AddColumn(fAppEnabledCol, kAppEnabledIndex); 75 76 // Notifications list 77 fNotifications = new BColumnListView(rect, _T("Notifications"), 78 0, B_WILL_DRAW, B_FANCY_BORDER, true); 79 fNotifications->SetSelectionMode(B_SINGLE_SELECTION_LIST); 80 81 fTitleCol = new BStringColumn(_T("Title"), 100, 82 be_plain_font->StringWidth(_T("Title")) + (kCLVTitlePadding * 2), 83 rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); 84 fNotifications->AddColumn(fTitleCol, kTitleIndex); 85 86 fDateCol = new BDateColumn(_T("Last Received"), 100, 87 be_plain_font->StringWidth(_T("Last Received")) + (kCLVTitlePadding * 2), 88 rect.Width(), B_ALIGN_LEFT); 89 fNotifications->AddColumn(fDateCol, kDateIndex); 90 91 fTypeCol = new BStringColumn(_T("Type"), 100, 92 be_plain_font->StringWidth(_T("Type")) + (kCLVTitlePadding * 2), 93 rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); 94 fNotifications->AddColumn(fTypeCol, kTypeIndex); 95 96 fAllowCol = new BStringColumn(_T("Allowed"), 100, 97 be_plain_font->StringWidth(_T("Allowed")) + (kCLVTitlePadding * 2), 98 rect.Width(), B_TRUNCATE_END, B_ALIGN_LEFT); 99 fNotifications->AddColumn(fAllowCol, kAllowIndex); 100 101 // Load the applications list 102 _LoadAppUsage(); 103 _PopulateApplications(); 104 105 // Calculate inset 106 float inset = ceilf(be_plain_font->Size() * 0.7f); 107 108 // Set layout 109 SetLayout(new BGroupLayout(B_VERTICAL)); 110 111 // Add views 112 AddChild(BGroupLayoutBuilder(B_VERTICAL, inset) 113 .AddGroup(B_HORIZONTAL) 114 .AddGlue() 115 .Add(fSearch) 116 .End() 117 .Add(fApplications) 118 .Add(fNotifications) 119 ); 120 } 121 122 123 void 124 NotificationsView::AttachedToWindow() 125 { 126 fApplications->SetTarget(this); 127 fApplications->SetInvocationMessage(new BMessage(kApplicationSelected)); 128 129 fNotifications->SetTarget(this); 130 fNotifications->SetInvocationMessage(new BMessage(kNotificationSelected)); 131 132 #if 0 133 fNotifications->AddFilter(new BMessageFilter(B_ANY_DELIVERY, 134 B_ANY_SOURCE, B_KEY_DOWN, CatchDelete)); 135 #endif 136 } 137 138 139 void 140 NotificationsView::MessageReceived(BMessage* msg) 141 { 142 switch (msg->what) { 143 case kApplicationSelected: { 144 BRow *row = fApplications->CurrentSelection(); 145 if (row == NULL) 146 return; 147 BStringField* appname = 148 dynamic_cast<BStringField*>(row->GetField(kAppIndex)); 149 150 appusage_t::iterator it = fAppFilters.find(appname->String()); 151 if (it != fAppFilters.end()) 152 _Populate(it->second); 153 } break; 154 case kNotificationSelected: 155 break; 156 default: 157 BView::MessageReceived(msg); 158 break; 159 } 160 } 161 162 163 status_t 164 NotificationsView::_LoadAppUsage() 165 { 166 BPath path; 167 168 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 169 return B_ERROR; 170 171 path.Append(kSettingsDirectory); 172 173 if (create_directory(path.Path(), 0755) != B_OK) { 174 BAlert* alert = new BAlert("", 175 _T("There was a problem saving the preferences.\n" 176 "It's possible you don't have write access to the " 177 "settings directory."), "OK", NULL, NULL, 178 B_WIDTH_AS_USUAL, B_STOP_ALERT); 179 (void)alert->Go(); 180 return B_ERROR; 181 } 182 183 path.Append(kFiltersSettings); 184 185 BFile file(path.Path(), B_READ_ONLY); 186 BMessage settings; 187 if (settings.Unflatten(&file) != B_OK) 188 return B_ERROR; 189 190 type_code type; 191 int32 count = 0; 192 193 if (settings.GetInfo("app_usage", &type, &count) != B_OK) 194 return B_ERROR; 195 196 // Clean filters 197 appusage_t::iterator auIt; 198 for (auIt = fAppFilters.begin(); auIt != fAppFilters.end(); auIt++) 199 delete auIt->second; 200 fAppFilters.clear(); 201 202 // Add new filters 203 for (int32 i = 0; i < count; i++) { 204 AppUsage* app = new AppUsage(); 205 settings.FindFlat("app_usage", i, app); 206 fAppFilters[app->Name()] = app; 207 } 208 209 return B_OK; 210 } 211 212 213 void 214 NotificationsView::_PopulateApplications() 215 { 216 appusage_t::iterator it; 217 218 fApplications->Clear(); 219 220 for (it = fAppFilters.begin(); it != fAppFilters.end(); ++it) { 221 BRow* row = new BRow(); 222 row->SetField(new BStringField(it->first.String()), kAppIndex); 223 fApplications->AddRow(row); 224 } 225 } 226 227 228 void 229 NotificationsView::_Populate(AppUsage* usage) 230 { 231 // Sanity check 232 if (!usage) 233 return; 234 235 int32 size = usage->Notifications(); 236 237 if (usage->Allowed() == false) 238 fBlockAll->SetValue(B_CONTROL_ON); 239 240 fNotifications->Clear(); 241 242 for (int32 i = 0; i < size; i++) { 243 NotificationReceived* notification = usage->NotificationAt(i); 244 time_t updated = notification->LastReceived(); 245 const char* allow = notification->Allowed() ? _T("Yes") : _T("No"); 246 const char* type = ""; 247 248 switch (notification->Type()) { 249 case B_INFORMATION_NOTIFICATION: 250 type = _T("Information"); 251 break; 252 case B_IMPORTANT_NOTIFICATION: 253 type = _T("Important"); 254 break; 255 case B_ERROR_NOTIFICATION: 256 type = _T("Error"); 257 break; 258 case B_PROGRESS_NOTIFICATION: 259 type = _T("Progress"); 260 break; 261 default: 262 type = _T("Unknown"); 263 } 264 265 BRow* row = new BRow(); 266 row->SetField(new BStringField(notification->Title()), kTitleIndex); 267 row->SetField(new BDateField(&updated), kDateIndex); 268 row->SetField(new BStringField(type), kTypeIndex); 269 row->SetField(new BStringField(allow), kAllowIndex); 270 271 fNotifications->AddRow(row); 272 } 273 } -
new file src/preferences/notifications/NotificationsView.h
diff --git a/src/preferences/notifications/NotificationsView.h b/src/preferences/notifications/NotificationsView.h new file mode 100644 index 0000000..45a09eb
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _APPS_VIEW_H 7 #define _APPS_VIEW_H 8 9 #include <View.h> 10 11 #include <notification/AppUsage.h> 12 13 typedef std::map<BString, AppUsage *> appusage_t; 14 15 class BCheckBox; 16 class BTextControl; 17 class BColumnListView; 18 class BStringColumn; 19 class BDateColumn; 20 21 class NotificationsView : public BView { 22 public: 23 NotificationsView(); 24 25 virtual void AttachedToWindow(); 26 virtual void MessageReceived(BMessage* msg); 27 28 private: 29 status_t _LoadAppUsage(); 30 void _PopulateApplications(); 31 void _Populate(AppUsage* usage); 32 33 appusage_t fAppFilters; 34 BCheckBox* fBlockAll; 35 BTextControl* fSearch; 36 BColumnListView* fApplications; 37 BStringColumn* fAppCol; 38 BStringColumn* fAppEnabledCol; 39 BColumnListView* fNotifications; 40 BStringColumn* fTitleCol; 41 BDateColumn* fDateCol; 42 BStringColumn* fTypeCol; 43 BStringColumn* fAllowCol; 44 }; 45 46 #endif // _APPS_VIEW_H -
new file src/preferences/notifications/PrefletView.cpp
diff --git a/src/preferences/notifications/PrefletView.cpp b/src/preferences/notifications/PrefletView.cpp new file mode 100644 index 0000000..1482502
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <Message.h> 11 #include <GroupLayout.h> 12 #include <GroupLayoutBuilder.h> 13 #include <CardLayout.h> 14 #include <LayoutItem.h> 15 16 #include "SettingsHost.h" 17 #include "PrefletView.h" 18 #include "IconRule.h" 19 #include "GeneralView.h" 20 #include "DisplayView.h" 21 #include "NotificationsView.h" 22 23 #define _T(str) (str) 24 25 const int32 kPageSelected = '_LCH'; 26 27 28 PrefletView::PrefletView(SettingsHost* host) 29 : 30 BView("pages", B_WILL_DRAW) 31 { 32 // Page selector 33 fRule = new BIconRule("icon_rule"); 34 fRule->SetSelectionMessage(new BMessage(kPageSelected)); 35 (void)fRule->AddIcon(_T("General"), NULL); 36 (void)fRule->AddIcon(_T("Display"), NULL); 37 //(void)fRule->AddIcon(_T("Notifications"), NULL); 38 39 // View for card layout 40 fPagesView = new BView("pages", B_WILL_DRAW); 41 42 // Pages 43 GeneralView* general = new GeneralView(host); 44 DisplayView* display = new DisplayView(host); 45 NotificationsView* apps = new NotificationsView(); 46 47 // Calculate inset 48 float inset = ceilf(be_plain_font->Size() * 0.7f); 49 50 // Build the layout 51 SetLayout(new BGroupLayout(B_VERTICAL)); 52 53 // Card layout for pages 54 BCardLayout* layout = new BCardLayout(); 55 fPagesView->SetLayout(layout); 56 layout->AddView(general); 57 layout->AddView(display); 58 layout->AddView(apps); 59 60 // Add childs 61 AddChild(BGroupLayoutBuilder(B_VERTICAL, inset) 62 .Add(fRule) 63 .Add(fPagesView) 64 ); 65 66 // Select the first view 67 Select(0); 68 } 69 70 71 void 72 PrefletView::AttachedToWindow() 73 { 74 fRule->SetTarget(this); 75 } 76 77 78 void 79 PrefletView::MessageReceived(BMessage* message) 80 { 81 switch (message->what) { 82 case kPageSelected: 83 { 84 int32 index = B_ERROR; 85 if (message->FindInt32("index", &index) != B_OK) 86 return; 87 88 Select(index); 89 break; 90 } 91 default: 92 BView::MessageReceived(message); 93 } 94 } 95 96 97 void 98 PrefletView::Select(int32 index) 99 { 100 BCardLayout* layout 101 = dynamic_cast<BCardLayout*>(fPagesView->GetLayout()); 102 if (layout) 103 layout->SetVisibleItem(index); 104 } 105 106 107 BView* 108 PrefletView::CurrentPage() 109 { 110 BCardLayout* layout 111 = dynamic_cast<BCardLayout*>(fPagesView->GetLayout()); 112 if (layout) 113 return layout->VisibleItem()->View(); 114 return NULL; 115 } 116 117 118 int32 119 PrefletView::CountPages() const 120 { 121 BCardLayout* layout 122 = dynamic_cast<BCardLayout*>(fPagesView->GetLayout()); 123 if (layout) 124 return layout->CountItems(); 125 return 0; 126 } 127 128 129 BView* 130 PrefletView::PageAt(int32 index) 131 { 132 BCardLayout* layout 133 = dynamic_cast<BCardLayout*>(fPagesView->GetLayout()); 134 if (layout) 135 return layout->ItemAt(index)->View(); 136 return NULL; 137 } -
new file src/preferences/notifications/PrefletView.h
diff --git a/src/preferences/notifications/PrefletView.h b/src/preferences/notifications/PrefletView.h new file mode 100644 index 0000000..8b7d484
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _PREFLET_VIEW_H 7 #define _PREFLET_VIEW_H 8 9 #include <View.h> 10 11 class BIconRule; 12 13 class SettingsHost; 14 15 class PrefletView : public BView { 16 public: 17 PrefletView(SettingsHost* host); 18 19 virtual void AttachedToWindow(); 20 virtual void MessageReceived(BMessage* message); 21 22 void Select(int32 index); 23 BView* CurrentPage(); 24 int32 CountPages() const; 25 BView* PageAt(int32 index); 26 27 private: 28 BIconRule* fRule; 29 BView* fPagesView; 30 }; 31 32 #endif // PREFLETVIEW_H -
new file src/preferences/notifications/PrefletWin.cpp
diff --git a/src/preferences/notifications/PrefletWin.cpp b/src/preferences/notifications/PrefletWin.cpp new file mode 100644 index 0000000..6925ac3
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <Application.h> 11 #include <GroupLayout.h> 12 #include <GroupLayoutBuilder.h> 13 #include <Button.h> 14 15 #include "PrefletWin.h" 16 #include "PrefletView.h" 17 18 #define _T(str) (str) 19 20 const int32 kRevert = '_RVT'; 21 const int32 kSave = '_SAV'; 22 23 24 PrefletWin::PrefletWin() 25 : 26 BWindow(BRect(0, 0, 1, 1), "Notifications", B_TITLED_WINDOW, B_NOT_ZOOMABLE 27 | B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS) 28 { 29 // Preflet container view 30 fMainView = new PrefletView(this); 31 32 // Save and revert buttons 33 fRevert = new BButton("revert", _T("Revert"), new BMessage(kRevert)); 34 fRevert->SetEnabled(false); 35 fSave = new BButton("save", _T("Save"), new BMessage(kSave)); 36 fSave->SetEnabled(false); 37 38 // Calculate inset 39 float inset = ceilf(be_plain_font->Size() * 0.7f); 40 41 // Build the layout 42 SetLayout(new BGroupLayout(B_VERTICAL)); 43 44 // Add childs 45 AddChild(BGroupLayoutBuilder(B_VERTICAL, inset) 46 .Add(fMainView) 47 48 .AddGroup(B_HORIZONTAL, inset) 49 .AddGlue() 50 .Add(fRevert) 51 .Add(fSave) 52 .End() 53 54 .SetInsets(inset, inset, inset, inset) 55 ); 56 57 // Center this window on screen and show it 58 CenterOnScreen(); 59 Show(); 60 } 61 62 63 void 64 PrefletWin::MessageReceived(BMessage* msg) 65 { 66 switch (msg->what) { 67 case kSave: 68 for (int32 i = 0; i < fMainView->CountPages(); i++) { 69 SettingsPane* pane = 70 dynamic_cast<SettingsPane*>(fMainView->PageAt(i)); 71 if (pane) { 72 if (pane->Save() == B_OK) { 73 fSave->SetEnabled(false); 74 fRevert->SetEnabled(true); 75 } else 76 break; 77 } 78 } 79 break; 80 case kRevert: 81 for (int32 i = 0; i < fMainView->CountPages(); i++) { 82 SettingsPane* pane = 83 dynamic_cast<SettingsPane*>(fMainView->PageAt(i)); 84 if (pane) { 85 if (pane->Revert() == B_OK) 86 fRevert->SetEnabled(false); 87 } 88 } 89 break; 90 default: 91 BWindow::MessageReceived(msg); 92 } 93 } 94 95 96 bool 97 PrefletWin::QuitRequested() 98 { 99 be_app_messenger.SendMessage(B_QUIT_REQUESTED); 100 return true; 101 } 102 103 104 void 105 PrefletWin::SettingChanged() 106 { 107 fSave->SetEnabled(true); 108 } -
new file src/preferences/notifications/PrefletWin.h
diff --git a/src/preferences/notifications/PrefletWin.h b/src/preferences/notifications/PrefletWin.h new file mode 100644 index 0000000..f2029b8
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _PREFLET_WIN_H 7 #define _PREFLET_WIN_H 8 9 #include <Window.h> 10 11 #include "SettingsHost.h" 12 13 class BButton; 14 15 class PrefletView; 16 17 class PrefletWin : public BWindow, public SettingsHost { 18 public: 19 PrefletWin(); 20 21 virtual bool QuitRequested(); 22 virtual void MessageReceived(BMessage* msg); 23 24 virtual void SettingChanged(); 25 26 private: 27 PrefletView* fMainView; 28 BButton* fSave; 29 BButton* fRevert; 30 }; 31 32 #endif // _PREFLET_WIN_H -
new file src/preferences/notifications/SettingsHost.h
diff --git a/src/preferences/notifications/SettingsHost.h b/src/preferences/notifications/SettingsHost.h new file mode 100644 index 0000000..3774d7d
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _SETTINGS_HOST_H 7 #define _SETTINGS_HOST_H 8 9 #include <vector> 10 11 #include "SettingsPane.h" 12 13 class SettingsHost { 14 public: 15 SettingsHost() {} 16 17 virtual void SettingChanged() = 0; 18 }; 19 20 #endif // _SETTINGS_HOST_H -
new file src/preferences/notifications/SettingsPane.cpp
diff --git a/src/preferences/notifications/SettingsPane.cpp b/src/preferences/notifications/SettingsPane.cpp new file mode 100644 index 0000000..55e325e
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 * 6 * Authors: 7 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 8 */ 9 10 #include <Message.h> 11 #include <Node.h> 12 #include <Path.h> 13 #include <FindDirectory.h> 14 #include <Directory.h> 15 16 #include "SettingsPane.h" 17 #include "SettingsHost.h" 18 19 20 SettingsPane::SettingsPane(const char* name, SettingsHost* host) 21 : 22 BView(name, B_WILL_DRAW), 23 fHost(host) 24 { 25 } 26 27 28 void 29 SettingsPane::MessageReceived(BMessage* msg) 30 { 31 switch (msg->what) { 32 case kSettingChanged: 33 fHost->SettingChanged(); 34 break; 35 default: 36 BView::MessageReceived(msg); 37 } 38 } -
new file src/preferences/notifications/SettingsPane.h
diff --git a/src/preferences/notifications/SettingsPane.h b/src/preferences/notifications/SettingsPane.h new file mode 100644 index 0000000..6908900
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Copyright 2009, Pier Luigi Fiorini. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef _SETTINGS_PANE_H 7 #define _SETTINGS_PANE_H 8 9 #include <View.h> 10 11 class BNode; 12 13 class SettingsHost; 14 15 const int32 kSettingChanged = '_STC'; 16 17 class SettingsPane : public BView { 18 public: 19 SettingsPane(const char* name, SettingsHost* host); 20 21 virtual void MessageReceived(BMessage* msg); 22 23 virtual status_t Load() = 0; 24 virtual status_t Save() = 0; 25 virtual status_t Revert() = 0; 26 27 protected: 28 SettingsHost* fHost; 29 }; 30 31 #endif // _SETTINGS_PANE_H -
src/servers/Jamfile
diff --git a/src/servers/Jamfile b/src/servers/Jamfile index 1d05594..77f3dc7 100644
a b SubInclude HAIKU_TOP src servers media_addon ; 11 11 SubInclude HAIKU_TOP src servers midi ; 12 12 SubInclude HAIKU_TOP src servers mount ; 13 13 SubInclude HAIKU_TOP src servers net ; 14 SubInclude HAIKU_TOP src servers notification ; 14 15 SubInclude HAIKU_TOP src servers power ; 15 16 SubInclude HAIKU_TOP src servers print ; 16 17 SubInclude HAIKU_TOP src servers registrar ; -
new file src/servers/notification/AppGroupView.cpp
diff --git a/src/servers/notification/AppGroupView.cpp b/src/servers/notification/AppGroupView.cpp new file mode 100644 index 0000000..9612f54
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Michael Davidson, slaad@bong.com.au 10 * Mikael Eiman, mikael@eiman.tv 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 */ 13 14 #include <algorithm> 15 16 #include "AppGroupView.h" 17 18 #include "NotificationWindow.h" 19 #include "NotificationView.h" 20 21 22 AppGroupView::AppGroupView(NotificationWindow* win, const char* label) 23 : 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), 26 fLabel(label), 27 fParent(win), 28 fCollapsed(false) 29 { 30 Show(); 31 } 32 33 34 AppGroupView::~AppGroupView() 35 { 36 } 37 38 39 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 void 49 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 widget 84 PushState(); 85 SetHighColor(detailCol); 86 StrokeLine(BPoint(kEdgePadding, linePos), BPoint(fCollapseRect.left, linePos)); 87 PopState(); 88 89 // Draw the expand widget 90 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 title 104 DrawString(label.String(), BPoint(fCollapseRect.right + kEdgePadding, labelOffset + kEdgePadding)); 105 106 // Draw the line from the label to the close widget 107 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 widget 116 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 widget 126 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 border 141 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 widget 150 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 widget 161 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 label 172 DrawString(label.String(), BPoint(fCollapseRect.right + kEdgePadding, labelOffset + kEdgePadding)); 173 PopState(); 174 } 175 176 Sync(); 177 } 178 179 180 void 181 AppGroupView::MouseDown(BPoint point) 182 { 183 bool changed = false; 184 if (fCloseRect.Contains(point)) { 185 changed = true; 186 187 int32 children = fInfo.size(); 188 for (int32 i = 0; i < children; i++) { 189 fInfo[i]->RemoveSelf(); 190 delete fInfo[i]; 191 } 192 fInfo.clear(); 193 } 194 195 if (fCollapseRect.Contains(point)) { 196 fCollapsed = !fCollapsed; 197 changed = true; 198 } 199 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; 233 } 234 235 236 void 237 AppGroupView::MessageReceived(BMessage* msg) 238 { 239 switch (msg->what) { 240 case kRemoveView: 241 { 242 NotificationView* view = NULL; 243 if (msg->FindPointer("view", (void**)&view) != B_OK) 244 return; 245 246 infoview_t::iterator vIt = find(fInfo.begin(), fInfo.end(), view); 247 248 if (vIt != fInfo.end()) { 249 fInfo.erase(vIt); 250 view->RemoveSelf(); 251 delete view; 252 } 253 254 ResizeViews(); 255 Invalidate(); 256 257 // When all the views are destroy, save app filters 258 if (fInfo.size() == 0) 259 dynamic_cast<NotificationWindow*>(Window())->SaveAppFilters(); 260 break; 261 } 262 default: 263 BView::MessageReceived(msg); 264 } 265 } 266 267 268 void 269 AppGroupView::AddInfo(NotificationView* view) 270 { 271 BString id = view->MessageID(); 272 if (id.Length() > 0) { 273 int32 children = fInfo.size(); 274 bool found = false; 275 276 for (int32 i = 0; i < children; i++) { 277 if (fInfo[i]->HasMessageID(id.String())) { 278 fInfo[i]->RemoveSelf(); 279 delete fInfo[i]; 280 281 fInfo[i] = view; 282 found = true; 283 284 break; 285 } 286 } 287 288 if (!found) 289 fInfo.push_back(view); 290 } else 291 fInfo.push_back(view); 292 293 if (fParent->IsHidden()) 294 fParent->Show(); 295 if (IsHidden()) 296 Show(); 297 if (view->IsHidden()) 298 view->Show(); 299 300 AddChild(view); 301 302 ResizeViews(); 303 Invalidate(); 304 } 305 306 307 void 308 AppGroupView::ResizeViews() 309 { 310 font_height fh; 311 be_bold_font->GetHeight(&fh); 312 313 float offset = fh.ascent + fh.leading + fh.descent; 314 int32 children = fInfo.size(); 315 316 if (!fCollapsed) { 317 offset += kEdgePadding + kPenSize; 318 319 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 if (fInfo[i]->IsHidden()) 325 fInfo[i]->Show(); 326 fInfo[i]->SetPosition(false, false); 327 }; 328 } else { 329 for (int32 i = 0; i < children; i++) 330 if (!fInfo[i]->IsHidden()) 331 fInfo[i]->Hide(); 332 } 333 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); 342 float labelOffset = fh.ascent + fh.leading; 343 344 BRect borderRect = Bounds().InsetByCopy(kEdgePadding, kEdgePadding); 345 borderRect.top = labelOffset; 346 347 fCollapseRect = borderRect; 348 fCollapseRect.right = fCollapseRect.left + kExpandSize; 349 fCollapseRect.bottom = fCollapseRect.top + kExpandSize; 350 fCollapseRect.OffsetTo(kEdgePadding * 2, kEdgePadding * 1.5); 351 352 fCloseRect = borderRect; 353 fCloseRect.right -= kEdgePadding * 4; 354 fCloseRect.left = fCloseRect.right - kCloseSize; 355 fCloseRect.bottom = fCloseRect.top + kCloseSize; 356 fCloseRect.OffsetTo(fCloseRect.left, kEdgePadding * 1.5); 357 358 fParent->ResizeAll(); 359 } 360 361 362 bool 363 AppGroupView::HasChildren() 364 { 365 return !fInfo.empty(); 366 } -
new file src/servers/notification/AppGroupView.h
diff --git a/src/servers/notification/AppGroupView.h b/src/servers/notification/AppGroupView.h new file mode 100644 index 0000000..eeb9a81
- + 1 /* 2 * Copyright 2005-2008, Mikael Eiman. 3 * Copyright 2005-2008, Michael Davidson. 4 * 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 */ 10 11 #ifndef APPGROUPVIEW_H 12 #define APPGROUPVIEW_H 13 14 #include <vector> 15 16 #include <String.h> 17 #include <View.h> 18 19 class NotificationWindow; 20 class NotificationView; 21 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; 48 }; 49 50 #endif -
new file src/servers/notification/BorderView.cpp
diff --git a/src/servers/notification/BorderView.cpp b/src/servers/notification/BorderView.cpp new file mode 100644 index 0000000..e19fb86
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Michael Davidson, slaad@bong.com.au 10 * Mikael Eiman, mikael@eiman.tv 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 */ 13 14 #include "BorderView.h" 15 16 const float kBorderWidth = 2.0f; 17 const int32 kTitleSize = 14; 18 19 20 BorderView::BorderView(BRect rect, const char* text) 21 : 22 BView(rect, "NotificationBorderView", B_FOLLOW_ALL, 23 B_WILL_DRAW | B_FRAME_EVENTS), 24 fTitle(text) 25 { 26 SetViewColor(B_TRANSPARENT_COLOR); 27 } 28 29 30 BorderView::~BorderView() 31 { 32 } 33 34 35 void 36 BorderView::FrameResized(float, float) 37 { 38 Invalidate(); 39 } 40 41 42 void 43 BorderView::Draw(BRect rect) 44 { 45 rgb_color col_bg = ui_color(B_PANEL_BACKGROUND_COLOR); 46 rgb_color col_text = tint_color(col_bg, B_LIGHTEN_MAX_TINT); 47 rgb_color col_text_shadow = tint_color(col_bg, B_DARKEN_MAX_TINT); 48 49 // Background 50 SetDrawingMode(B_OP_COPY); 51 SetHighColor(col_bg); 52 FillRect(rect); 53 54 // Text 55 SetLowColor(col_bg); 56 SetDrawingMode(B_OP_ALPHA); 57 SetFont(be_bold_font); 58 SetFontSize(kTitleSize); 59 60 BFont font; 61 GetFont(&font); 62 63 font_height fh; 64 font.GetHeight(&fh); 65 66 // float line_height = fh.ascent + fh.descent + fh.leading; 67 68 float text_pos = fh.ascent; 69 70 SetHighColor(col_text); 71 DrawString(fTitle.String(), BPoint(kBorderWidth, text_pos)); 72 73 SetHighColor(col_text_shadow); 74 DrawString(fTitle.String(), BPoint(kBorderWidth + 1, text_pos + 1)); 75 76 // Content border 77 SetHighColor(tint_color(col_bg, B_DARKEN_2_TINT)); 78 79 BRect content = Bounds(); 80 content.InsetBy(kBorderWidth, kBorderWidth); 81 content.top += text_pos + fh.descent + 2; 82 83 BRect content_line(content); 84 content_line.InsetBy(-1, -1); 85 86 StrokeRect(content_line); 87 } 88 89 90 void 91 BorderView::GetPreferredSize(float* w, float* h) 92 { 93 SetFont(be_bold_font); 94 SetFontSize(kTitleSize); 95 96 BFont font; 97 GetFont(&font); 98 99 font_height fh; 100 font.GetHeight(&fh); 101 102 float line_height = fh.ascent + fh.descent; 103 104 *w = 2 * kBorderWidth + StringWidth(fTitle.String()); 105 *h = 2 * kBorderWidth + line_height + 3; 106 *w = *h = 0; 107 } 108 109 110 float 111 BorderView::BorderSize() 112 { 113 return 0; 114 } -
new file src/servers/notification/BorderView.h
diff --git a/src/servers/notification/BorderView.h b/src/servers/notification/BorderView.h new file mode 100644 index 0000000..2e1bea9
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 */ 8 #ifndef _BORDER_VIEW_H 9 #define _BORDER_VIEW_H 10 11 #include <View.h> 12 #include <String.h> 13 14 class BorderView : public BView { 15 public: 16 BorderView(BRect, const char*); 17 virtual ~BorderView(); 18 19 virtual void Draw(BRect updateRect); 20 21 virtual void GetPreferredSize(float*, float*); 22 23 virtual void FrameResized(float, float); 24 25 float BorderSize(); 26 27 private: 28 BString fTitle; 29 }; 30 31 #endif // _BORDER_VIEW_H -
new file src/servers/notification/Jamfile
diff --git a/src/servers/notification/Jamfile b/src/servers/notification/Jamfile new file mode 100644 index 0000000..26d0652
- + 1 SubDir HAIKU_TOP src servers notification ; 2 3 UsePrivateHeaders notification ; 4 UseLibraryHeaders icon ; 5 6 Server notification_server : 7 AppGroupView.cpp 8 BorderView.cpp 9 NotificationServer.cpp 10 NotificationView.cpp 11 NotificationWindow.cpp 12 : be $(TARGET_LIBSTDC++) libicon.a libnotification.a 13 : notification_server.rdef 14 ; 15 16 Depends notification_server : libicon.a ; 17 Depends notification_server : libnotification.a ; -
new file src/servers/notification/NotificationServer.cpp
diff --git a/src/servers/notification/NotificationServer.cpp b/src/servers/notification/NotificationServer.cpp new file mode 100644 index 0000000..bd874e3
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 7 */ 8 9 #include <Beep.h> 10 #include <Notifications.h> 11 12 #include "NotificationWindow.h" 13 #include "NotificationServer.h" 14 15 const char* kSoundNames[] = { 16 "Information notification", 17 "Important notification", 18 "Error notification", 19 "Progress notification", 20 NULL 21 }; 22 23 24 NotificationServer::NotificationServer() 25 : BApplication(kNotificationServerSignature) 26 { 27 fWindow = new NotificationWindow(); 28 } 29 30 31 NotificationServer::~NotificationServer() 32 { 33 } 34 35 36 void 37 NotificationServer::MessageReceived(BMessage* message) 38 { 39 switch (message->what) { 40 case kNotificationMessage: 41 { 42 // Skip this message if we don't have the window 43 if (!fWindow) 44 return; 45 46 int32 type = 0; 47 48 // Emit a sound for this event 49 if (message->FindInt32("type", &type) == B_OK) { 50 if (type < (int32)(sizeof(kSoundNames) / sizeof(const char*))) 51 system_beep(kSoundNames[type]); 52 } 53 54 // Let the notification window handle this message 55 BMessenger(fWindow).SendMessage(message); 56 break; 57 } 58 default: 59 BApplication::MessageReceived(message); 60 } 61 } 62 63 64 bool 65 NotificationServer::QuitRequested() 66 { 67 if (fWindow && fWindow->Lock()) { 68 fWindow->Quit(); 69 fWindow = NULL; 70 } 71 return true; 72 } 73 74 75 status_t 76 NotificationServer::GetSupportedSuites(BMessage* msg) 77 { 78 msg->AddString("suites", "suite/x-vnd.Haiku-notification_server"); 79 80 BPropertyInfo info(main_prop_list); 81 msg->AddFlat("messages", &info); 82 83 return BApplication::GetSupportedSuites(msg); 84 } 85 86 87 BHandler* 88 NotificationServer::ResolveSpecifier(BMessage* msg, int32 index, 89 BMessage* spec, int32 from, const char* prop) 90 { 91 BPropertyInfo info(main_prop_list); 92 93 if (strcmp(prop, "message") == 0) { 94 BMessenger messenger(fWindow); 95 messenger.SendMessage(msg, fWindow); 96 return NULL; 97 } 98 99 return BApplication::ResolveSpecifier(msg, index, spec, from, prop); 100 } 101 102 103 int 104 main(int argc, char* argv[]) 105 { 106 int32 i = 0; 107 108 // Add system sounds 109 while (kSoundNames[i] != NULL) 110 add_system_beep_event(kSoundNames[i++], 0); 111 112 // Start! 113 NotificationServer* server = new NotificationServer(); 114 server->Run(); 115 116 return 0; 117 } -
new file src/servers/notification/NotificationServer.h
diff --git a/src/servers/notification/NotificationServer.h b/src/servers/notification/NotificationServer.h new file mode 100644 index 0000000..aff0da1
- + 1 /* 2 * Copyright 2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _NOTIFICATION_SERVER_H 6 #define _NOTIFICATION_SERVER_H 7 8 #include <Application.h> 9 10 class NotificationWindow; 11 12 class NotificationServer : public BApplication { 13 public: 14 NotificationServer(); 15 virtual ~NotificationServer(); 16 17 virtual void MessageReceived(BMessage* message); 18 virtual bool QuitRequested(); 19 20 virtual status_t GetSupportedSuites(BMessage* msg); 21 virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, 22 int32 form, const char* prop); 23 24 private: 25 NotificationWindow* fWindow; 26 }; 27 28 #endif // _NOTIFICATION_SERVER_H -
new file src/servers/notification/NotificationView.cpp
diff --git a/src/servers/notification/NotificationView.cpp b/src/servers/notification/NotificationView.cpp new file mode 100644 index 0000000..fee1853
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Michael Davidson, slaad@bong.com.au 10 * Mikael Eiman, mikael@eiman.tv 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 */ 13 14 #include <stdlib.h> 15 16 #include <Font.h> 17 #include <IconUtils.h> 18 #include <Messenger.h> 19 #include <Picture.h> 20 #include <PropertyInfo.h> 21 #include <Region.h> 22 #include <Resources.h> 23 #include <Roster.h> 24 #include <StringView.h> 25 #include <TranslationUtils.h> 26 27 #include "NotificationView.h" 28 #include "NotificationWindow.h" 29 30 const char* kSmallIconAttribute = "BEOS:M:STD_ICON"; 31 const char* kLargeIconAttribute = "BEOS:L:STD_ICON"; 32 const char* kIconAttribute = "BEOS:ICON"; 33 34 property_info message_prop_list[] = { 35 { "type", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 36 {B_DIRECT_SPECIFIER, 0}, "get the notification type"}, 37 { "app", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 38 {B_DIRECT_SPECIFIER, 0}, "get notification's app"}, 39 { "title", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 40 {B_DIRECT_SPECIFIER, 0}, "get notification's title"}, 41 { "content", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 42 {B_DIRECT_SPECIFIER, 0}, "get notification's contents"}, 43 { "icon", {B_GET_PROPERTY, 0}, 44 {B_DIRECT_SPECIFIER, 0}, "get icon as an archived bitmap"}, 45 { "progress", {B_GET_PROPERTY, B_SET_PROPERTY, 0}, 46 {B_DIRECT_SPECIFIER, 0}, "get the progress (between 0.0 and 1.0)"}, 47 NULL 48 }; 49 50 51 NotificationView::NotificationView(NotificationWindow* win, 52 notification_type type, const char* app, const char* title, const char* text, 53 BMessage* details) 54 : 55 BView(BRect(0, 0, win->ViewWidth(), 1), "NotificationView", 56 B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE 57 | B_FRAME_EVENTS), 58 fParent(win), 59 fType(type), 60 fRunner(NULL), 61 fProgress(0.0f), 62 fMessageID(""), 63 fDetails(details), 64 fBitmap(NULL), 65 fIsFirst(false), 66 fIsLast(false) 67 { 68 BMessage iconMsg; 69 if (fDetails->FindMessage("icon", &iconMsg) == B_OK) 70 fBitmap = new BBitmap(&iconMsg); 71 72 if (!fBitmap) 73 _LoadIcon(); 74 75 const char* messageID = NULL; 76 if (fDetails->FindString("messageID", &messageID) == B_OK) 77 fMessageID = messageID; 78 79 if (fDetails->FindFloat("progress", &fProgress) != B_OK) 80 fProgress = 0.0f; 81 82 // Progress is between 0 and 1 83 if (fProgress < 0.0f) 84 fProgress = 0.0f; 85 if (fProgress > 1.0f) 86 fProgress = 1.0f; 87 88 SetText(app, title, text); 89 ResizeToPreferred(); 90 91 switch (type) { 92 case B_IMPORTANT_NOTIFICATION: 93 SetViewColor(255, 255, 255); 94 SetLowColor(255, 255, 255); 95 break; 96 case B_ERROR_NOTIFICATION: 97 SetViewColor(ui_color(B_FAILURE_COLOR)); 98 SetLowColor(ui_color(B_FAILURE_COLOR)); 99 break; 100 default: 101 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 102 SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 103 break; 104 } 105 } 106 107 108 NotificationView::~NotificationView() 109 { 110 delete fRunner; 111 delete fDetails; 112 delete fBitmap; 113 114 vline::iterator lIt; 115 for (lIt = fLines.begin(); lIt != fLines.end(); lIt++) 116 delete (*lIt); 117 } 118 119 120 void 121 NotificationView::AttachedToWindow() 122 { 123 BMessage msg(kRemoveView); 124 msg.AddPointer("view", this); 125 int32 timeout = -1; 126 127 if (fDetails->FindInt32("timeout", &timeout) != B_OK) 128 timeout = fParent->Timeout(); 129 bigtime_t delay = timeout * 1000 * 1000; 130 131 if (delay > 0) 132 fRunner = new BMessageRunner(BMessenger(Parent()), &msg, delay, 1); 133 } 134 135 136 void 137 NotificationView::MessageReceived(BMessage* msg) 138 { 139 switch (msg->what) { 140 case B_GET_PROPERTY: 141 { 142 BMessage specifier; 143 const char* property; 144 BMessage reply(B_REPLY); 145 bool msgOkay = true; 146 147 if (msg->FindMessage("specifiers", 0, &specifier) != B_OK) 148 msgOkay = false; 149 if (specifier.FindString("property", &property) != B_OK) 150 msgOkay = false; 151 152 if (msgOkay) { 153 if (strcmp(property, "type") == 0) 154 reply.AddInt32("result", fType); 155 156 if (strcmp(property, "app") == 0) 157 reply.AddString("result", fApp); 158 159 if (strcmp(property, "title") == 0) 160 reply.AddString("result", fTitle); 161 162 if (strcmp(property, "content") == 0) 163 reply.AddString("result", fText); 164 165 if (strcmp(property, "progress") == 0) 166 reply.AddFloat("result", fProgress); 167 168 if ((strcmp(property, "icon") == 0) && fBitmap) { 169 BMessage archive; 170 if (fBitmap->Archive(&archive) == B_OK) 171 reply.AddMessage("result", &archive); 172 } 173 174 reply.AddInt32("error", B_OK); 175 } else { 176 reply.what = B_MESSAGE_NOT_UNDERSTOOD; 177 reply.AddInt32("error", B_ERROR); 178 } 179 180 msg->SendReply(&reply); 181 break; 182 } 183 case B_SET_PROPERTY: 184 { 185 BMessage specifier; 186 const char* property; 187 BMessage reply(B_REPLY); 188 bool msgOkay = true; 189 190 if (msg->FindMessage("specifiers", 0, &specifier) != B_OK) 191 msgOkay = false; 192 if (specifier.FindString("property", &property) != B_OK) 193 msgOkay = false; 194 195 if (msgOkay) { 196 if (strcmp(property, "app") == 0) 197 msg->FindString("data", &fApp); 198 199 if (strcmp(property, "title") == 0) 200 msg->FindString("data", &fTitle); 201 202 if (strcmp(property, "content") == 0) 203 msg->FindString("data", &fText); 204 205 if (strcmp(property, "icon") == 0) { 206 BMessage archive; 207 if (msg->FindMessage("data", &archive) == B_OK) { 208 delete fBitmap; 209 fBitmap = new BBitmap(&archive); 210 } 211 } 212 213 SetText(Application(), Title(), Text()); 214 Invalidate(); 215 216 reply.AddInt32("error", B_OK); 217 } else { 218 reply.what = B_MESSAGE_NOT_UNDERSTOOD; 219 reply.AddInt32("error", B_ERROR); 220 } 221 222 msg->SendReply(&reply); 223 break; 224 } 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 default: 234 BView::MessageReceived(msg); 235 } 236 } 237 238 239 void 240 NotificationView::GetPreferredSize(float* w, float* h) 241 { 242 // Parent width, minus the edge padding, minus the pensize 243 *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 void 256 NotificationView::Draw(BRect updateRect) 257 { 258 BRect progRect; 259 260 // Draw progress background 261 if (fType == B_PROGRESS_NOTIFICATION) { 262 PushState(); 263 264 font_height fh; 265 be_plain_font->GetHeight(&fh); 266 float fontHeight = fh.ascent + fh.descent + fh.leading; 267 268 progRect = Bounds(); 269 progRect.InsetBy(kEdgePadding, kEdgePadding); 270 progRect.top = progRect.bottom - (kSmallPadding * 2) - fontHeight; 271 StrokeRect(progRect); 272 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); 278 279 SetHighColor(ui_color(B_PANEL_TEXT_COLOR)); 280 281 BString label = ""; 282 label << (int)(fProgress * 100) << " %"; 283 284 float labelWidth = be_plain_font->StringWidth(label.String()); 285 float labelX = progRect.left + (progRect.IntegerWidth() / 2) - (labelWidth / 2); 286 287 SetLowColor(B_TRANSPARENT_COLOR); 288 SetDrawingMode(B_OP_ALPHA); 289 DrawString(label.String(), label.Length(), 290 BPoint(labelX, progRect.top + fh.ascent + fh.leading + kSmallPadding)); 291 292 PopState(); 293 } 294 295 SetDrawingMode(B_OP_ALPHA); 296 SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY); 297 298 // Icon size 299 float iconSize = (float)fParent->IconSize(); 300 301 // Rectangle for icon and overlay icon 302 BRect iconRect(0, 0, 0, 0); 303 304 // Draw icon 305 if (fBitmap) { 306 lineinfo* appLine = fLines.back(); 307 font_height fh; 308 appLine->font.GetHeight(&fh); 309 310 float title_bottom = appLine->location.y + fh.descent; 311 312 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; 319 320 if (fType == B_PROGRESS_NOTIFICATION) 321 // Move icon up by half progress bar height if it's present 322 iy -= (progRect.Height() + kEdgePadding) / 2.0; 323 324 iconRect.left = ix; 325 iconRect.top = iy; 326 iconRect.right = ix + iconSize; 327 iconRect.bottom = iy + iconSize; 328 329 DrawBitmapAsync(fBitmap, fBitmap->Bounds(), 330 iconRect, B_FILTER_BITMAP_BILINEAR); 331 } 332 333 // Draw content 334 vline::iterator lIt; 335 for (lIt = fLines.begin(); lIt != fLines.end(); lIt++) { 336 lineinfo *l = (*lIt); 337 338 SetFont(&l->font); 339 DrawString(l->text.String(), l->text.Length(), l->location); 340 } 341 342 rgb_color detailCol = ui_color(B_CONTROL_BORDER_COLOR); 343 detailCol = tint_color(detailCol, B_LIGHTEN_2_TINT); 344 345 // Draw the close widget 346 BRect closeRect = Bounds(); 347 closeRect.InsetBy(kEdgePadding, kEdgePadding); 348 closeRect.left = closeRect.right - kCloseSize; 349 closeRect.bottom = closeRect.top + kCloseSize; 350 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(); 360 } 361 362 363 void 364 NotificationView::MouseDown(BPoint point) 365 { 366 int32 buttons; 367 Window()->CurrentMessage()->FindInt32("buttons", &buttons); 368 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 } 400 401 if (useArgv) { 402 type_code type; 403 int32 argc = 0; 404 BString arg; 405 406 BPath p(&appRef); 407 argMsg.AddString("argv", p.Path()); 408 409 fDetails->GetInfo("onClickArgv", &type, &argc); 410 argMsg.AddInt32("argc", argc + 1); 411 412 for (int32 i = 0; fDetails->FindString("onClickArgv", i, &arg) == B_OK; i++) 413 argMsg.AddString("argv", arg); 414 415 messages.AddItem((void*)&argMsg); 416 } 417 418 BMessage tmp; 419 for (int32 i = 0; fDetails->FindMessage("onClickMsg", i, &tmp) == B_OK; i++) 420 messages.AddItem((void*)&tmp); 421 422 if (fDetails->FindString("onClickApp", &launchString) == B_OK) 423 be_roster->Launch(launchString.String(), &messages); 424 else 425 be_roster->Launch(&launchRef, &messages); 426 } 427 428 // Remove the info view after a click 429 BMessage remove_msg(kRemoveView); 430 remove_msg.AddPointer("view", this); 431 432 BMessenger msgr(Parent()); 433 msgr.SendMessage(&remove_msg); 434 break; 435 } 436 } 437 } 438 439 440 void 441 NotificationView::FrameResized( float w, float /*h*/) 442 { 443 SetText(Application(), Title(), Text()); 444 } 445 446 447 BHandler* 448 NotificationView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, int32 form, const char* prop) 449 { 450 BPropertyInfo prop_info(message_prop_list); 451 if (prop_info.FindMatch(msg, index, spec, form, prop) >= 0) { 452 msg->PopSpecifier(); 453 return this; 454 } 455 456 return BView::ResolveSpecifier(msg, index, spec, form, prop); 457 } 458 459 460 status_t 461 NotificationView::GetSupportedSuites(BMessage* msg) 462 { 463 msg->AddString("suites", "suite/x-vnd.Haiku-notification_server"); 464 BPropertyInfo prop_info(message_prop_list); 465 msg->AddFlat("messages", &prop_info); 466 return BView::GetSupportedSuites(msg); 467 } 468 469 470 const char* 471 NotificationView::Application() const 472 { 473 return fApp.Length() > 0 ? fApp.String() : NULL; 474 } 475 476 477 const char* 478 NotificationView::Title() const 479 { 480 return fTitle.Length() > 0 ? fTitle.String() : NULL; 481 } 482 483 484 const char* 485 NotificationView::Text() const 486 { 487 return fText.Length() > 0 ? fText.String() : NULL; 488 } 489 490 491 void 492 NotificationView::SetText(const char *app, const char *title, 493 const char *text, float newMaxWidth) 494 { 495 if (newMaxWidth < 0) 496 newMaxWidth = Bounds().Width() - (kEdgePadding * 2); 497 498 // Delete old lines 499 vline::iterator lIt; 500 for (lIt = fLines.begin(); lIt != fLines.end(); lIt++) 501 delete (*lIt); 502 fLines.clear(); 503 504 fApp = app; 505 fTitle = title; 506 fText = text; 507 508 font_height fh; 509 float fontHeight = 0; 510 float iconRight = kEdgePadding + kEdgePadding; 511 float y = 0; 512 513 if (fBitmap) 514 iconRight += fParent->IconSize(); 515 516 be_bold_font->GetHeight(&fh); 517 fontHeight = fh.leading + fh.descent + fh.ascent; 518 y += fontHeight; 519 520 // Title 521 lineinfo* titleLine = new lineinfo; 522 titleLine->text = fTitle.String(); 523 titleLine->font = be_bold_font; 524 525 if (fParent->Layout() == AllTextRightOfIcon) 526 titleLine->location = BPoint(iconRight, y); 527 else 528 titleLine->location = BPoint(kEdgePadding, y); 529 530 fLines.push_front(titleLine); 531 y += fontHeight; 532 533 // Text 534 const char spacers[] = " \n-\\/"; 535 BString textBuffer = fText; 536 textBuffer.ReplaceAll("\t", " "); 537 const char* _text = textBuffer.String(); 538 539 size_t offset = 0; 540 size_t n = 0; 541 int16 count = 0; 542 int16 length = strlen(_text); 543 int16* spaces = NULL; 544 int16 index = 0; 545 546 lineinfo* tempLine = NULL; 547 548 while ((n = strcspn(_text + offset, spacers)) < (length - offset)) { 549 ++count; 550 offset += n + 1; 551 } 552 553 spaces = (int16*)calloc(count, sizeof(int16)); 554 offset = 0; 555 556 while ((n = strcspn(_text + offset, spacers)) < (length - offset)) { 557 spaces[index++] = n + offset; 558 offset += n + 1; 559 } 560 561 offset = 0; 562 float maxWidth = newMaxWidth - kEdgePadding - iconRight; 563 bool wasNewline = false; 564 565 for (int32 i = 0; i < count; i++) { 566 if (_text[spaces[i]] == '\n') { 567 lineinfo *tempLine = new lineinfo; 568 tempLine->text = ""; 569 tempLine->text.Append(_text + offset, spaces[i] - offset); 570 wasNewline = true; 571 tempLine->font = be_plain_font; 572 tempLine->location = BPoint(iconRight + kEdgePadding, y); 573 y += fontHeight; 574 575 offset = spaces[i] + 1; 576 577 fLines.push_front(tempLine); 578 } else if ( 579 ((i+1 < count) && (StringWidth(_text + offset, spaces[i+1] - offset) > maxWidth)) || 580 ((i+1 == count) && (StringWidth(_text + offset) > maxWidth)) 581 ) 582 583 tempLine = new lineinfo(); 584 tempLine->font = be_plain_font; 585 if (!wasNewline) 586 tempLine->location = BPoint(iconRight + (kEdgePadding * 2), y); 587 else { 588 tempLine->location = BPoint(iconRight, y); 589 wasNewline = false; 590 } 591 592 y += fontHeight; 593 tempLine->text = ""; 594 tempLine->text.Append(_text + offset, spaces[i] - offset); 595 596 // Strip first space 597 if ((tempLine->text.String())[0] == ' ') 598 tempLine->text.RemoveFirst(" "); 599 600 fLines.push_front(tempLine); 601 602 offset = spaces[i]; 603 } 604 605 tempLine = new lineinfo(); 606 tempLine->text = ""; 607 tempLine->text.Append(_text + offset, strlen(_text) - offset); 608 tempLine->font = be_plain_font; 609 if (wasNewline) 610 tempLine->location = BPoint(iconRight, y); 611 else 612 tempLine->location = BPoint(iconRight + (kEdgePadding * 2), y); 613 614 // Strip first space 615 if ((tempLine->text.String())[0] == ' ') 616 tempLine->text.RemoveFirst(" "); 617 618 free(spaces); 619 620 fLines.push_front(tempLine); 621 622 fHeight = y + (kEdgePadding * 2); 623 624 // Make sure icon fits 625 if (fBitmap) { 626 lineinfo* appLine = fLines.back(); 627 font_height fh; 628 appLine->font.GetHeight( &fh ); 629 630 float title_bottom = fLines.back()->location.y + fh.descent; 631 632 if (fParent->Layout() == TitleAboveIcon) { 633 if (fHeight < title_bottom + fBitmap->Bounds().Height() + 2 * kEdgePadding) 634 fHeight = title_bottom + fBitmap->Bounds().Height() + 2 * kEdgePadding; 635 } else { 636 if (fHeight < fBitmap->Bounds().Height() + kEdgePadding * 2) 637 fHeight = fBitmap->Bounds().Height() + kEdgePadding * 2; 638 } 639 } 640 641 BMessenger msgr(Parent()); 642 msgr.SendMessage(kResizeToFit); 643 } 644 645 646 bool 647 NotificationView::HasMessageID(const char* id) 648 { 649 return fMessageID == id; 650 } 651 652 653 const char* 654 NotificationView::MessageID() 655 { 656 return fMessageID.String(); 657 } 658 659 660 void 661 NotificationView::SetPosition(bool first, bool last) 662 { 663 fIsFirst = first; 664 fIsLast = last; 665 } 666 667 668 BBitmap* 669 NotificationView::_ReadNodeIcon(const char* fileName, icon_size size) 670 { 671 BEntry entry(fileName, true); 672 673 entry_ref ref; 674 entry.GetRef(&ref); 675 676 BNode node(BPath(&ref).Path()); 677 678 BBitmap* ret = new BBitmap(BRect(0, 0, (float)size - 1, (float)size - 1), B_RGBA32); 679 if (BIconUtils::GetIcon(&node, kIconAttribute, kSmallIconAttribute, 680 kLargeIconAttribute, size, ret) != B_OK) { 681 delete ret; 682 ret = NULL; 683 } 684 685 return ret; 686 } 687 688 void 689 NotificationView::_LoadIcon() 690 { 691 // First try to get the icon from the caller application 692 app_info info; 693 BMessenger msgr = fDetails->ReturnAddress(); 694 695 if (msgr.IsValid()) 696 be_roster->GetRunningAppInfo(msgr.Team(), &info); 697 else if (fType == B_PROGRESS_NOTIFICATION) 698 be_roster->GetAppInfo("application/x-vnd.Haiku-notification_server", 699 &info); 700 701 BPath path; 702 path.SetTo(&info.ref); 703 704 fBitmap = _ReadNodeIcon(path.Path(), fParent->IconSize()); 705 if (fBitmap) 706 return; 707 708 // If that failed get icons from app_server 709 if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) != B_OK) 710 return; 711 712 path.Append("app_server"); 713 714 BFile file(path.Path(), B_READ_ONLY); 715 if (file.InitCheck() != B_OK) 716 return; 717 718 BResources res(&file); 719 if (res.InitCheck() != B_OK) 720 return; 721 722 // Which one should we choose? 723 const char* iconName = ""; 724 switch (fType) { 725 case B_INFORMATION_NOTIFICATION: 726 iconName = "info"; 727 break; 728 case B_ERROR_NOTIFICATION: 729 iconName = "stop"; 730 break; 731 case B_IMPORTANT_NOTIFICATION: 732 iconName = "warn"; 733 break; 734 default: 735 return; 736 } 737 738 // Allocate the bitmap 739 fBitmap = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1, 740 (float)B_LARGE_ICON - 1), B_RGBA32); 741 if (!fBitmap || fBitmap->InitCheck() != B_OK) { 742 fBitmap = NULL; 743 return; 744 } 745 746 // Load raw icon data 747 size_t size = 0; 748 const uint8* data = (const uint8*)res.LoadResource(B_VECTOR_ICON_TYPE, 749 iconName, &size); 750 if ((data == NULL 751 || BIconUtils::GetVectorIcon(data, size, fBitmap) != B_OK)) 752 fBitmap = NULL; 753 } -
new file src/servers/notification/NotificationView.h
diff --git a/src/servers/notification/NotificationView.h b/src/servers/notification/NotificationView.h new file mode 100644 index 0000000..283b24d
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 */ 8 #ifndef _NOTIFICATION_VIEW_H 9 #define _NOTIFICATION_VIEW_H 10 11 #include <list> 12 13 #include <Bitmap.h> 14 #include <Entry.h> 15 #include <Message.h> 16 #include <MessageRunner.h> 17 #include <MimeType.h> 18 #include <Notification.h> 19 #include <Path.h> 20 #include <Roster.h> 21 #include <String.h> 22 #include <TextView.h> 23 #include <View.h> 24 25 class NotificationWindow; 26 27 typedef struct line_struct { 28 BFont font; 29 BString text; 30 BPoint location; 31 } lineinfo; 32 33 typedef std::list<lineinfo*> vline; 34 35 const uint32 kRemoveView = 'ReVi'; 36 37 class NotificationView : public BView { 38 public: 39 NotificationView(NotificationWindow* win, notification_type type, 40 const char* app, const char* title, 41 const char* text, BMessage* details); 42 ~NotificationView(); 43 44 virtual void AttachedToWindow(); 45 virtual void MessageReceived(BMessage *msg); 46 virtual void GetPreferredSize(float* width, float* height); 47 virtual void Draw(BRect updateRect); 48 virtual void MouseDown(BPoint point); 49 virtual void FrameResized(float width, float height); 50 51 virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index, 52 BMessage* spec, int32 form, const char* prop); 53 virtual status_t GetSupportedSuites(BMessage* msg); 54 55 const char* Application() const; 56 const char* Title() const; 57 const char* Text() const; 58 59 void SetText(const char* app, const char* title, 60 const char* text, float newMaxWidth = -1); 61 bool HasMessageID(const char* id); 62 const char* MessageID(); 63 void SetPosition(bool first, bool last); 64 65 private: 66 NotificationWindow* fParent; 67 68 notification_type fType; 69 BMessageRunner* fRunner; 70 float fProgress; 71 BString fMessageID; 72 73 BMessage* fDetails; 74 BBitmap* fBitmap; 75 76 vline fLines; 77 78 BString fApp; 79 BString fTitle; 80 BString fText; 81 82 float fHeight; 83 84 bool fIsFirst; 85 bool fIsLast; 86 87 BBitmap* _ReadNodeIcon(const char* fileName, icon_size size); 88 void _LoadIcon(); 89 }; 90 91 #endif // _NOTIFICATION_VIEW_H -
new file src/servers/notification/NotificationWindow.cpp
diff --git a/src/servers/notification/NotificationWindow.cpp b/src/servers/notification/NotificationWindow.cpp new file mode 100644 index 0000000..74b54be
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 * 8 * Authors: 9 * Michael Davidson, slaad@bong.com.au 10 * Mikael Eiman, mikael@eiman.tv 11 * Pier Luigi Fiorini, pierluigi.fiorini@gmail.com 12 */ 13 14 #include <algorithm> 15 16 #include <Alert.h> 17 #include <Application.h> 18 #include <Debug.h> 19 #include <File.h> 20 #include <NodeMonitor.h> 21 #include <PropertyInfo.h> 22 23 #include "AppGroupView.h" 24 #include "AppUsage.h" 25 #include "BorderView.h" 26 #include "NotificationWindow.h" 27 28 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 34 }; 35 36 const float kCloseSize = 8; 37 const float kExpandSize = 8; 38 const float kPenSize = 1; 39 const float kEdgePadding = 5; 40 const float kSmallPadding = 2; 41 42 43 NotificationWindow::NotificationWindow() 44 : 45 BWindow(BRect(10, 10, 30, 30), "Notification", B_BORDERED_WINDOW, 46 B_AVOID_FRONT | B_AVOID_FOCUS | B_NOT_CLOSABLE | B_NOT_ZOOMABLE 47 | B_NOT_MINIMIZABLE | B_NOT_RESIZABLE, B_ALL_WORKSPACES) 48 { 49 fBorder = new BorderView(Bounds(), "Notification"); 50 51 AddChild(fBorder); 52 53 Show(); 54 Hide(); 55 56 LoadSettings(true); 57 LoadAppFilters(true); 58 } 59 60 61 NotificationWindow::~NotificationWindow() 62 { 63 appfilter_t::iterator aIt; 64 for (aIt = fAppFilters.begin(); aIt != fAppFilters.end(); aIt++) 65 delete aIt->second; 66 } 67 68 69 bool 70 NotificationWindow::QuitRequested() 71 { 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(); 80 } 81 82 83 void 84 NotificationWindow::WorkspaceActivated(int32 /*workspace*/, bool active) 85 { 86 // Ensure window is in the correct position 87 if (active) 88 ResizeAll(); 89 } 90 91 92 void 93 NotificationWindow::MessageReceived(BMessage* message) 94 { 95 switch (message->what) { 96 case B_NODE_MONITOR: 97 { 98 LoadSettings(); 99 LoadAppFilters(); 100 break; 101 } 102 case kResizeToFit: 103 ResizeAll(); 104 break; 105 case B_COUNT_PROPERTIES: 106 { 107 BMessage reply(B_REPLY); 108 BMessage specifier; 109 const char* property = NULL; 110 bool messageOkay = true; 111 112 if (message->FindMessage("specifiers", 0, &specifier) != B_OK) 113 messageOkay = false; 114 if (specifier.FindString("property", &property) != B_OK) 115 messageOkay = false; 116 if (strcmp(property, "message") != 0) 117 messageOkay = false; 118 119 if (messageOkay) 120 reply.AddInt32("result", fViews.size()); 121 else { 122 reply.what = B_MESSAGE_NOT_UNDERSTOOD; 123 reply.AddInt32("error", B_ERROR); 124 } 125 126 message->SendReply(&reply); 127 break; 128 } 129 case B_CREATE_PROPERTY: 130 case kNotificationMessage: 131 { 132 int32 type; 133 const char* content = NULL; 134 const char* title = NULL; 135 const char* app = NULL; 136 BMessage reply(B_REPLY); 137 bool messageOkay = true; 138 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; 147 148 if (messageOkay) { 149 NotificationView* view = new NotificationView(this, (notification_type)type, app, 150 title, content, new BMessage(*message)); 151 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); 161 162 AppUsage* appUsage = new AppUsage(info.ref, app, true); 163 fAppFilters[app] = appUsage; 164 165 appUsage->Allowed(title, (notification_type)type); 166 167 allow = true; 168 } else 169 allow = fIt->second->Allowed(title, (notification_type)type); 170 171 if (allow) { 172 appview_t::iterator aIt = fAppViews.find(app); 173 AppGroupView *group = NULL; 174 if (aIt == fAppViews.end()) { 175 group = new AppGroupView(this, app); 176 fAppViews[app] = group; 177 fBorder->AddChild(group); 178 } else { 179 group = aIt->second; 180 }; 181 group->AddInfo(view); 182 183 ResizeAll(); 184 185 reply.AddInt32("error", B_OK); 186 } else 187 reply.AddInt32("Error", B_ERROR); 188 } else { 189 reply.what = B_MESSAGE_NOT_UNDERSTOOD; 190 reply.AddInt32("error", B_ERROR); 191 } 192 193 message->SendReply(&reply); 194 break; 195 } 196 case kRemoveView: 197 { 198 void* _ptr; 199 message->FindPointer("view", &_ptr); 200 201 NotificationView* info 202 = reinterpret_cast<NotificationView*>(_ptr); 203 204 fBorder->RemoveChild(info); 205 206 std::vector<NotificationView*>::iterator i 207 = find(fViews.begin(), fViews.end(), info); 208 if (i != fViews.end()) 209 fViews.erase(i); 210 211 delete info; 212 213 ResizeAll(); 214 break; 215 } 216 default: 217 BWindow::MessageReceived(message); 218 } 219 } 220 221 222 BHandler* 223 NotificationWindow::ResolveSpecifier(BMessage *msg, int32 index, 224 BMessage *spec, int32 form, const char *prop) 225 { 226 BPropertyInfo prop_info(main_prop_list); 227 BHandler* handler = NULL; 228 229 if (strcmp(prop,"message") == 0) { 230 switch (msg->what) { 231 case B_CREATE_PROPERTY: 232 { 233 msg->PopSpecifier(); 234 handler = this; 235 break; 236 } 237 case B_SET_PROPERTY: 238 case B_GET_PROPERTY: 239 { 240 int32 i; 241 242 if (spec->FindInt32("index", &i) != B_OK) 243 i = -1; 244 245 if (i >= 0 && i < (int32)fViews.size()) { 246 msg->PopSpecifier(); 247 handler = fViews[i]; 248 } else 249 handler = NULL; 250 break; 251 } 252 case B_COUNT_PROPERTIES: 253 msg->PopSpecifier(); 254 handler = this; 255 break; 256 default: 257 break; 258 } 259 } 260 261 if (!handler) 262 handler = BWindow::ResolveSpecifier(msg, index, spec, form, prop); 263 264 return handler; 265 } 266 267 268 icon_size 269 NotificationWindow::IconSize() 270 { 271 return fIconSize; 272 } 273 274 275 int32 276 NotificationWindow::Timeout() 277 { 278 return fTimeout; 279 } 280 281 282 283 infoview_layout 284 NotificationWindow::Layout() 285 { 286 return fLayout; 287 } 288 289 290 float 291 NotificationWindow::ViewWidth() 292 { 293 return fWidth; 294 } 295 296 297 void 298 NotificationWindow::ResizeAll() 299 { 300 if (fAppViews.empty()) { 301 if (!IsHidden()) 302 Hide(); 303 return; 304 } 305 306 appview_t::iterator aIt; 307 bool shouldHide = true; 308 309 for (aIt = fAppViews.begin(); aIt != fAppViews.end(); aIt++) { 310 AppGroupView *app = aIt->second; 311 if (app->HasChildren()) { 312 shouldHide = false; 313 break; 314 } 315 } 316 317 if (shouldHide) { 318 if (!IsHidden()) 319 Hide(); 320 return; 321 } 322 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()); 353 } 354 355 356 void 357 NotificationWindow::PopupAnimation(float width, float height) 358 { 359 float x = 0, y = 0, sx, sy; 360 float pad = 0; 361 BDeskbar deskbar; 362 BRect frame = deskbar.Frame(); 363 364 switch (deskbar.Location()) { 365 case B_DESKBAR_TOP: 366 // Put it just under, top right corner 367 sx = frame.right; 368 sy = frame.bottom+pad; 369 y = sy; 370 x = sx-width-pad; 371 break; 372 case B_DESKBAR_BOTTOM: 373 // Put it just above, lower left corner 374 sx = frame.right; 375 sy = frame.top-height-pad; 376 y = sy; 377 x = sx - width-pad; 378 break; 379 case B_DESKBAR_LEFT_TOP: 380 // Put it just to the right of the deskbar 381 sx = frame.right+pad; 382 sy = frame.top-height; 383 x = sx; 384 y = frame.top+pad; 385 break; 386 case B_DESKBAR_RIGHT_TOP: 387 // Put it just to the left of the deskbar 388 sx = frame.left-width-pad; 389 sy = frame.top-height; 390 x = sx; 391 y = frame.top+pad; 392 break; 393 case B_DESKBAR_LEFT_BOTTOM: 394 // Put it to the right of the deskbar. 395 sx = frame.right+pad; 396 sy = frame.bottom; 397 x = sx; 398 y = sy-height-pad; 399 break; 400 case B_DESKBAR_RIGHT_BOTTOM: 401 // Put it to the left of the deskbar. 402 sx = frame.left-width-pad; 403 sy = frame.bottom; 404 y = sy-height-pad; 405 x = sx; 406 break; 407 default: 408 break; 409 } 410 411 MoveTo(x, y); 412 413 if (IsHidden() && fViews.size() != 0) 414 Show(); 415 //Activate();// it hides floaters from apps :-( 416 } 417 418 419 void 420 NotificationWindow::LoadSettings(bool startMonitor) 421 { 422 _LoadGeneralSettings(startMonitor); 423 _LoadDisplaySettings(startMonitor); 424 } 425 426 427 void 428 NotificationWindow::LoadAppFilters(bool startMonitor) 429 { 430 BPath path; 431 432 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 433 return; 434 435 path.Append(kSettingsDirectory); 436 437 if (create_directory(path.Path(), 0755) != B_OK) 438 return; 439 440 path.Append(kFiltersSettings); 441 442 BFile file(path.Path(), B_READ_ONLY); 443 BMessage settings; 444 if (settings.Unflatten(&file) != B_OK) 445 return; 446 447 type_code type; 448 int32 count = 0; 449 450 if (settings.GetInfo("app_usage", &type, &count) != B_OK) 451 return; 452 453 for (int32 i = 0; i < count; i++) { 454 AppUsage* app = new AppUsage(); 455 settings.FindFlat("app_usage", i, app); 456 fAppFilters[app->Name()] = app; 457 } 458 459 if (startMonitor) { 460 node_ref nref; 461 BEntry entry(path.Path()); 462 entry.GetNodeRef(&nref); 463 464 if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) { 465 BAlert* alert = new BAlert("", "Couldn't start filter " 466 " monitor. Live filter changes disabled.", "Darn."); 467 alert->Go(); 468 } 469 } 470 } 471 472 473 void 474 NotificationWindow::SaveAppFilters() 475 { 476 BPath path; 477 478 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 479 return; 480 481 path.Append(kSettingsDirectory); 482 path.Append(kFiltersSettings); 483 484 BMessage settings; 485 BFile file(path.Path(), B_WRITE_ONLY); 486 487 appfilter_t::iterator fIt; 488 for (fIt = fAppFilters.begin(); fIt != fAppFilters.end(); fIt++) 489 settings.AddFlat("app_usage", fIt->second); 490 491 settings.Flatten(&file); 492 } 493 494 495 void 496 NotificationWindow::_LoadGeneralSettings(bool startMonitor) 497 { 498 BPath path; 499 BMessage settings; 500 501 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 502 return; 503 504 path.Append(kSettingsDirectory); 505 if (create_directory(path.Path(), 0755) == B_OK) { 506 path.Append(kGeneralSettings); 507 508 BFile file(path.Path(), B_READ_ONLY); 509 settings.Unflatten(&file); 510 } 511 512 if (settings.FindInt32(kTimeoutName, &fTimeout) != B_OK) 513 fTimeout = kDefaultTimeout; 514 515 // Notify the view about the change 516 views_t::iterator it; 517 for (it = fViews.begin(); it != fViews.end(); ++it) { 518 NotificationView* view = (*it); 519 view->SetText(view->Application(), view->Title(), view->Text()); 520 view->Invalidate(); 521 } 522 523 if (startMonitor) { 524 node_ref nref; 525 BEntry entry(path.Path()); 526 entry.GetNodeRef(&nref); 527 528 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"); 531 alert->Go(); 532 } 533 } 534 } 535 536 537 void 538 NotificationWindow::_LoadDisplaySettings(bool startMonitor) 539 { 540 BPath path; 541 BMessage settings; 542 543 if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) 544 return; 545 546 path.Append(kSettingsDirectory); 547 if (create_directory(path.Path(), 0755) == B_OK) { 548 path.Append(kDisplaySettings); 549 550 BFile file(path.Path(), B_READ_ONLY); 551 settings.Unflatten(&file); 552 } 553 554 int32 setting; 555 556 if (settings.FindFloat(kWidthName, &fWidth) != B_OK) 557 fWidth = kDefaultWidth; 558 559 if (settings.FindInt32(kIconSizeName, &setting) != B_OK) 560 fIconSize = kDefaultIconSize; 561 else 562 fIconSize = (icon_size)setting; 563 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 // Notify the view about the change 580 views_t::iterator it; 581 for (it = fViews.begin(); it != fViews.end(); ++it) { 582 NotificationView* view = (*it); 583 view->SetText(view->Application(), view->Title(), view->Text()); 584 view->Invalidate(); 585 } 586 587 if (startMonitor) { 588 node_ref nref; 589 BEntry entry(path.Path()); 590 entry.GetNodeRef(&nref); 591 592 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"); 595 alert->Go(); 596 } 597 } 598 } -
new file src/servers/notification/NotificationWindow.h
diff --git a/src/servers/notification/NotificationWindow.h b/src/servers/notification/NotificationWindow.h new file mode 100644 index 0000000..a246f7e
- + 1 /* 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. 6 * Distributed under the terms of the MIT License. 7 */ 8 #ifndef _NOTIFICATION_WINDOW_H 9 #define _NOTIFICATION_WINDOW_H 10 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 15 #include <Directory.h> 16 #include <Deskbar.h> 17 #include <Entry.h> 18 #include <FindDirectory.h> 19 #include <Message.h> 20 #include <Notifications.h> 21 #include <PropertyInfo.h> 22 #include <String.h> 23 #include <Window.h> 24 25 #include "NotificationView.h" 26 27 class AppGroupView; 28 class AppUsage; 29 class BorderView; 30 class SettingsFile; 31 32 typedef std::map<BString, AppGroupView*> appview_t; 33 typedef std::map<BString, AppUsage*> appfilter_t; 34 typedef std::vector<NotificationView*> views_t; 35 36 extern const float kEdgePadding; 37 extern const float kSmallPadding; 38 extern const float kCloseSize; 39 extern const float kExpandSize; 40 extern const float kPenSize; 41 42 const uint32 kResizeToFit = 'IWrf'; 43 44 class NotificationWindow : public BWindow { 45 public: 46 NotificationWindow(); 47 virtual ~NotificationWindow(); 48 49 virtual bool QuitRequested(); 50 virtual void MessageReceived(BMessage*); 51 virtual void WorkspaceActivated(int32, bool); 52 virtual BHandler* ResolveSpecifier(BMessage*, int32, BMessage*, 53 int32, const char*); 54 55 icon_size IconSize(); 56 int32 Timeout(); 57 infoview_layout Layout(); 58 float ViewWidth(); 59 60 void ResizeAll(); 61 62 private: 63 friend class AppGroupView; 64 65 void PopupAnimation(float, float); 66 void LoadSettings(bool startMonitor = false); 67 void LoadAppFilters(bool startMonitor = false); 68 void SaveAppFilters(); 69 void _LoadGeneralSettings(bool startMonitor); 70 void _LoadDisplaySettings(bool startMonitor); 71 72 views_t fViews; 73 BorderView* fBorder; 74 75 appview_t fAppViews; 76 77 BString fStatusText; 78 BString fMessageText; 79 80 float fWidth; 81 icon_size fIconSize; 82 int32 fTimeout; 83 infoview_layout fLayout; 84 85 appfilter_t fAppFilters; 86 }; 87 88 extern property_info main_prop_list[]; 89 90 #endif // _NOTIFICATION_WINDOW_H -
new file src/servers/notification/notification_server.rdef
diff --git a/src/servers/notification/notification_server.rdef b/src/servers/notification/notification_server.rdef new file mode 100644 index 0000000..feeaf4a
- + 1 2 resource app_signature "application/x-vnd.Haiku-notification_server"; 3 4 resource app_flags B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP; 5 6 resource app_version { 7 major = 1, 8 middle = 0, 9 minor = 0, 10 11 variety = B_APPV_ALPHA, 12 internal = 0, 13 14 short_info = "notification_server", 15 long_info = "notification_server ©2010 Haiku Inc." 16 }; 17 18 resource vector_icon { 19 $"6E6369661201B0AEB6330200160734E2E73823CEB823CE34E2E74AE8E44C3C6C" 20 $"000020054715732EA251D37EE38F03B89B9B0200160734000B36F73FB6F73F34" 21 $"000B4AF7984C1AC8000020054715732EA251D37EE38F039F9FAA0200160730F6" 22 $"C6343295B4329530F6C64B14D64C04C5000020054715732EA251D37EE38F0200" 23 $"16073104ED343D08B43D083104ED4B14734C02F8000020054715732EA251D37E" 24 $"E38F039F9FBD020116023C322F0000000000003C322F4B471E4AA0B10000FF8F" 25 $"0500020116073C263B0000000000003C263B4AA2864A01D4000020054715732E" 26 $"A251D37EE38F039997AE0312031903B0AEB603292F3D0200160736FA5E3A3533" 27 $"BA353336FA5E4945B24A4CD9000020054715732EA251D37EE38F039B9C9F0400" 28 $"19140204CAC5CED7CAC5CE14CAC5CF99BF00D037CB4CD062B85FD02020CED720" 29 $"CF9920CE14BF00CD76B85FCD76C5A0CD76060B7FF413CACFCF60CACFCF60CACF" 30 $"CF5FCAD0CF5CCAD0CF5DCAD0CF5ACACFCF57CACFCF58CACFCF57CE42C3A0CF66" 31 $"C3A2CF66C3A2CF66C3B8CFDAC738D037C54AD037C926D037CACECF66CAB8CFDA" 32 $"CACECF66CACFCF600204C738CD66C535CD66C93BCD66CAD0CE42CAD0CDC7CAD0" 33 $"CEBDC738CF1DC93BCF1DC535CF1DC3A0CE42C3A0CEBDC3A0CDC7060847FFC914" 34 $"CDEAC914CDECC914CDEACCCCC514CDEBC515CDEBC515CDEBC515CDEDC514CDF1" 35 $"C514CDEFC514CE31C714CE65C5F9CE65C830CE65C915CDF1C915CE31C915CDEF" 36 $"0204C714CC50C5F5CC50C833CC50C915CCC4C915CC83C915CD05C714CD39C833" 37 $"CD39C5F5CD39C514CCC4C514CD05C514CC830204C714CC51C668CC51C7C0CC51" 38 $"C848CC97C848CC70C848CCBEC714CCDCC7C0CCDCC668CCDCC5E1CC97C5E1CCBE" 39 $"C5E1CC700A04C5E1CC67C847CC67C847CC97C5E1CC970204C714CC26C668CC26" 40 $"C7C0CC26C848CC6BC848CC44C848CC92C714CCB1C7C0CCB1C668CCB1C5E1CC6B" 41 $"C5E1CC92C5E1CC440611FEFFEDFF02C394BADFC73EBD9CC613BD06C869BE32CB" 42 $"07BFE3CA26BF02CBE7C0C3CC45C2CFCC45C20ACC45C394CB56C5A4CC23C4D7CA" 43 $"89C671CA0BC6CFCAD0C651C946C74DC82EC865C8A0C7A4C7BCC926C77DCBC4C7" 44 $"7DCA4AC77DCD3ECC61C70CCC7DC762CC7DC6B6CC7DC6A8CC61C681C926C681C9" 45 $"F3C681C859C77DC6DFC6FBC761C7FFC65DC9E4C394CA37C503C991C22AC852C2" 46 $"A8C8F7C271C7ACC2DFC56DC42AC61A4AC4C0C498C385C56D0204C2A9B8AAC14F" 47 $"B8AAC403B8AAC513BFF8C513BBE1C513C40FC2A9C746C403C746C14FC746C03F" 48 $"BFF8C03FC40FC03FBBE10204C298B8E9C15BB8E9C3D6B8E9C4D0BFF8C4D0BC04" 49 $"C4D0C3ECC298C706C3D6C706C15BC706C061BFF8C061C3ECC061BC040607FF3E" 50 $"CAFCC32ACB30C35DCAFCC32ACA65C4DBCAF7C449C9D4C56DC936C5F5C990C5AB" 51 $"C8DBC640C80EC6FEC864C680C7D3C754C77DC875C90BC698C7FCC73EC9A2C63B" 52 $"CB36C4BCCB04C529CB86C40D0205C517C3A4C517C369C517C3A4C817C271C78A" 53 $"C29EC8A8C242C9EBC27CC938C1F7CA40C2BCCA3EC1E7CAADC23EC9BAC17EC6E7" 54 $"C23DC87AC199C5B8C2BA0608FEFAC26DB961C2EBBA45C29CB9CFC33ABABBC41A" 55 $"BCDBC3EFBAB7C446BEFEC3F7C39CC4A0C0FEC34EC63AC30BC67DC31EC690C491" 56 $"BE5DC4FFC3D7C43DBA33C2D7B95DC379B994C236B9260205C186BD52C1BABCA9" 57 $"C186BD52C14BC116C12ABF53C16CC2D9C254C45BC1CAC46BC2DDC44BC2DDC2AC" 58 $"C33FC335C27BC222C1B3C0E5C1B3C1EEC1B3BFDD0205C0EFBD9CC12EBCE8C0EF" 59 $"BD9CC0A8C19DC081BFBEC0CFC37CC1E7C516C142C528C28DC505C28DC34CC303" 60 $"C3DEC216C2BAC126C169C126C282C126C0500205C2B8C588C2D2C5A2C2B8C588" 61 $"C252C68CC252C655C252C6C3C2A4C6D7C281C6D7C2C8C6D7C2F9C6A6C316C6C3" 62 $"C2DBC688C2ACC680C2ACC6A4C2ACC65D0207B7C920B7C920B8BD20B8BDB4A4B8" 63 $"C8B393B8BDB4A4B857BC43B857BC43B84BBD0AB735BDAFB81EBDAFB64CBDAFB6" 64 $"13BC43B61EBD0AB613BC43B5ACB4A4B5ACB4A4B59BB393B6A720B5B220B6A720" 65 $"0208B77FC12CB77FC12CB857C12CB8BDC270B8BDC198B8BDC270B8BDC304B8BD" 66 $"C304B8BDC3DCB77FC448B857C448B77FC448B6EBC448B6EBC448B613C448B5AC" 67 $"C304B5ACC3DCB5ACC304B5ACC270B5ACC270B5ACC198B6EBC12CB613C12CB6EB" 68 $"C12C0204B72ACD68B577CD68B8DDCD68BA33CDE5BA33CD9FBA33CE2CB72ACE63" 69 $"B8DDCE63B577CE63B421CDE5B421CE2CB421CD9F130A00010002400000000000" 70 $"0000003F71070000003D00000A010101024000000000000000003F7107000000" 71 $"3D00000A020102024000000000000000003F71070000003D00000A0301030240" 72 $"00000000000000003F71070000003D00000A040104024000000000000000003F" 73 $"71070000003D00000A050105024000000000000000003F71070000003D00000A" 74 $"060106024000000000000000003F71070000003D00000A070107024000000000" 75 $"000000003F71070000003D00000A080108024000000000000000003F71070000" 76 $"003D00000A090109024000000000000000003F71070000003D00000A0A010A02" 77 $"4000000000000000003F71070000003D00000A0B010B02400000000000000000" 78 $"3F71070000003D00000A0C010C024000000000000000003F71070000003D0000" 79 $"0A0D010D024000000000000000003F71070000003D00000A0E010E0240000000" 80 $"00000000003F71070000003D00000A0F010F024000000000000000003F710700" 81 $"00003D00000A100110024000000000000000003F71070000003D00000A090211" 82 $"12024000000000000000003F71070000003D00000A1101130240000000000000" 83 $"00003F71070000003D0000" 84 };