Merge patch by plfiorini :

Some changes to the API for notifications.
	* Don't go through be_roster to send a notification, but use Notification->Send() instead.
	* Rename App to Group to make the purpose clearer

And some changes to the notification code itself:
	* Use the Notification class as the way to convey informations about a notification. Allows easier extension of this class
	* Code cleanup
	* Use of the layout kit for the notify window

Unfortunately, the latter part clashes quite a bit with the changes I already did to the notification window, so it's now quite broken. Working on that next, but I wanted to separate that work from the patch ...


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43114 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adrien Destugues 2011-11-02 14:57:43 +00:00
parent 561696cbfc
commit 4ec6c3a042
19 changed files with 321 additions and 785 deletions

View File

@ -6,6 +6,7 @@
#define _NOTIFICATION_H
#include <Archivable.h>
#include <Entry.h>
#include <List.h>
#include <String.h>
@ -22,15 +23,21 @@ enum notification_type {
class BBitmap;
class BNotification {
class BNotification : public BArchivable {
public:
BNotification(notification_type type);
~BNotification();
BNotification(BMessage* archive);
virtual ~BNotification();
status_t InitCheck() const;
static BArchivable* Instantiate(BMessage* archive);
virtual status_t Archive(BMessage* archive, bool deep = true) const;
notification_type Type() const;
const char* Application() const;
void SetApplication(const BString& app);
const char* Group() const;
void SetGroup(const BString& group);
const char* Title() const;
void SetTitle(const BString& title);
@ -61,9 +68,13 @@ public:
const BBitmap* Icon() const;
status_t SetIcon(const BBitmap* icon);
status_t Send(bigtime_t timeout = -1);
private:
status_t fInitStatus;
notification_type fType;
BString fAppName;
BString fGroup;
BString fTitle;
BString fContent;
BString fID;

View File

@ -13,7 +13,6 @@
class BFile;
class BMimeType;
class BNodeInfo;
class BNotification;
struct app_info {
@ -117,10 +116,6 @@ class BRoster {
void AddToRecentFolders(const entry_ref *folder,
const char *appSig = 0) const;
// notifications
status_t Notify(const BNotification& notification,
bigtime_t timeout = -1) const;
// private/reserved stuff starts here
class Private;

View File

@ -28,15 +28,6 @@ typedef enum {
} b_mail_status_window_option;
typedef enum {
B_MAIL_STATUS_LOOK_TITLED = 0,
B_MAIL_STATUS_LOOK_NORMAL_BORDER = 1,
B_MAIL_STATUS_LOOK_FLOATING = 2,
B_MAIL_STATUS_LOOK_THIN_BORDER = 3,
B_MAIL_STATUS_LOOK_NO_BORDER = 4
} b_mail_status_window_look;
class BMailSettings {
public:
BMailSettings();

View File

@ -10,7 +10,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Application.h>
#include <Bitmap.h>
@ -19,7 +18,6 @@
#include <Mime.h>
#include <Notification.h>
#include <Path.h>
#include <Roster.h>
#include <TranslationUtils.h>
const char* kSignature = "application/x-vnd.Haiku-notify";
@ -52,15 +50,15 @@ public:
private:
bool fHasGoodArguments;
notification_type fType;
char* fAppName;
char* fTitle;
char* fMsgId;
BString fGroup;
BString fTitle;
BString fMsgId;
float fProgress;
bigtime_t fTimeout;
char* fIconFile;
BString fIconFile;
entry_ref fFileRef;
char* fMessage;
char* fApp;
BString fContent;
BString fOnClickApp;
bool fHasFile;
entry_ref fFile;
BList* fRefs;
@ -76,14 +74,8 @@ NotifyApp::NotifyApp()
BApplication(kSignature),
fHasGoodArguments(false),
fType(B_INFORMATION_NOTIFICATION),
fAppName(NULL),
fTitle(NULL),
fMsgId(NULL),
fProgress(0.0f),
fTimeout(0),
fIconFile(NULL),
fMessage(NULL),
fApp(NULL),
fTimeout(-1),
fHasFile(false)
{
fRefs = new BList();
@ -93,19 +85,12 @@ NotifyApp::NotifyApp()
NotifyApp::~NotifyApp()
{
free(fAppName);
free(fTitle);
free(fMsgId);
free(fIconFile);
free(fMessage);
free(fApp);
for (int32 i = 0; void* item = fRefs->ItemAt(i); i++)
delete (BEntry*)item;
delete fRefs;
for (int32 i = 0; void* item = fArgv->ItemAt(i); i++)
free(item);
delete (BString*)item;
delete fArgv;
}
@ -134,25 +119,25 @@ NotifyApp::ArgvReceived(int32 argc, char** argv)
if (strncmp(kTypeNames[i], argument, strlen(argument)) == 0)
fType = (notification_type)i;
}
} else if (strcmp(option, "app") == 0)
fAppName = strdup(argument);
} else if (strcmp(option, "group") == 0)
fGroup = argument;
else if (strcmp(option, "title") == 0)
fTitle = strdup(argument);
fTitle = argument;
else if (strcmp(option, "messageID") == 0)
fMsgId = strdup(argument);
fMsgId = argument;
else if (strcmp(option, "progress") == 0)
fProgress = atof(argument);
else if (strcmp(option, "timeout") == 0)
fTimeout = atol(argument) * 1000000;
else if (strcmp(option, "icon") == 0) {
fIconFile = strdup(argument);
fIconFile = argument;
if (get_ref_for_path(fIconFile, &fFileRef) < B_OK) {
if (get_ref_for_path(fIconFile.String(), &fFileRef) < B_OK) {
fprintf(stderr, "Bad icon path!\n\n");
return;
}
} else if (strcmp(option, "onClickApp") == 0)
fApp = strdup(argument);
fOnClickApp = argument;
else if (strcmp(option, "onClickFile") == 0) {
if (get_ref_for_path(argument, &fFile) != B_OK) {
fprintf(stderr, "Bad path for --onClickFile!\n\n");
@ -170,7 +155,7 @@ NotifyApp::ArgvReceived(int32 argc, char** argv)
fRefs->AddItem(new BEntry(&ref));
} else if (strcmp(option, "onClickArgv") == 0)
fArgv->AddItem(strdup(argument));
fArgv->AddItem(new BString(argument));
else {
// Unrecognized option
fprintf(stderr, "Unrecognized option --%s\n\n", option);
@ -188,17 +173,7 @@ NotifyApp::ArgvReceived(int32 argc, char** argv)
}
}
// Check for missing arguments
if (fAppName == NULL) {
fprintf(stderr, "Missing --app argument!\n\n");
return;
}
if (fTitle == NULL) {
fprintf(stderr, "Missing --title argument!\n\n");
return;
}
fMessage = strdup(argv[index]);
fContent = argv[index];
fHasGoodArguments = true;
}
@ -208,13 +183,13 @@ NotifyApp::_Usage() const
fprintf(stderr, "Usage: notify [OPTION]... [MESSAGE]\n"
"Send notifications to notification_server.\n"
" --type <type>\tNotification type,\n"
" \t <type>: ");
" \t <type> - \"information\" is assumed by default: ");
for (int32 i = 0; kTypeNames[i]; i++)
fprintf(stderr, kTypeNames[i + 1] ? "%s|" : "%s\n", kTypeNames[i]);
fprintf(stderr,
" --app <app name>\tApplication name\n"
" --group <group>\tGroup\n"
" --title <title>\tMessage title\n"
" --messageID <msg id>\tMessage ID\n"
" --progress <float>\tProgress, value between 0.0 and 1.0 - if type is set to progress\n"
@ -256,17 +231,20 @@ NotifyApp::ReadyToRun()
{
if (HasGoodArguments()) {
BNotification notification(fType);
notification.SetApplication(fAppName);
notification.SetTitle(fTitle);
notification.SetContent(fMessage);
if (fGroup != "")
notification.SetGroup(fGroup);
if (fTitle != "")
notification.SetTitle(fTitle);
if (fContent != "")
notification.SetContent(fContent);
if (fMsgId != NULL)
if (fMsgId != "")
notification.SetMessageID(fMsgId);
if (fType == B_PROGRESS_NOTIFICATION)
notification.SetProgress(fProgress);
if (fIconFile != NULL) {
if (fIconFile != "") {
BBitmap* bitmap = _GetBitmap(&fFileRef);
if (bitmap) {
notification.SetIcon(bitmap);
@ -274,8 +252,8 @@ NotifyApp::ReadyToRun()
}
}
if (fApp != NULL)
notification.SetOnClickApp(fApp);
if (fOnClickApp != "")
notification.SetOnClickApp(fOnClickApp);
if (fHasFile)
notification.SetOnClickFile(&fFile);
@ -289,11 +267,11 @@ NotifyApp::ReadyToRun()
}
for (int32 i = 0; void* item = fArgv->ItemAt(i); i++) {
const char* arg = (const char*)item;
notification.AddOnClickArg(arg);
BString* arg = (BString*)item;
notification.AddOnClickArg(arg->String());
}
status_t ret = be_roster->Notify(notification, fTimeout);
status_t ret = notification.Send(fTimeout);
if (ret != B_OK) {
fprintf(stderr, "Failed to deliver notification: %s\n",
strerror(ret));

View File

@ -27,9 +27,8 @@ AppUsage::AppUsage()
}
AppUsage::AppUsage(entry_ref ref, const char* name, bool allow)
AppUsage::AppUsage(const char* name, bool allow)
:
fRef(ref),
fName(name),
fAllow(allow)
{
@ -38,7 +37,7 @@ AppUsage::AppUsage(entry_ref ref, const char* name, bool allow)
AppUsage::~AppUsage()
{
notify_t::iterator nIt;
notification_t::iterator nIt;
for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
delete nIt->second;
}
@ -55,13 +54,12 @@ status_t
AppUsage::Flatten(void* buffer, ssize_t numBytes) const
{
BMessage msg;
msg.AddString("app_name", fName);
msg.AddRef("app_ref", &fRef);
msg.AddBool("app_allow", fAllow);
msg.AddString("signature", fName);
msg.AddBool("allow", fAllow);
notify_t::const_iterator nIt;
notification_t::const_iterator nIt;
for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
msg.AddFlat("notify", nIt->second);
msg.AddFlat("notification", nIt->second);
if (numBytes < msg.FlattenedSize())
return B_ERROR;
@ -74,13 +72,12 @@ ssize_t
AppUsage::FlattenedSize() const
{
BMessage msg;
msg.AddString("app_name", fName);
msg.AddRef("app_ref", &fRef);
msg.AddBool("app_allow", fAllow);
msg.AddString("signature", fName);
msg.AddBool("allow", fAllow);
notify_t::const_iterator nIt;
notification_t::const_iterator nIt;
for (nIt = fNotifications.begin(); nIt != fNotifications.end(); nIt++)
msg.AddFlat("notify", nIt->second);
msg.AddFlat("notification", nIt->second);
return msg.FlattenedSize();
}
@ -113,21 +110,20 @@ AppUsage::Unflatten(type_code code, const void* buffer,
status = msg.Unflatten((const char*)buffer);
if (status == B_OK) {
msg.FindString("app_name", &fName);
msg.FindRef("app_ref", &fRef);
msg.FindBool("app_allow", &fAllow);
msg.FindString("signature", &fName);
msg.FindBool("allow", &fAllow);
type_code type;
int32 count = 0;
status = msg.GetInfo("notify", &type, &count);
status = msg.GetInfo("notification", &type, &count);
if (status != B_OK)
return status;
for (int32 i = 0; i < count; i++) {
NotificationReceived *notify = new NotificationReceived();
msg.FindFlat("notify", i, notify);
fNotifications[notify->Title()] = notify;
NotificationReceived *notification = new NotificationReceived();
msg.FindFlat("notification", i, notification);
fNotifications[notification->Title()] = notification;
}
status = B_OK;
@ -137,13 +133,6 @@ AppUsage::Unflatten(type_code code, const void* buffer,
}
entry_ref
AppUsage::Ref()
{
return fRef;
}
const char*
AppUsage::Name()
{
@ -157,7 +146,7 @@ AppUsage::Allowed(const char* title, notification_type type)
bool allowed = fAllow;
if (allowed) {
notify_t::iterator nIt = fNotifications.find(title);
notification_t::iterator nIt = fNotifications.find(title);
if (nIt == fNotifications.end()) {
allowed = true;
fNotifications[title] = new NotificationReceived(title, type);
@ -182,7 +171,7 @@ AppUsage::Allowed()
NotificationReceived*
AppUsage::NotificationAt(int32 index)
{
notify_t::iterator nIt = fNotifications.begin();
notification_t::iterator nIt = fNotifications.begin();
for (int32 i = 0; i < index; i++)
nIt++;

View File

@ -20,5 +20,3 @@ const char* kTimeoutName = "timeout";
// Display settings
const char* kWidthName = "width";
const char* kIconSizeName = "icon size";
const char* kLayoutName = "layout";

View File

@ -191,7 +191,7 @@ MailDaemonApp::ReadyToRun()
fCentralBeep = false;
fNotification = new BNotification(B_INFORMATION_NOTIFICATION);
fNotification->SetApplication(B_TRANSLATE("Mail status"));
fNotification->SetGroup(B_TRANSLATE("Mail status"));
fNotification->SetTitle(string);
fNotification->SetMessageID("daemon_status");
@ -390,7 +390,7 @@ MailDaemonApp::MessageReceived(BMessage* msg)
fNotification->SetTitle(string.String());
if (fNotifyMode != B_MAIL_SHOW_STATUS_WINDOW_NEVER)
be_roster->Notify(*fNotification);
fNotification->Send();
break;
}

View File

@ -42,7 +42,7 @@ DefaultNotifier::DefaultNotifier(const char* accountName, bool inbound,
// Two windows for each acocunt : one for sending and the other for
// receiving mails
fNotification.SetMessageID(identifier);
fNotification.SetApplication(B_TRANSLATE("Mail Status"));
fNotification.SetGroup(B_TRANSLATE("Mail Status"));
fNotification.SetTitle(desc);
app_info info;
@ -127,7 +127,7 @@ DefaultNotifier::ReportProgress(int bytes, int messages, const char* message)
if ((!fIsInbound && fShowMode | B_MAIL_SHOW_STATUS_WINDOW_WHEN_SENDING)
|| (fIsInbound && fShowMode | B_MAIL_SHOW_STATUS_WINDOW_WHEN_ACTIVE))
be_roster->Notify(fNotification, timeout);
fNotification.Send(timeout);
}
@ -137,5 +137,5 @@ DefaultNotifier::ResetProgress(const char* message)
fNotification.SetProgress(0);
if (message != NULL)
fNotification.SetTitle(message);
be_roster->Notify(fNotification, 0);
fNotification.Send(0);
}

View File

@ -13,6 +13,9 @@
#include <algorithm>
#include <GroupLayout.h>
#include <GroupView.h>
#include "AppGroupView.h"
#include "NotificationWindow.h"
@ -21,13 +24,16 @@
AppGroupView::AppGroupView(NotificationWindow* win, const char* label)
:
BView(BRect(0, 0, win->ViewWidth(), 1), label, B_FOLLOW_LEFT_RIGHT,
B_WILL_DRAW|B_FULL_UPDATE_ON_RESIZE|B_FRAME_EVENTS),
BBox(B_FANCY_BORDER, (fView = new BGroupView(B_VERTICAL, 10))),
fLabel(label),
fParent(win),
fCollapsed(false)
{
Show();
// If no group was specified we don't have any border or label
if (label == NULL)
SetBorder(B_NO_BORDER);
else
SetLabel(label);
}
@ -36,6 +42,7 @@ AppGroupView::~AppGroupView()
}
/*
void
AppGroupView::AttachedToWindow()
{
@ -43,8 +50,9 @@ AppGroupView::AttachedToWindow()
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
}
*/
/*
void
AppGroupView::Draw(BRect updateRect)
{
@ -120,7 +128,7 @@ AppGroupView::Draw(BRect updateRect)
Sync();
}
*/
void
AppGroupView::MouseDown(BPoint point)
@ -131,7 +139,7 @@ AppGroupView::MouseDown(BPoint point)
int32 children = fInfo.size();
for (int32 i = 0; i < children; i++) {
fInfo[i]->RemoveSelf();
fView->GetLayout()->RemoveView(fInfo[i]);
delete fInfo[i];
}
fInfo.clear();
@ -143,41 +151,11 @@ AppGroupView::MouseDown(BPoint point)
}
if (changed) {
ResizeViews();
Invalidate();
_ResizeViews();
}
}
void
AppGroupView::GetPreferredSize(float* width, float* height)
{
font_height fh;
be_bold_font->GetHeight(&fh);
float h = fh.ascent + fh.leading + fh.leading;
h += kEdgePadding * 2; // Padding between top and bottom of label
if (!fCollapsed) {
int32 children = fInfo.size();
for (int32 i = 0; i < children; i++) {
float childHeight = 0;
float childWidth = 0;
fInfo[i]->GetPreferredSize(&childWidth, &childHeight);
h += childHeight;
}
}
h += kEdgePadding;
*width = fParent->ViewWidth();
*height = h;
}
void
AppGroupView::MessageReceived(BMessage* msg)
{
@ -192,16 +170,14 @@ AppGroupView::MessageReceived(BMessage* msg)
if (vIt != fInfo.end()) {
fInfo.erase(vIt);
view->RemoveSelf();
fView->GetLayout()->RemoveView(view);
delete view;
}
ResizeViews();
Invalidate();
if (Window() != NULL)
Window()->PostMessage(msg);
// When all the views are destroy, save app filters
if (fInfo.size() == 0)
dynamic_cast<NotificationWindow*>(Window())->SaveAppFilters();
_ResizeViews();
break;
}
default:
@ -214,13 +190,14 @@ void
AppGroupView::AddInfo(NotificationView* view)
{
BString id = view->MessageID();
bool found = false;
if (id.Length() > 0) {
int32 children = fInfo.size();
bool found = false;
for (int32 i = 0; i < children; i++) {
if (fInfo[i]->HasMessageID(id.String())) {
fInfo[i]->RemoveSelf();
if (id == fInfo[i]->MessageID()) {
fView->GetLayout()->RemoveView(fInfo[i]);
delete fInfo[i];
fInfo[i] = view;
@ -229,28 +206,23 @@ AppGroupView::AddInfo(NotificationView* view)
break;
}
}
}
if (!found)
fInfo.push_back(view);
} else
if (!found)
fInfo.push_back(view);
fView->GetLayout()->AddView(view);
if (fParent->IsHidden())
fParent->Show();
if (IsHidden())
Show();
if (view->IsHidden())
view->Show();
AddChild(view);
ResizeViews();
Invalidate();
_ResizeViews();
}
void
AppGroupView::ResizeViews()
AppGroupView::_ResizeViews()
{
font_height fh;
be_bold_font->GetHeight(&fh);
@ -268,22 +240,14 @@ AppGroupView::ResizeViews()
offset += fInfo[i]->Bounds().Height();
if (fInfo[i]->IsHidden())
fInfo[i]->Show();
fInfo[i]->SetPosition(false, false);
};
}
} else {
for (int32 i = 0; i < children; i++)
if (!fInfo[i]->IsHidden())
fInfo[i]->Hide();
}
if (children == 1)
fInfo[0]->SetPosition(true, true);
else if (children > 1) {
fInfo[0]->SetPosition(true, false);
fInfo[children - 1]->SetPosition(false, true);
}
ResizeTo(fParent->ViewWidth(), offset);
ResizeTo(fParent->Width(), offset);
float labelOffset = fh.ascent + fh.leading;
BRect borderRect = Bounds().InsetByCopy(kEdgePadding, kEdgePadding);
@ -299,8 +263,6 @@ AppGroupView::ResizeViews()
fCloseRect.top += kEdgePadding * 1.5;
fCloseRect.left = fCloseRect.right - kCloseSize;
fCloseRect.bottom = fCloseRect.top + kCloseSize;
fParent->ResizeAll();
}

View File

@ -1,50 +1,47 @@
/*
* Copyright 2005-2008, Mikael Eiman.
* Copyright 2005-2008, Michael Davidson.
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Mikael Eiman <mikael@eiman.tv>
* Michael Davidson <slaad@bong.com.au>
*/
#ifndef APPGROUPVIEW_H
#define APPGROUPVIEW_H
#ifndef _APP_GROUP_VIEW_H
#define _APP_GROUP_VIEW_H
#include <vector>
#include <Box.h>
#include <String.h>
#include <View.h>
class BGroupView;
class NotificationWindow;
class NotificationView;
typedef std::vector<NotificationView *> infoview_t;
typedef std::vector<NotificationView*> infoview_t;
class AppGroupView : public BView {
public:
AppGroupView(NotificationWindow *win, const char *label);
~AppGroupView(void);
// Hooks
void AttachedToWindow(void);
void Draw(BRect bounds);
void MouseDown(BPoint point);
void GetPreferredSize(float *width, float *height);
void MessageReceived(BMessage *msg);
// Public
void AddInfo(NotificationView *view);
void ResizeViews(void);
bool HasChildren(void);
private:
BString fLabel;
NotificationWindow *fParent;
infoview_t fInfo;
bool fCollapsed;
BRect fCloseRect;
BRect fCollapseRect;
class AppGroupView : public BBox {
public:
AppGroupView(NotificationWindow* win, const char* label);
~AppGroupView();
virtual void MouseDown(BPoint point);
virtual void MessageReceived(BMessage* msg);
bool HasChildren();
void AddInfo(NotificationView* view);
private:
void _ResizeViews();
BString fLabel;
NotificationWindow* fParent;
BGroupView* fView;
infoview_t fInfo;
bool fCollapsed;
BRect fCloseRect;
BRect fCollapseRect;
};
#endif
#endif // _APP_GROUP_VIEW_H

View File

@ -1,114 +0,0 @@
/*
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Davidson, slaad@bong.com.au
* Mikael Eiman, mikael@eiman.tv
* Pier Luigi Fiorini, pierluigi.fiorini@gmail.com
*/
#include "BorderView.h"
const float kBorderWidth = 2.0f;
const int32 kTitleSize = 14;
BorderView::BorderView(BRect rect, const char* text)
:
BView(rect, "NotificationBorderView", B_FOLLOW_ALL,
B_WILL_DRAW | B_FRAME_EVENTS),
fTitle(text)
{
SetViewColor(B_TRANSPARENT_COLOR);
}
BorderView::~BorderView()
{
}
void
BorderView::FrameResized(float, float)
{
Invalidate();
}
void
BorderView::Draw(BRect rect)
{
rgb_color col_bg = ui_color(B_PANEL_BACKGROUND_COLOR);
rgb_color col_text = tint_color(col_bg, B_LIGHTEN_MAX_TINT);
rgb_color col_text_shadow = tint_color(col_bg, B_DARKEN_MAX_TINT);
// Background
SetDrawingMode(B_OP_COPY);
SetHighColor(col_bg);
FillRect(rect);
// Text
SetLowColor(col_bg);
SetDrawingMode(B_OP_ALPHA);
SetFont(be_bold_font);
SetFontSize(kTitleSize);
BFont font;
GetFont(&font);
font_height fh;
font.GetHeight(&fh);
// float line_height = fh.ascent + fh.descent + fh.leading;
float text_pos = fh.ascent;
SetHighColor(col_text);
DrawString(fTitle.String(), BPoint(kBorderWidth, text_pos));
SetHighColor(col_text_shadow);
DrawString(fTitle.String(), BPoint(kBorderWidth + 1, text_pos + 1));
// Content border
SetHighColor(tint_color(col_bg, B_DARKEN_2_TINT));
BRect content = Bounds();
// content.InsetBy(kBorderWidth, kBorderWidth);
content.top += text_pos + fh.descent + 2;
BRect content_line(content);
// content_line.InsetBy(-1, -1);
StrokeRect(content_line);
}
void
BorderView::GetPreferredSize(float* w, float* h)
{
SetFont(be_bold_font);
SetFontSize(kTitleSize);
BFont font;
GetFont(&font);
font_height fh;
font.GetHeight(&fh);
float line_height = fh.ascent + fh.descent;
*w = 2 * kBorderWidth + StringWidth(fTitle.String());
*h = 2 * kBorderWidth + line_height + 3;
*w = *h = 0;
}
float
BorderView::BorderSize()
{
return 0;
}

View File

@ -1,31 +0,0 @@
/*
* Copyright 2010, Haiku, Inc. All Rights Reserved.
* Copyright 2008-2009, Pier Luigi Fiorini. All Rights Reserved.
* Copyright 2004-2008, Michael Davidson. All Rights Reserved.
* Copyright 2004-2007, Mikael Eiman. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _BORDER_VIEW_H
#define _BORDER_VIEW_H
#include <View.h>
#include <String.h>
class BorderView : public BView {
public:
BorderView(BRect, const char*);
virtual ~BorderView();
virtual void Draw(BRect updateRect);
virtual void GetPreferredSize(float*, float*);
virtual void FrameResized(float, float);
float BorderSize();
private:
BString fTitle;
};
#endif // _BORDER_VIEW_H

View File

@ -4,11 +4,10 @@ UsePrivateHeaders notification ;
Server notification_server :
AppGroupView.cpp
BorderView.cpp
NotificationServer.cpp
NotificationView.cpp
NotificationWindow.cpp
: be $(TARGET_LIBSTDC++) libicon.a libnotification.a $(HAIKU_LOCALE_LIBS)
: be translation $(TARGET_LIBSTDC++) libnotification.a $(HAIKU_LOCALE_LIBS)
: notification_server.rdef
;
@ -20,5 +19,4 @@ DoCatalogs notification_server :
NotificationWindow.cpp
;
Depends notification_server : libicon.a ;
Depends notification_server : libnotification.a ;

View File

@ -24,7 +24,6 @@ const char* kSoundNames[] = {
NotificationServer::NotificationServer()
: BApplication(kNotificationServerSignature)
{
fWindow = new NotificationWindow();
}
@ -33,6 +32,13 @@ NotificationServer::~NotificationServer()
}
void
NotificationServer::ReadyToRun()
{
fWindow = new NotificationWindow();
}
void
NotificationServer::MessageReceived(BMessage* message)
{
@ -61,17 +67,6 @@ NotificationServer::MessageReceived(BMessage* message)
}
bool
NotificationServer::QuitRequested()
{
if (fWindow && fWindow->Lock()) {
fWindow->Quit();
fWindow = NULL;
}
return true;
}
status_t
NotificationServer::GetSupportedSuites(BMessage* msg)
{
@ -110,8 +105,8 @@ main(int argc, char* argv[])
add_system_beep_event(kSoundNames[i++], 0);
// Start!
NotificationServer* server = new NotificationServer();
server->Run();
NotificationServer server;
server.Run();
return 0;
}

View File

@ -14,8 +14,8 @@ public:
NotificationServer();
virtual ~NotificationServer();
virtual void ReadyToRun();
virtual void MessageReceived(BMessage* message);
virtual bool QuitRequested();
virtual status_t GetSupportedSuites(BMessage* msg);
virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,

View File

@ -13,28 +13,16 @@
* Adrien Destugues <pulkomandy@pulkomandy.ath.cx>
*/
#include <stdlib.h>
#include <ControlLook.h>
#include <Font.h>
#include <IconUtils.h>
#include <LayoutUtils.h>
#include <Messenger.h>
#include <Picture.h>
#include <PropertyInfo.h>
#include <Region.h>
#include <Resources.h>
#include <Path.h>
#include <Roster.h>
#include <StatusBar.h>
#include <StringView.h>
#include <TranslationUtils.h>
#include "NotificationView.h"
#include "NotificationWindow.h"
const char* kSmallIconAttribute = "BEOS:M:STD_ICON";
const char* kLargeIconAttribute = "BEOS:L:STD_ICON";
const char* kIconAttribute = "BEOS:ICON";
static const int kIconStripeWidth = 32;
property_info message_prop_list[] = {
@ -55,46 +43,25 @@ property_info message_prop_list[] = {
NotificationView::NotificationView(NotificationWindow* win,
notification_type type, const char* app, const char* title, const char* text,
BMessage* details)
BNotification* notification, bigtime_t timeout)
:
BView(BRect(0, 0, win->ViewWidth(), 1), "NotificationView",
B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
BView("NotificationView", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
| B_FRAME_EVENTS),
fParent(win),
fType(type),
fNotification(notification),
fTimeout(timeout),
fRunner(NULL),
fProgress(0.0f),
fMessageID(""),
fDetails(details),
fBitmap(NULL),
fIsFirst(false),
fIsLast(false)
fBitmap(NULL)
{
BMessage iconMsg;
if (fDetails->FindMessage("icon", &iconMsg) == B_OK)
fBitmap = new BBitmap(&iconMsg);
if (fNotification->Icon() != NULL)
fBitmap = new BBitmap(fNotification->Icon());
if (!fBitmap)
_LoadIcon();
if (fTimeout <= 0)
fTimeout = fParent->Timeout() * 1000000;
const char* messageID = NULL;
if (fDetails->FindString("messageID", &messageID) == B_OK)
fMessageID = messageID;
SetText();
if (fDetails->FindFloat("progress", &fProgress) != B_OK)
fProgress = 0.0f;
// Progress is between 0 and 1
if (fProgress < 0.0f)
fProgress = 0.0f;
if (fProgress > 1.0f)
fProgress = 1.0f;
SetText(app, title, text);
ResizeToPreferred();
switch (type) {
switch (fNotification->Type()) {
case B_IMPORTANT_NOTIFICATION:
SetViewColor(255, 255, 255);
SetLowColor(255, 255, 255);
@ -110,18 +77,18 @@ NotificationView::NotificationView(NotificationWindow* win,
BStatusBar* progress = new BStatusBar(frame, "progress");
progress->SetBarHeight(12.0f);
progress->SetMaxValue(1.0f);
progress->Update(fProgress);
progress->Update(fNotification->Progress());
BString label = "";
label << (int)(fProgress * 100) << " %";
label << (int)(fNotification->Progress() * 100) << " %";
progress->SetTrailingText(label);
AddChild(progress);
}
// fall through
default:
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
break;
}
}
@ -129,8 +96,8 @@ NotificationView::NotificationView(NotificationWindow* win,
NotificationView::~NotificationView()
{
delete fRunner;
delete fDetails;
delete fBitmap;
delete fNotification;
LineInfoList::iterator lIt;
for (lIt = fLines.begin(); lIt != fLines.end(); lIt++)
@ -143,13 +110,8 @@ NotificationView::AttachedToWindow()
{
BMessage msg(kRemoveView);
msg.AddPointer("view", this);
bigtime_t timeout = -1;
if (fDetails->FindInt64("timeout", &timeout) != B_OK)
timeout = fParent->Timeout() * 1000000;
if (timeout > 0)
fRunner = new BMessageRunner(BMessenger(Parent()), &msg, timeout, 1);
fRunner = new BMessageRunner(BMessenger(Parent()), &msg, fTimeout, 1);
}
@ -171,19 +133,19 @@ NotificationView::MessageReceived(BMessage* msg)
if (msgOkay) {
if (strcmp(property, "type") == 0)
reply.AddInt32("result", fType);
reply.AddInt32("result", fNotification->Type());
if (strcmp(property, "app") == 0)
reply.AddString("result", fApp);
if (strcmp(property, "group") == 0)
reply.AddString("result", fNotification->Group());
if (strcmp(property, "title") == 0)
reply.AddString("result", fTitle);
reply.AddString("result", fNotification->Title());
if (strcmp(property, "content") == 0)
reply.AddString("result", fText);
reply.AddString("result", fNotification->Content());
if (strcmp(property, "progress") == 0)
reply.AddFloat("result", fProgress);
reply.AddFloat("result", fNotification->Progress());
if ((strcmp(property, "icon") == 0) && fBitmap) {
BMessage archive;
@ -213,14 +175,19 @@ NotificationView::MessageReceived(BMessage* msg)
msgOkay = false;
if (msgOkay) {
if (strcmp(property, "app") == 0)
msg->FindString("data", &fApp);
const char* value = NULL;
if (strcmp(property, "group") == 0)
if (msg->FindString("data", &value) == B_OK)
fNotification->SetGroup(value);
if (strcmp(property, "title") == 0)
msg->FindString("data", &fTitle);
if (msg->FindString("data", &value) == B_OK)
fNotification->SetTitle(value);
if (strcmp(property, "content") == 0)
msg->FindString("data", &fText);
if (msg->FindString("data", &value) == B_OK)
fNotification->SetContent(value);
if (strcmp(property, "icon") == 0) {
BMessage archive;
@ -230,7 +197,7 @@ NotificationView::MessageReceived(BMessage* msg)
}
}
SetText(Application(), Title(), Text());
SetText();
Invalidate();
reply.AddInt32("error", B_OK);
@ -242,33 +209,12 @@ NotificationView::MessageReceived(BMessage* msg)
msg->SendReply(&reply);
break;
}
case kRemoveView:
{
BMessage remove(kRemoveView);
remove.AddPointer("view", this);
BMessenger msgr(Window());
msgr.SendMessage( &remove );
break;
}
default:
BView::MessageReceived(msg);
}
}
void
NotificationView::GetPreferredSize(float* w, float* h)
{
*w = fParent->ViewWidth();
*h = fHeight;
if (fType == B_PROGRESS_NOTIFICATION) {
*h += 16 + kEdgePadding;
// 16 is progress bar default size as stated in the BeBook
}
}
void
NotificationView::Draw(BRect updateRect)
{
@ -295,7 +241,7 @@ NotificationView::Draw(BRect updateRect)
float iy = (Bounds().Height() - iconSize) / 4.0;
// Icon is vertically centered in view
if (fType == B_PROGRESS_NOTIFICATION)
if (fNotification->Type() == B_PROGRESS_NOTIFICATION)
{
// Move icon up by half progress bar height if it's present
iy -= (progRect.Height() + kEdgePadding);
@ -363,46 +309,44 @@ NotificationView::MouseDown(BPoint point)
BList messages;
entry_ref ref;
if (fDetails->FindString("onClickApp", &launchString) == B_OK)
if (be_roster->FindApp(launchString.String(), &appRef) == B_OK)
useArgv = true;
if (fDetails->FindRef("onClickFile", &launchRef) == B_OK) {
if (be_roster->FindApp(&launchRef, &appRef) == B_OK)
useArgv = true;
if (fNotification->OnClickApp() != NULL
&& be_roster->FindApp(fNotification->OnClickApp(), &appRef)
== B_OK) {
useArgv = true;
}
if (fDetails->FindRef("onClickRef", &ref) == B_OK) {
for (int32 i = 0; fDetails->FindRef("onClickRef", i, &ref) == B_OK; i++)
refMsg.AddRef("refs", &ref);
messages.AddItem((void*)&refMsg);
if (fNotification->OnClickFile() != NULL
&& be_roster->FindApp(
(entry_ref*)fNotification->OnClickFile(), &appRef)
== B_OK) {
useArgv = true;
}
for (int32 i = 0; i < fNotification->CountOnClickRefs(); i++)
refMsg.AddRef("refs", fNotification->OnClickRefAt(i));
messages.AddItem((void*)&refMsg);
if (useArgv) {
type_code type;
int32 argc = 0;
int32 argc = fNotification->CountOnClickArgs() + 1;
BString arg;
BPath p(&appRef);
argMsg.AddString("argv", p.Path());
fDetails->GetInfo("onClickArgv", &type, &argc);
argMsg.AddInt32("argc", argc + 1);
argMsg.AddInt32("argc", argc);
for (int32 i = 0; fDetails->FindString("onClickArgv", i, &arg) == B_OK; i++)
argMsg.AddString("argv", arg);
for (int32 i = 0; i < argc - 1; i++) {
argMsg.AddString("argv",
fNotification->OnClickArgAt(i));
}
messages.AddItem((void*)&argMsg);
}
BMessage tmp;
for (int32 i = 0; fDetails->FindMessage("onClickMsg", i, &tmp) == B_OK; i++)
messages.AddItem((void*)&tmp);
if (fDetails->FindString("onClickApp", &launchString) == B_OK)
be_roster->Launch(launchString.String(), &messages);
if (fNotification->OnClickApp() != NULL)
be_roster->Launch(fNotification->OnClickApp(), &messages);
else
be_roster->Launch(&launchRef, &messages);
be_roster->Launch(fNotification->OnClickFile(), &messages);
}
// Remove the info view after a click
@ -417,15 +361,31 @@ NotificationView::MouseDown(BPoint point)
}
void
NotificationView::FrameResized( float w, float /*h*/)
BSize
NotificationView::MinSize()
{
SetText(Application(), Title(), Text());
return BLayoutUtils::ComposeSize(ExplicitMinSize(), _CalculateSize());
}
BSize
NotificationView::MaxSize()
{
return BLayoutUtils::ComposeSize(ExplicitMaxSize(), _CalculateSize());
}
BSize
NotificationView::PreferredSize()
{
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
_CalculateSize());
}
BHandler*
NotificationView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec, int32 form, const char* prop)
NotificationView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* spec,
int32 form, const char* prop)
{
BPropertyInfo prop_info(message_prop_list);
if (prop_info.FindMatch(msg, index, spec, form, prop) >= 0) {
@ -447,30 +407,8 @@ NotificationView::GetSupportedSuites(BMessage* msg)
}
const char*
NotificationView::Application() const
{
return fApp.Length() > 0 ? fApp.String() : NULL;
}
const char*
NotificationView::Title() const
{
return fTitle.Length() > 0 ? fTitle.String() : NULL;
}
const char*
NotificationView::Text() const
{
return fText.Length() > 0 ? fText.String() : NULL;
}
void
NotificationView::SetText(const char* app, const char* title, const char* text,
float newMaxWidth)
NotificationView::SetText(float newMaxWidth)
{
if (newMaxWidth < 0)
newMaxWidth = Bounds().Width() - (kEdgePadding * 2);
@ -481,10 +419,6 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
delete (*lIt);
fLines.clear();
fApp = app;
fTitle = title;
fText = text;
float iconRight = kIconStripeWidth;
if (fBitmap != NULL)
iconRight += fParent->IconSize();
@ -499,7 +433,7 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
// Title
LineInfo* titleLine = new LineInfo;
titleLine->text = fTitle;
titleLine->text = fNotification->Title();
titleLine->font = *be_bold_font;
titleLine->location = BPoint(iconRight, y);
@ -514,7 +448,7 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
// Split text into chunks between certain characters and compose the lines.
const char kSeparatorCharacters[] = " \n-\\/";
BString textBuffer = fText;
BString textBuffer = fNotification->Content();
textBuffer.ReplaceAll("\t", " ");
const char* chunkStart = textBuffer.String();
float maxWidth = newMaxWidth - kEdgePadding - iconRight;
@ -523,8 +457,7 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
while (chunkStart - textBuffer.String() < length) {
size_t chunkLength = strcspn(chunkStart, kSeparatorCharacters) + 1;
// Start a new line if either we didn't start one before,
// the current offset
// Start a new line if we didn't start one before
BString tempText;
if (line != NULL)
tempText.SetTo(line->text);
@ -539,20 +472,21 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
fLines.push_front(line);
y += fontHeight;
// Skip the eventual new-line character at the beginning of this
// chunk.
// Skip the eventual new-line character at the beginning of this chunk
if (chunkStart[0] == '\n') {
chunkStart++;
chunkLength--;
}
// Skip more new-line characters and move the line further down.
// Skip more new-line characters and move the line further down
while (chunkStart[0] == '\n') {
chunkStart++;
chunkLength--;
line->location.y += fontHeight;
y += fontHeight;
}
// Strip space at beginning of a new line.
// Strip space at beginning of a new line
while (chunkStart[0] == ' ') {
chunkLength--;
chunkStart++;
@ -563,7 +497,7 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
break;
// Append the chunk to the current line, which was either a new
// line or the one from the previous iteration.
// line or the one from the previous iteration
line->text.Append(chunkStart, chunkLength);
chunkStart += chunkLength;
@ -573,130 +507,36 @@ NotificationView::SetText(const char* app, const char* title, const char* text,
// Make sure icon fits
if (fBitmap != NULL) {
float minHeight = 0;
if (fParent->Layout() == TitleAboveIcon) {
LineInfo* appLine = fLines.back();
font_height fh;
appLine->font.GetHeight(&fh);
minHeight = appLine->location.y + fh.descent;
}
float minHeight = fBitmap->Bounds().Height() + 2 * kEdgePadding;
minHeight += fBitmap->Bounds().Height() + 2 * kEdgePadding;
if (fHeight < minHeight)
fHeight = minHeight;
}
BMessenger messenger(Parent());
messenger.SendMessage(kResizeToFit);
}
bool
NotificationView::HasMessageID(const char* id)
{
return fMessageID == id;
}
const char*
NotificationView::MessageID()
NotificationView::MessageID() const
{
return fMessageID.String();
return fNotification->MessageID();
}
void
NotificationView::SetPosition(bool first, bool last)
BSize
NotificationView::_CalculateSize()
{
fIsFirst = first;
fIsLast = last;
}
BSize size;
// Parent width, minus the edge padding, minus the pensize
size.width = fParent->Width() - (kEdgePadding * 2) - (kPenSize * 2);
size.height = fHeight;
BBitmap*
NotificationView::_ReadNodeIcon(const char* fileName, icon_size size)
{
BEntry entry(fileName, true);
entry_ref ref;
entry.GetRef(&ref);
BNode node(BPath(&ref).Path());
BBitmap* ret = new BBitmap(BRect(0, 0, (float)size - 1, (float)size - 1), B_RGBA32);
if (BIconUtils::GetIcon(&node, kIconAttribute, kSmallIconAttribute,
kLargeIconAttribute, size, ret) != B_OK) {
delete ret;
ret = NULL;
if (fNotification->Type() == B_PROGRESS_NOTIFICATION) {
font_height fh;
be_plain_font->GetHeight(&fh);
float fontHeight = fh.ascent + fh.descent + fh.leading;
size.height += (kSmallPadding * 2) + (kEdgePadding * 1) + fontHeight;
}
return ret;
}
void
NotificationView::_LoadIcon()
{
// First try to get the icon from the caller application
app_info info;
BMessenger msgr = fDetails->ReturnAddress();
if (msgr.IsValid())
be_roster->GetRunningAppInfo(msgr.Team(), &info);
else if (fType == B_PROGRESS_NOTIFICATION)
be_roster->GetAppInfo("application/x-vnd.Haiku-notification_server",
&info);
BPath path;
path.SetTo(&info.ref);
fBitmap = _ReadNodeIcon(path.Path(), fParent->IconSize());
if (fBitmap)
return;
// If that failed get icons from app_server
if (find_directory(B_BEOS_SERVERS_DIRECTORY, &path) != B_OK)
return;
path.Append("app_server");
BFile file(path.Path(), B_READ_ONLY);
if (file.InitCheck() != B_OK)
return;
BResources res(&file);
if (res.InitCheck() != B_OK)
return;
// Which one should we choose?
const char* iconName = "";
switch (fType) {
case B_INFORMATION_NOTIFICATION:
iconName = "info";
break;
case B_ERROR_NOTIFICATION:
iconName = "stop";
break;
case B_IMPORTANT_NOTIFICATION:
iconName = "warn";
break;
default:
return;
}
// Allocate the bitmap
fBitmap = new BBitmap(BRect(0, 0, (float)B_LARGE_ICON - 1,
(float)B_LARGE_ICON - 1), B_RGBA32);
if (!fBitmap || fBitmap->InitCheck() != B_OK) {
fBitmap = NULL;
return;
}
// Load raw icon data
size_t size = 0;
const uint8* data = (const uint8*)res.LoadResource(B_VECTOR_ICON_TYPE,
iconName, &size);
if ((data == NULL
|| BIconUtils::GetVectorIcon(data, size, fBitmap) != B_OK))
fBitmap = NULL;
return size;
}

View File

@ -11,15 +11,8 @@
#include <list>
#include <Bitmap.h>
#include <Entry.h>
#include <Message.h>
#include <MessageRunner.h>
#include <MimeType.h>
#include <Notification.h>
#include <Path.h>
#include <Roster.h>
#include <String.h>
#include <TextView.h>
#include <View.h>
class NotificationWindow;
@ -29,39 +22,31 @@ const uint32 kRemoveView = 'ReVi';
class NotificationView : public BView {
public:
NotificationView(NotificationWindow* win,
notification_type type,
const char* app, const char* title,
const char* text, BMessage* details);
BNotification* notification,
bigtime_t timeout = -1);
virtual ~NotificationView();
virtual void AttachedToWindow();
virtual void MessageReceived(BMessage* message);
virtual void GetPreferredSize(float* width, float* height);
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint point);
virtual void FrameResized(float width, float height);
virtual BSize MinSize();
virtual BSize MaxSize();
virtual BSize PreferredSize();
virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index,
BMessage* specifier, int32 form,
const char* property);
virtual status_t GetSupportedSuites(BMessage* msg);
const char* Application() const;
const char* Title() const;
const char* Text() const;
void SetText(float newMaxWidth = -1);
void SetText(const char* app, const char* title,
const char* text, float newMaxWidth = -1);
bool HasMessageID(const char* id);
const char* MessageID();
void SetPosition(bool first, bool last);
const char* MessageID() const;
private:
BBitmap* _ReadNodeIcon(const char* fileName,
icon_size size);
void _LoadIcon();
BSize _CalculateSize();
private:
struct LineInfo {
BFont font;
BString text;
@ -70,27 +55,17 @@ private:
typedef std::list<LineInfo*> LineInfoList;
NotificationWindow* fParent;
BNotification* fNotification;
bigtime_t fTimeout;
notification_type fType;
BMessageRunner* fRunner;
float fProgress;
BString fMessageID;
BMessage* fDetails;
BBitmap* fBitmap;
LineInfoList fLines;
BString fApp;
BString fTitle;
BString fText;
float fHeight;
bool fIsFirst;
bool fIsLast;
};
#endif // _NOTIFICATION_VIEW_H

View File

@ -19,15 +19,17 @@
#include <Alert.h>
#include <Application.h>
#include <Catalog.h>
#include <Debug.h>
#include <File.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <Layout.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <PropertyInfo.h>
#include <private/interface/WindowPrivate.h>
#include "AppGroupView.h"
#include "AppUsage.h"
#include "BorderView.h"
#undef B_TRANSLATE_CONTEXT
#define B_TRANSLATE_CONTEXT "NotificationWindow"
@ -54,23 +56,19 @@ const float kSmallPadding = 2;
NotificationWindow::NotificationWindow()
:
BWindow(BRect(0, 0, 0, 0), B_TRANSLATE_MARK("Notification"),
BWindow(BRect(0, 0, -1, -1), B_TRANSLATE_MARK("Notification"),
B_BORDERED_WINDOW_LOOK, B_FLOATING_ALL_WINDOW_FEEL, B_AVOID_FRONT
| B_AVOID_FOCUS | B_NOT_CLOSABLE | B_NOT_ZOOMABLE | B_NOT_MINIMIZABLE
| B_NOT_RESIZABLE | B_NOT_MOVABLE,
| B_NOT_RESIZABLE | B_NOT_MOVABLE | B_AUTO_UPDATE_SIZE_LIMITS,
B_ALL_WORKSPACES)
{
fBorder = new BorderView(Bounds(), "Notification");
SetLayout(new BGroupLayout(B_VERTICAL, 10));
AddChild(fBorder);
// Needed so everything gets the right size - we should switch to layout
// mode...
Show();
Hide();
Show();
LoadSettings(true);
LoadAppFilters(true);
_LoadSettings(true);
_LoadAppFilters(true);
}
@ -101,7 +99,7 @@ NotificationWindow::WorkspaceActivated(int32 /*workspace*/, bool active)
{
// Ensure window is in the correct position
if (active)
ResizeAll();
_ResizeAll();
}
@ -111,13 +109,10 @@ NotificationWindow::MessageReceived(BMessage* message)
switch (message->what) {
case B_NODE_MONITOR:
{
LoadSettings();
LoadAppFilters();
_LoadSettings();
_LoadAppFilters();
break;
}
case kResizeToFit:
ResizeAll();
break;
case B_COUNT_PROPERTIES:
{
BMessage reply(B_REPLY);
@ -145,60 +140,55 @@ NotificationWindow::MessageReceived(BMessage* message)
case B_CREATE_PROPERTY:
case kNotificationMessage:
{
int32 type;
const char* content = NULL;
const char* title = NULL;
const char* app = NULL;
BMessage reply(B_REPLY);
bool messageOkay = true;
BNotification* notification = new BNotification(message);
if (message->FindInt32("type", &type) != B_OK)
type = B_INFORMATION_NOTIFICATION;
if (message->FindString("content", &content) != B_OK)
messageOkay = false;
if (message->FindString("title", &title) != B_OK)
messageOkay = false;
if (message->FindString("app", &app) != B_OK
&& message->FindString("appTitle", &app) != B_OK)
messageOkay = false;
if (notification->InitCheck() == B_OK) {
bigtime_t timeout;
if (message->FindInt64("timeout", &timeout) != B_OK)
timeout = -1;
BMessenger messenger = message->ReturnAddress();
app_info info;
if (messenger.IsValid())
be_roster->GetRunningAppInfo(messenger.Team(), &info);
else
be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info);
if (messageOkay) {
NotificationView* view = new NotificationView(this,
(notification_type)type, app, title, content,
new BMessage(*message));
notification, timeout);
appfilter_t::iterator fIt = fAppFilters.find(app);
bool allow = false;
if (fIt == fAppFilters.end()) {
app_info info;
BMessenger messenger = message->ReturnAddress();
if (messenger.IsValid())
be_roster->GetRunningAppInfo(messenger.Team(), &info);
else
be_roster->GetAppInfo("application/x-vnd.Be-SHEL", &info);
appfilter_t::iterator it = fAppFilters.find(info.signature);
AppUsage* appUsage = new AppUsage(info.ref, app, true);
fAppFilters[app] = appUsage;
appUsage->Allowed(title, (notification_type)type);
if (it == fAppFilters.end()) {
AppUsage* appUsage = new AppUsage(notification->Group(),
true);
appUsage->Allowed(notification->Title(),
notification->Type());
fAppFilters[info.signature] = appUsage;
allow = true;
} else
allow = fIt->second->Allowed(title, (notification_type)type);
} else {
allow = it->second->Allowed(notification->Title(),
notification->Type());
}
if (allow) {
appview_t::iterator aIt = fAppViews.find(app);
BString groupName(notification->Group());
appview_t::iterator aIt = fAppViews.find(groupName);
AppGroupView* group = NULL;
if (aIt == fAppViews.end()) {
group = new AppGroupView(this, app);
fAppViews[app] = group;
fBorder->AddChild(group);
group = new AppGroupView(this,
groupName == "" ? NULL : groupName.String());
fAppViews[groupName] = group;
GetLayout()->AddView(group);
} else
group = aIt->second;
group->AddInfo(view);
ResizeAll();
_ResizeAll();
reply.AddInt32("error", B_OK);
} else
@ -213,22 +203,16 @@ NotificationWindow::MessageReceived(BMessage* message)
}
case kRemoveView:
{
void* _ptr;
message->FindPointer("view", &_ptr);
NotificationView* view = NULL;
if (message->FindPointer("view", (void**)&view) != B_OK)
return;
NotificationView* info
= reinterpret_cast<NotificationView*>(_ptr);
views_t::iterator it = find(fViews.begin(), fViews.end(), view);
fBorder->RemoveChild(info);
if (it != fViews.end())
fViews.erase(it);
std::vector<NotificationView*>::iterator i
= find(fViews.begin(), fViews.end(), info);
if (i != fViews.end())
fViews.erase(i);
delete info;
ResizeAll();
_ResizeAll();
break;
}
default:
@ -297,22 +281,15 @@ NotificationWindow::Timeout()
}
infoview_layout
NotificationWindow::Layout()
{
return fLayout;
}
float
NotificationWindow::ViewWidth()
NotificationWindow::Width()
{
return fWidth;
}
void
NotificationWindow::ResizeAll()
NotificationWindow::_ResizeAll()
{
if (fAppViews.empty()) {
if (!IsHidden())
@ -365,7 +342,7 @@ NotificationWindow::ResizeAll()
}
}
ResizeTo(ViewWidth(), height);
ResizeTo(Width(), height);
PopupAnimation();
}
@ -429,14 +406,14 @@ NotificationWindow::PopupAnimation()
{
SetPosition();
if (IsHidden() && fViews.size() != 0)
if (IsHidden())
Show();
// Activate();// it hides floaters from apps :-(
}
void
NotificationWindow::LoadSettings(bool startMonitor)
NotificationWindow::_LoadSettings(bool startMonitor)
{
_LoadGeneralSettings(startMonitor);
_LoadDisplaySettings(startMonitor);
@ -444,7 +421,7 @@ NotificationWindow::LoadSettings(bool startMonitor)
void
NotificationWindow::LoadAppFilters(bool startMonitor)
NotificationWindow::_LoadAppFilters(bool startMonitor)
{
BPath path;
@ -491,7 +468,7 @@ NotificationWindow::LoadAppFilters(bool startMonitor)
void
NotificationWindow::SaveAppFilters()
NotificationWindow::_SaveAppFilters()
{
BPath path;
@ -543,7 +520,6 @@ NotificationWindow::_LoadGeneralSettings(bool startMonitor)
views_t::iterator it;
for (it = fViews.begin(); it != fViews.end(); ++it) {
NotificationView* view = (*it);
view->SetText(view->Application(), view->Title(), view->Text());
view->Invalidate();
}
@ -589,26 +565,10 @@ NotificationWindow::_LoadDisplaySettings(bool startMonitor)
else
fIconSize = (icon_size)setting;
if (settings.FindInt32(kLayoutName, &setting) != B_OK)
fLayout = kDefaultLayout;
else {
switch (setting) {
case 0:
fLayout = TitleAboveIcon;
break;
case 1:
fLayout = AllTextRightOfIcon;
break;
default:
fLayout = kDefaultLayout;
}
}
// Notify the view about the change
views_t::iterator it;
for (it = fViews.begin(); it != fViews.end(); ++it) {
NotificationView* view = (*it);
view->SetText(view->Application(), view->Title(), view->Text());
view->Invalidate();
}

View File

@ -26,8 +26,6 @@
class AppGroupView;
class AppUsage;
class BorderView;
class SettingsFile;
typedef std::map<BString, AppGroupView*> appview_t;
typedef std::map<BString, AppUsage*> appfilter_t;
@ -39,8 +37,6 @@ extern const float kCloseSize;
extern const float kExpandSize;
extern const float kPenSize;
const uint32 kResizeToFit = 'IWrf';
class NotificationWindow : public BWindow {
public:
NotificationWindow();
@ -56,25 +52,22 @@ public:
icon_size IconSize();
int32 Timeout();
infoview_layout Layout();
float ViewWidth();
float Width();
void ResizeAll();
void _ResizeAll();
private:
friend class AppGroupView;
void SetPosition();
void PopupAnimation();
void LoadSettings(bool startMonitor = false);
void LoadAppFilters(bool startMonitor = false);
void SaveAppFilters();
void _LoadSettings(bool startMonitor = false);
void _LoadAppFilters(bool startMonitor = false);
void _SaveAppFilters();
void _LoadGeneralSettings(bool startMonitor);
void _LoadDisplaySettings(bool startMonitor);
views_t fViews;
BorderView* fBorder;
appview_t fAppViews;
BString fStatusText;
@ -83,7 +76,6 @@ private:
float fWidth;
icon_size fIconSize;
int32 fTimeout;
infoview_layout fLayout;
appfilter_t fAppFilters;
};