From 44c6e69bd178b3fcfc48b180b394d4075a89d091 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Thu, 3 Nov 2011 21:04:41 +0000 Subject: [PATCH] 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 --- src/servers/notification/AppGroupView.cpp | 265 ++++++++++-------- src/servers/notification/AppGroupView.h | 7 +- src/servers/notification/NotificationView.cpp | 33 ++- src/servers/notification/NotificationView.h | 2 + .../notification/NotificationWindow.cpp | 53 ++-- src/servers/notification/NotificationWindow.h | 1 - 6 files changed, 185 insertions(+), 176 deletions(-) diff --git a/src/servers/notification/AppGroupView.cpp b/src/servers/notification/AppGroupView.cpp index 756cb89d34..01e4778fe1 100644 --- a/src/servers/notification/AppGroupView.cpp +++ b/src/servers/notification/AppGroupView.cpp @@ -13,6 +13,7 @@ #include +#include #include #include @@ -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(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); } diff --git a/src/servers/notification/AppGroupView.h b/src/servers/notification/AppGroupView.h index d0ec4787f9..551bc4fa14 100644 --- a/src/servers/notification/AppGroupView.h +++ b/src/servers/notification/AppGroupView.h @@ -10,7 +10,7 @@ #include -#include +#include #include class BGroupView; @@ -20,13 +20,13 @@ class NotificationView; typedef std::vector 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; diff --git a/src/servers/notification/NotificationView.cpp b/src/servers/notification/NotificationView.cpp index e7e74b70d2..613ecc542f 100644 --- a/src/servers/notification/NotificationView.cpp +++ b/src/servers/notification/NotificationView.cpp @@ -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(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; } diff --git a/src/servers/notification/NotificationView.h b/src/servers/notification/NotificationView.h index 46588a5e3b..62d12ec83b 100644 --- a/src/servers/notification/NotificationView.h +++ b/src/servers/notification/NotificationView.h @@ -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, diff --git a/src/servers/notification/NotificationWindow.cpp b/src/servers/notification/NotificationWindow.cpp index c5954fba6f..8a280849e9 100644 --- a/src/servers/notification/NotificationWindow.cpp +++ b/src/servers/notification/NotificationWindow.cpp @@ -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) diff --git a/src/servers/notification/NotificationWindow.h b/src/servers/notification/NotificationWindow.h index 9457ccf32d..4556417d7f 100644 --- a/src/servers/notification/NotificationWindow.h +++ b/src/servers/notification/NotificationWindow.h @@ -60,7 +60,6 @@ private: friend class AppGroupView; void SetPosition(); - void PopupAnimation(); void _LoadSettings(bool startMonitor = false); void _LoadAppFilters(bool startMonitor = false); void _SaveAppFilters();