Even more work on notification window:

* Use the layout kit. That makes the code simpler.
  * Group headers now look like deskbar team entries. I had the answer just under my eyes all the time.
  * Folding and closing a group are back. However, folding does not work yet.
  * We need to select a better default "failure" color, as red looks a bit aggressive.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@43170 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Adrien Destugues 2011-11-03 21:04:41 +00:00
parent 2d980c7f9d
commit 44c6e69bd1
6 changed files with 185 additions and 176 deletions

View File

@ -13,6 +13,7 @@
#include <algorithm>
#include <ControlLook.h>
#include <GroupLayout.h>
#include <GroupView.h>
@ -22,115 +23,140 @@
#include "NotificationView.h"
static const int kHeaderSize = 20;
AppGroupView::AppGroupView(NotificationWindow* win, const char* label)
:
BBox(B_FANCY_BORDER, (fView = new BGroupView(B_VERTICAL, 0))),
BGroupView("appGroup", B_VERTICAL, 0),
fLabel(label),
fParent(win),
fCollapsed(false)
{
// If no group was specified we don't have any border or label
if (label == NULL)
SetBorder(B_NO_BORDER);
else
SetLabel(label);
}
AppGroupView::~AppGroupView()
{
}
/*
void
AppGroupView::AttachedToWindow()
{
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
}
*/
/*
void
AppGroupView::Draw(BRect updateRect)
{
FillRect(Bounds(), B_SOLID_LOW);
BString label = fLabel;
if (fCollapsed)
label << " (" << fInfo.size() << ")";
SetFlags(Flags() | B_WILL_DRAW);
font_height fh;
be_bold_font->GetHeight(&fh);
float labelOffset = fh.ascent + fh.leading;
static_cast<BGroupLayout*>(GetLayout())->SetInsets(0, kHeaderSize, 0, 0);
}
BRect textRect = Bounds();
//textRect.right = textRect.left + be_bold_font->StringWidth(label.String())
// + (kEdgePadding * 3);
textRect.bottom = 2 * labelOffset;
BRect borderRect = Bounds().InsetByCopy(kEdgePadding, kEdgePadding);
borderRect.top = 2 * labelOffset;
void
AppGroupView::Draw(BRect updateRect)
{
rgb_color menuColor = ViewColor();
BRect bounds = Bounds();
rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_TINT);
bounds.bottom = bounds.top + kHeaderSize;
BRect closeCross = fCloseRect;
closeCross.InsetBy(kSmallPadding, kSmallPadding);
// Draw the header background
if (be_control_look != NULL) {
SetHighColor(tint_color(menuColor, 1.22));
StrokeLine(bounds.LeftTop(), bounds.LeftBottom());
uint32 borders = BControlLook::B_TOP_BORDER
| BControlLook::B_BOTTOM_BORDER | BControlLook::B_RIGHT_BORDER;
rgb_color detailCol = ui_color(B_CONTROL_BORDER_COLOR);
detailCol = tint_color(detailCol, B_LIGHTEN_2_TINT);
// detailCol = tint_color(detailCol, B_LIGHTEN_1_TINT);
be_control_look->DrawButtonBackground(this, bounds, bounds, menuColor,
0, borders);
} else {
SetHighColor(vlight);
StrokeLine(bounds.LeftTop(), bounds.RightTop());
StrokeLine(BPoint(bounds.left, bounds.top + 1), bounds.LeftBottom());
SetHighColor(hilite);
StrokeLine(BPoint(bounds.left + 1, bounds.bottom),
bounds.RightBottom());
}
// Draw the buttons
fCollapseRect.top = (kHeaderSize - kExpandSize) / 2;
fCollapseRect.left = kEdgePadding * 2;
fCollapseRect.right = fCollapseRect.left + 1.5 * kExpandSize;
fCollapseRect.bottom = fCollapseRect.top + kExpandSize;
fCloseRect = bounds;
fCloseRect.top = (kHeaderSize - kExpandSize) / 2;
fCloseRect.right -= kEdgePadding * 2;
fCloseRect.left = fCloseRect.right - kCloseSize;
fCloseRect.bottom = fCloseRect.top + kCloseSize;
if (be_control_look != NULL) {
uint32 arrowDirection = fCollapsed
? BControlLook::B_DOWN_ARROW : BControlLook::B_UP_ARROW;
be_control_look->DrawArrowShape(this, fCollapseRect, fCollapseRect,
LowColor(), arrowDirection, 0, B_DARKEN_3_TINT);
} else {
rgb_color outlineColor = {80, 80, 80, 255};
rgb_color middleColor = {200, 200, 200, 255};
SetDrawingMode(B_OP_OVER);
if (fCollapsed) {
BeginLineArray(6);
AddLine(BPoint(fCollapseRect.left + 3, fCollapseRect.top + 1),
BPoint(fCollapseRect.left + 3, fCollapseRect.bottom - 1), outlineColor);
AddLine(BPoint(fCollapseRect.left + 3, fCollapseRect.top + 1),
BPoint(fCollapseRect.left + 7, fCollapseRect.top + 5), outlineColor);
AddLine(BPoint(fCollapseRect.left + 7, fCollapseRect.top + 5),
BPoint(fCollapseRect.left + 3, fCollapseRect.bottom - 1), outlineColor);
AddLine(BPoint(fCollapseRect.left + 4, fCollapseRect.top + 3),
BPoint(fCollapseRect.left + 4, fCollapseRect.bottom - 3), middleColor);
AddLine(BPoint(fCollapseRect.left + 5, fCollapseRect.top + 4),
BPoint(fCollapseRect.left + 5, fCollapseRect.bottom - 4), middleColor);
AddLine(BPoint(fCollapseRect.left + 5, fCollapseRect.top + 5),
BPoint(fCollapseRect.left + 6, fCollapseRect.top + 5), middleColor);
EndLineArray();
} else {
// expanded state
BeginLineArray(6);
AddLine(BPoint(fCollapseRect.left + 1, fCollapseRect.top + 3),
BPoint(fCollapseRect.right - 3, fCollapseRect.top + 3), outlineColor);
AddLine(BPoint(fCollapseRect.left + 1, fCollapseRect.top + 3),
BPoint(fCollapseRect.left + 5, fCollapseRect.top + 7), outlineColor);
AddLine(BPoint(fCollapseRect.left + 5, fCollapseRect.top + 7),
BPoint(fCollapseRect.right - 3, fCollapseRect.top + 3), outlineColor);
AddLine(BPoint(fCollapseRect.left + 3, fCollapseRect.top + 4),
BPoint(fCollapseRect.right - 5, fCollapseRect.top + 4), middleColor);
AddLine(BPoint(fCollapseRect.left + 4, fCollapseRect.top + 5),
BPoint(fCollapseRect.right - 6, fCollapseRect.top + 5), middleColor);
AddLine(BPoint(fCollapseRect.left + 5, fCollapseRect.top + 5),
BPoint(fCollapseRect.left + 5, fCollapseRect.top + 6), middleColor);
EndLineArray();
}
}
PushState();
SetFont(be_bold_font);
SetPenSize(kPenSize);
if (fCollapsed) {
// Draw the expand widget
PushState();
SetHighColor(detailCol);
StrokeRoundRect(fCollapseRect, kSmallPadding, kSmallPadding);
BPoint expandHorStart(fCollapseRect.left + kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);
BPoint expandHorEnd(fCollapseRect.right - kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);
StrokeLine(expandHorStart, expandHorEnd);
BPoint expandVerStart(fCollapseRect.Width() / 2 + fCollapseRect.left, fCollapseRect.top + kSmallPadding);
BPoint expandVerEnd(fCollapseRect.Width() / 2 + fCollapseRect.left, fCollapseRect.bottom - kSmallPadding);
StrokeLine(expandVerStart, expandVerEnd);
PopState();
SetHighColor(tint_color(ui_color(B_PANEL_TEXT_COLOR), B_LIGHTEN_1_TINT));
} else {
SetLowColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
FillRect(textRect, B_SOLID_LOW);
SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
// Draw the collapse widget
StrokeRoundRect(fCollapseRect, kSmallPadding, kSmallPadding);
BPoint expandHorStart(fCollapseRect.left + kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);
BPoint expandHorEnd(fCollapseRect.right - kSmallPadding, fCollapseRect.Height() / 2 + fCollapseRect.top);
StrokeLine(expandHorStart, expandHorEnd);
}
// Draw the dismiss widget
StrokeRoundRect(fCloseRect, kSmallPadding, kSmallPadding);
BRect closeCross = fCloseRect;
closeCross.InsetBy(kSmallPadding, kSmallPadding);
rgb_color detailCol = ui_color(B_CONTROL_BORDER_COLOR);
detailCol = tint_color(detailCol, B_LIGHTEN_2_TINT);
StrokeRoundRect(fCloseRect, kSmallPadding, kSmallPadding);
StrokeLine(closeCross.LeftTop(), closeCross.RightBottom());
StrokeLine(closeCross.RightTop(), closeCross.LeftBottom());
// Draw the label
DrawString(label.String(), BPoint(fCollapseRect.right + 2 * kEdgePadding, labelOffset + kEdgePadding));
PopState();
SetHighColor(ui_color(B_PANEL_TEXT_COLOR));
BString label = fLabel;
if (fCollapsed)
label << " (" << fInfo.size() << ")";
Sync();
SetFont(be_bold_font);
DrawString(label.String(), BPoint(fCollapseRect.right + 2 * kEdgePadding,
fCloseRect.bottom));
}
*/
void
void
AppGroupView::MouseDown(BPoint point)
{
bool changed = false;
@ -139,15 +165,38 @@ AppGroupView::MouseDown(BPoint point)
int32 children = fInfo.size();
for (int32 i = 0; i < children; i++) {
fView->GetLayout()->RemoveView(fInfo[i]);
GetLayout()->RemoveView(fInfo[i]);
delete fInfo[i];
}
fInfo.clear();
// Remove ourselves from the parent view
BMessage message(kRemoveView);
message.AddPointer("view", this);
fParent->PostMessage(&message);
}
if (fCollapseRect.Contains(point)) {
fCollapsed = !fCollapsed;
int32 children = fInfo.size();
if (fCollapsed) {
for (int32 i = 0; i < children; i++) {
if (!fInfo[i]->IsHidden())
fInfo[i]->Hide();
}
} else {
for (int32 i = 0; i < children; i++) {
if (fInfo[i]->IsHidden())
fInfo[i]->Show();
}
}
changed = true;
Invalidate(); // Need to redraw the collapse indicator and title
BMessage message(kRemoveView);
// Do not actually remive anything, but update size
fParent->PostMessage(&message);
}
if (changed) {
@ -170,14 +219,14 @@ AppGroupView::MessageReceived(BMessage* msg)
if (vIt != fInfo.end()) {
fInfo.erase(vIt);
fView->GetLayout()->RemoveView(view);
GetLayout()->RemoveView(view);
delete view;
}
_ResizeViews();
if (Window() != NULL)
Window()->PostMessage(msg);
_ResizeViews();
break;
}
default:
@ -197,7 +246,7 @@ AppGroupView::AddInfo(NotificationView* view)
for (int32 i = 0; i < children; i++) {
if (id == fInfo[i]->MessageID()) {
fView->GetLayout()->RemoveView(fInfo[i]);
GetLayout()->RemoveView(fInfo[i]);
delete fInfo[i];
fInfo[i] = view;
@ -208,36 +257,25 @@ AppGroupView::AddInfo(NotificationView* view)
}
}
if (!found)
if (!found) {
fInfo.push_back(view);
fView->GetLayout()->AddView(view);
}
GetLayout()->AddView(view);
if (IsHidden())
Show();
if (view->IsHidden())
if (view->IsHidden() && !fCollapsed)
view->Show();
_ResizeViews();
}
void
AppGroupView::_ResizeViews()
{
font_height fh;
be_bold_font->GetHeight(&fh);
float offset = 2 * kEdgePadding + fh.ascent + fh.leading + fh.descent;
int32 children = fInfo.size();
if (!fCollapsed) {
offset += kEdgePadding + kPenSize;
for (int32 i = 0; i < children; i++) {
fInfo[i]->ResizeToPreferred();
fInfo[i]->MoveTo(0, offset);
offset += fInfo[i]->Bounds().Height();
if (fInfo[i]->IsHidden())
fInfo[i]->Show();
}
@ -247,22 +285,9 @@ AppGroupView::_ResizeViews()
fInfo[i]->Hide();
}
ResizeTo(fParent->Width(), offset);
float labelOffset = fh.ascent + fh.leading;
BRect borderRect = Bounds().InsetByCopy(kEdgePadding, kEdgePadding);
borderRect.top = 2*labelOffset;
fCollapseRect = borderRect;
fCollapseRect.right = fCollapseRect.left + kExpandSize;
fCollapseRect.bottom = fCollapseRect.top + kExpandSize;
fCollapseRect.OffsetTo(kEdgePadding * 2, kEdgePadding * 1.5);
fCloseRect = borderRect;
fCloseRect.right -= kEdgePadding * 2;
fCloseRect.top += kEdgePadding * 1.5;
fCloseRect.left = fCloseRect.right - kCloseSize;
fCloseRect.bottom = fCloseRect.top + kCloseSize;
if (!IsHidden() && !HasChildren())
Hide();
fParent->Layout(true);
}

View File

@ -10,7 +10,7 @@
#include <vector>
#include <Box.h>
#include <GroupView.h>
#include <String.h>
class BGroupView;
@ -20,13 +20,13 @@ class NotificationView;
typedef std::vector<NotificationView*> infoview_t;
class AppGroupView : public BBox {
class AppGroupView : public BGroupView {
public:
AppGroupView(NotificationWindow* win, const char* label);
~AppGroupView();
virtual void MouseDown(BPoint point);
virtual void MessageReceived(BMessage* msg);
void Draw(BRect updateRect);
bool HasChildren();
@ -37,7 +37,6 @@ private:
BString fLabel;
NotificationWindow* fParent;
BGroupView* fView;
infoview_t fInfo;
bool fCollapsed;
BRect fCloseRect;

View File

@ -48,8 +48,7 @@ property_info message_prop_list[] = {
NotificationView::NotificationView(NotificationWindow* win,
BNotification* notification, bigtime_t timeout)
:
BView("NotificationView", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE
| B_FRAME_EVENTS),
BView("NotificationView", B_WILL_DRAW),
fParent(win),
fNotification(notification),
fTimeout(timeout),
@ -65,8 +64,6 @@ NotificationView::NotificationView(NotificationWindow* win,
BGroupLayout* layout = new BGroupLayout(B_VERTICAL);
SetLayout(layout);
SetText();
switch (fNotification->Type()) {
case B_IMPORTANT_NOTIFICATION:
SetViewColor(255, 255, 255);
@ -87,15 +84,15 @@ NotificationView::NotificationView(NotificationWindow* win,
label << (int)(fNotification->Progress() * 100) << " %";
progress->SetTrailingText(label);
BGroupLayoutBuilder b(layout);
b.AddGlue()
.Add(progress);
layout->AddView(progress);
}
// fall through
default:
SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
SetLowColor(ui_color(B_PANEL_BACKGROUND_COLOR));
}
SetText();
}
@ -284,8 +281,8 @@ NotificationView::Draw(BRect updateRect)
PopState();
SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT));
BPoint left(Bounds().left, Bounds().bottom - 1);
BPoint right(Bounds().right, Bounds().bottom - 1);
BPoint left(Bounds().left, Bounds().top);
BPoint right(Bounds().right, Bounds().top);
StrokeLine(left, right);
Sync();
@ -367,17 +364,19 @@ NotificationView::MouseDown(BPoint point)
}
/*
BSize
NotificationView::MinSize()
{
return BLayoutUtils::ComposeSize(ExplicitMinSize(), _CalculateSize());
// return BLayoutUtils::ComposeSize(ExplicitMinSize(), _CalculateSize());
return _CalculateSize();
}
BSize
NotificationView::MaxSize()
{
return BLayoutUtils::ComposeSize(ExplicitMaxSize(), _CalculateSize());
return _CalculateSize();
}
@ -387,6 +386,7 @@ NotificationView::PreferredSize()
return BLayoutUtils::ComposeSize(ExplicitPreferredSize(),
_CalculateSize());
}
*/
BHandler*
@ -524,6 +524,8 @@ NotificationView::SetText(float newMaxWidth)
// enough.
static_cast<BGroupLayout*>(GetLayout())->SetInsets(kIconStripeWidth + 8,
fHeight, 8, 8);
_CalculateSize();
}
@ -539,16 +541,19 @@ NotificationView::_CalculateSize()
{
BSize size;
// Parent width, minus the edge padding, minus the pensize
size.width = B_SIZE_UNLIMITED;
size.width = 300;
size.height = fHeight;
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;
size.height += 9 + (kSmallPadding * 2) + (kEdgePadding * 1)
+ fontHeight * 2;
}
SetExplicitMinSize(size);
SetExplicitMaxSize(size);
return size;
}

View File

@ -31,9 +31,11 @@ public:
virtual void Draw(BRect updateRect);
virtual void MouseDown(BPoint point);
/*
virtual BSize MinSize();
virtual BSize MaxSize();
virtual BSize PreferredSize();
*/
virtual BHandler* ResolveSpecifier(BMessage* msg, int32 index,
BMessage* specifier, int32 form,

View File

@ -64,11 +64,12 @@ NotificationWindow::NotificationWindow()
{
SetLayout(new BGroupLayout(B_VERTICAL, 0));
Hide();
Show();
_LoadSettings(true);
_LoadAppFilters(true);
// Start the message loop
Hide();
Show();
}
@ -189,6 +190,7 @@ NotificationWindow::MessageReceived(BMessage* message)
group->AddInfo(view);
_ResizeAll();
SetPosition();
reply.AddInt32("error", B_OK);
} else
@ -213,6 +215,7 @@ NotificationWindow::MessageReceived(BMessage* message)
fViews.erase(it);
_ResizeAll();
SetPosition();
break;
}
default:
@ -317,45 +320,31 @@ NotificationWindow::_ResizeAll()
if (IsHidden())
Show();
float width = 0;
float height = 0;
for (aIt = fAppViews.begin(); aIt != fAppViews.end(); aIt++) {
AppGroupView* view = aIt->second;
float w = -1;
float h = -1;
if (!view->HasChildren()) {
if (!view->IsHidden())
view->Hide();
} else {
view->GetPreferredSize(&w, &h);
width = max_c(width, h);
view->ResizeToPreferred();
view->MoveTo(0, height);
height += h;
if (view->IsHidden())
view->Show();
}
}
ResizeTo(Width(), height);
PopupAnimation();
}
void
NotificationWindow::SetPosition()
{
Layout(true);
BRect bounds = DecoratorFrame();
float width = Bounds().Width() + 1;
float height = Bounds().Height() + 1;
float leftOffset = Frame().left - bounds.left;
float topOffset = Frame().top - bounds.top;
float topOffset = Frame().top - bounds.top + 1;
float rightOffset = bounds.right - Frame().right;
float bottomOffset = bounds.bottom - Frame().bottom;
// Size of the borders around the window
@ -370,27 +359,27 @@ NotificationWindow::SetPosition()
case B_DESKBAR_TOP:
// Put it just under, top right corner
y = frame.bottom + topOffset;
x = frame.right - width - rightOffset;
x = frame.right - width + rightOffset;
break;
case B_DESKBAR_BOTTOM:
// Put it just above, lower left corner
y = frame.top - height - bottomOffset;
x = frame.right - width - rightOffset;
x = frame.right - width + rightOffset;
break;
case B_DESKBAR_RIGHT_TOP:
x = frame.left - width - rightOffset;
y = frame.top + topOffset;
y = frame.top - topOffset;
break;
case B_DESKBAR_LEFT_TOP:
x = frame.right + leftOffset;
y = frame.top + topOffset;
y = frame.top - topOffset;
break;
case B_DESKBAR_RIGHT_BOTTOM:
y = frame.bottom - height - bottomOffset;
y = frame.bottom - height + bottomOffset;
x = frame.left - width - rightOffset;
break;
case B_DESKBAR_LEFT_BOTTOM:
y = frame.bottom - height - bottomOffset;
y = frame.bottom - height + bottomOffset;
x = frame.right + leftOffset;
break;
default:
@ -400,16 +389,6 @@ NotificationWindow::SetPosition()
MoveTo(x, y);
}
void
NotificationWindow::PopupAnimation()
{
SetPosition();
if (IsHidden())
Show();
// Activate();// it hides floaters from apps :-(
}
void
NotificationWindow::_LoadSettings(bool startMonitor)

View File

@ -60,7 +60,6 @@ private:
friend class AppGroupView;
void SetPosition();
void PopupAnimation();
void _LoadSettings(bool startMonitor = false);
void _LoadAppFilters(bool startMonitor = false);
void _SaveAppFilters();