From c07e6ff292cbe19ab758ce8bcb6c5cde38a3e662 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Fri, 26 Oct 2012 02:00:29 -0400 Subject: [PATCH] Make horizontal scrolling work in Deskbar * Split the Leaf menu and seperator into their own menubar. * I got rid of a lot of special cases for horizontal in the ExpandoMenuBar class because now the menubar contains the same items as in vertical mode. However, it also means that the dreaded bug also affects horizontal mode. * Make the application menubar resize itself even in horizontal mode. This means that the view background shows through so I'm going to have to fix this up. * Calculate when to add the scroll arrows and how much to allow the user to scroll by for horizontal. CheckItemSizes() got a big refactoring. * Rework the InlineScrollView class a bit. It no longer requires you to specify the begin and end limits on construction because it can calculate them instead. It also no longer depends on the screen at all, this means this class can be extened to be used more generally and in more places. --- src/apps/deskbar/BarMenuBar.cpp | 50 +++++++++- src/apps/deskbar/BarMenuBar.h | 4 + src/apps/deskbar/BarView.cpp | 50 +++++----- src/apps/deskbar/ExpandoMenuBar.cpp | 128 +++++++++++--------------- src/apps/deskbar/ExpandoMenuBar.h | 5 +- src/apps/deskbar/InlineScrollView.cpp | 20 ++-- src/apps/deskbar/InlineScrollView.h | 13 +-- src/apps/deskbar/TeamMenuItem.cpp | 2 +- 8 files changed, 144 insertions(+), 128 deletions(-) diff --git a/src/apps/deskbar/BarMenuBar.cpp b/src/apps/deskbar/BarMenuBar.cpp index bd093ae8e6..ae3689fb0c 100644 --- a/src/apps/deskbar/BarMenuBar.cpp +++ b/src/apps/deskbar/BarMenuBar.cpp @@ -51,6 +51,8 @@ All rights reserved. #include "TeamMenu.h" +const float kSepItemWidth = 5.0f; + TBarMenuBar::TBarMenuBar(TBarView* bar, BRect frame, const char* name) : BMenuBar(frame, name, B_FOLLOW_NONE, B_ITEMS_IN_ROW, false), fBarView(bar), @@ -86,11 +88,15 @@ TBarMenuBar::SmartResize(float width, float height) width -= 1; - int32 count = CountItems(); - if (fDeskbarMenuItem) - fDeskbarMenuItem->SetWidthHeight(width / count, height); - if (fAppListMenuItem) - fAppListMenuItem->SetWidthHeight(width / count, height); + if (fSeparatorItem) + fDeskbarMenuItem->SetWidthHeight(width - kSepItemWidth, height); + else { + int32 count = CountItems(); + if (fDeskbarMenuItem) + fDeskbarMenuItem->SetWidthHeight(width / count, height); + if (fAppListMenuItem) + fAppListMenuItem->SetWidthHeight(width / count, height); + } InvalidateLayout(); } @@ -129,6 +135,40 @@ TBarMenuBar::RemoveTeamMenu() } +void +TBarMenuBar::AddSeperatorItem() +{ + if (CountItems() > 1) + return; + + BRect frame(Frame()); + delete fSeparatorItem; + + fSeparatorItem = new TTeamMenuItem(kSepItemWidth, + frame.Height() - 2, false); + AddItem(fSeparatorItem); + fSeparatorItem->SetEnabled(false); + SmartResize(frame.Width() - 1.0f, frame.Height()); +} + + +void +TBarMenuBar::RemoveSeperatorItem() +{ + if (CountItems() < 2) + return; + + if (fSeparatorItem) { + RemoveItem((BMenuItem*)fSeparatorItem); + delete fSeparatorItem; + fSeparatorItem = NULL; + } + + BRect frame = Frame(); + SmartResize(frame.Width(), frame.Height()); +} + + void TBarMenuBar::Draw(BRect rect) { diff --git a/src/apps/deskbar/BarMenuBar.h b/src/apps/deskbar/BarMenuBar.h index a10630dbfc..f691a903a5 100644 --- a/src/apps/deskbar/BarMenuBar.h +++ b/src/apps/deskbar/BarMenuBar.h @@ -63,6 +63,9 @@ class TBarMenuBar : public BMenuBar { void AddTeamMenu(); void RemoveTeamMenu(); + void AddSeperatorItem(); + void RemoveSeperatorItem(); + void InitTrackingHook(bool (* hookfunction)(BMenu*, void*), void* state, bool both = false); @@ -70,6 +73,7 @@ class TBarMenuBar : public BMenuBar { TBarView* fBarView; TBarMenuTitle* fDeskbarMenuItem; TBarMenuTitle* fAppListMenuItem; + TTeamMenuItem* fSeparatorItem; }; diff --git a/src/apps/deskbar/BarView.cpp b/src/apps/deskbar/BarView.cpp index b0b620c847..94a256c6cf 100644 --- a/src/apps/deskbar/BarView.cpp +++ b/src/apps/deskbar/BarView.cpp @@ -42,6 +42,7 @@ All rights reserved. #include #include +#include #include #include #include @@ -71,6 +72,7 @@ const int32 kDefaultRecentAppCount = 10; const int32 kMenuTrackMargin = 20; const uint32 kUpdateOrientation = 'UpOr'; +const float kSepItemWidth = 5.0f; class BarViewMessageFilter : public BMessageFilter @@ -349,49 +351,47 @@ TBarView::MouseDown(BPoint where) void TBarView::PlaceDeskbarMenu() { - // top or bottom, full - if (!fVertical && fBarMenuBar != NULL) { - fBarMenuBar->RemoveSelf(); - delete fBarMenuBar; - fBarMenuBar = NULL; + // Calculate the size of the deskbar menu + BRect menuFrame(Bounds()); + if (fVertical) + menuFrame.bottom = menuFrame.top + kMenuBarHeight; + else { + menuFrame.bottom = menuFrame.top + + static_cast(be_app)->IconSize() + 4; } - // top or bottom expando mode has Be menu built in for tracking - // only for vertical mini or expanded - // mini mode will have team menu added as part of BarMenuBar - if (fVertical && fBarMenuBar == NULL) { + if (fBarMenuBar == NULL) { // create the Be menu - BRect mbarFrame(Bounds()); - mbarFrame.bottom = mbarFrame.top + kMenuBarHeight; - fBarMenuBar = new TBarMenuBar(this, mbarFrame, "BarMenuBar"); + fBarMenuBar = new TBarMenuBar(this, menuFrame, "BarMenuBar"); AddChild(fBarMenuBar); } - // if there isn't a bemenu at this point, - // DB should be in top/bottom mode, else error - if (fBarMenuBar == NULL) - return; - float width = sMinimumWindowWidth; BPoint loc(B_ORIGIN); - BRect menuFrame(fBarMenuBar->Frame()); if (fState == kFullState) { fBarMenuBar->RemoveTeamMenu(); + fBarMenuBar->RemoveSeperatorItem(); // TODO: Magic constants need explanation width = 8 + 16 + 8; + fBarMenuBar->SmartResize(width, menuFrame.Height()); loc = Bounds().LeftTop(); } else if (fState == kExpandoState) { - // shows apps below tray fBarMenuBar->RemoveTeamMenu(); - if (fVertical) + if (fVertical) { + // shows apps below tray + fBarMenuBar->RemoveSeperatorItem(); width += 1; - else - width = floorf(width) / 2; + } else { + // shows apps to the right of bemenu + fBarMenuBar->AddSeperatorItem(); + width = floorf(width) / 2 + kSepItemWidth; + } loc = Bounds().LeftTop(); } else { // mini mode, DeskbarMenu next to team menu fBarMenuBar->AddTeamMenu(); + fBarMenuBar->RemoveSeperatorItem(); } fBarMenuBar->SmartResize(width, menuFrame.Height()); @@ -491,6 +491,10 @@ TBarView::PlaceApplicationBar() expandoFrame.top = 0; int32 iconSize = static_cast(be_app)->IconSize(); expandoFrame.bottom = iconSize + 4; + + if (fBarMenuBar != NULL) + expandoFrame.left = fBarMenuBar->Frame().Width(); + if (fTrayLocation != 0) expandoFrame.right = fDragRegion->Frame().left - 1; else @@ -505,8 +509,6 @@ TBarView::PlaceApplicationBar() fVertical, !hideLabels && fState != kFullState); fInlineScrollView = new TInlineScrollView(menuScrollFrame, fExpando, - fVertical ? expandoFrame.top : expandoFrame.left, - fVertical ? screenFrame.bottom : expandoFrame.right, fVertical ? B_VERTICAL : B_HORIZONTAL); AddChild(fInlineScrollView); diff --git a/src/apps/deskbar/ExpandoMenuBar.cpp b/src/apps/deskbar/ExpandoMenuBar.cpp index b395d1e1e2..a4561ee7de 100644 --- a/src/apps/deskbar/ExpandoMenuBar.cpp +++ b/src/apps/deskbar/ExpandoMenuBar.cpp @@ -79,7 +79,7 @@ TExpandoMenuBar::TExpandoMenuBar(TBarView* bar, BRect frame, const char* name, bool vertical, bool drawLabel) : BMenuBar(frame, name, B_FOLLOW_NONE, - vertical ? B_ITEMS_IN_COLUMN : B_ITEMS_IN_ROW, vertical), + vertical ? B_ITEMS_IN_COLUMN : B_ITEMS_IN_ROW), fVertical(vertical), fOverflow(false), fDrawLabel(drawLabel), @@ -87,7 +87,6 @@ TExpandoMenuBar::TExpandoMenuBar(TBarView* bar, BRect frame, const char* name, fExpandNewTeams(static_cast(be_app)->Settings()->expandNewTeams), fDeskbarMenuWidth(kDefaultDeskbarMenuWidth), fBarView(bar), - fFirstApp(0), fPreviousDragTargetItem(NULL), fLastClickItem(NULL) { @@ -137,24 +136,10 @@ TExpandoMenuBar::AttachedToWindow() // top or bottom mode, add deskbar menu and sep for menubar tracking // consistency if (!fVertical) { - TDeskbarMenu* beMenu = new TDeskbarMenu(fBarView); - TBarWindow::SetDeskbarMenu(beMenu); const BBitmap* logoBitmap = AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_LeafLogoBitmap); if (logoBitmap != NULL) fDeskbarMenuWidth = logoBitmap->Bounds().Width() + 16; - - fDeskbarMenuItem = new TBarMenuTitle(fDeskbarMenuWidth, - Frame().Height(), logoBitmap, beMenu, true); - AddItem(fDeskbarMenuItem); - - fSeparatorItem = new TTeamMenuItem(kSepItemWidth, itemHeight, fVertical); - AddItem(fSeparatorItem); - fSeparatorItem->SetEnabled(false); - fFirstApp = 2; - } else { - fDeskbarMenuItem = NULL; - fSeparatorItem = NULL; } if (settings->sortRunningApps) @@ -169,7 +154,7 @@ TExpandoMenuBar::AttachedToWindow() && !strcmp(barInfo->sig, kTrackerSignature)) { AddItem(new TTeamMenuItem(barInfo->teams, barInfo->icon, barInfo->name, barInfo->sig, itemWidth, itemHeight, - fDrawLabel, fVertical), fFirstApp); + fDrawLabel, fVertical), 0); } else { AddItem(new TTeamMenuItem(barInfo->teams, barInfo->icon, barInfo->name, barInfo->sig, itemWidth, itemHeight, @@ -526,20 +511,15 @@ TExpandoMenuBar::MouseUp(BPoint where) bool TExpandoMenuBar::InDeskbarMenu(BPoint loc) const { - if (!fVertical) { - if (fDeskbarMenuItem && fDeskbarMenuItem->Frame().Contains(loc)) - return true; - } else { - TBarWindow* window = dynamic_cast(Window()); - if (window) { - if (TDeskbarMenu* bemenu = window->DeskbarMenu()) { - bool inDeskbarMenu = false; - if (bemenu->LockLooper()) { - inDeskbarMenu = bemenu->Frame().Contains(loc); - bemenu->UnlockLooper(); - } - return inDeskbarMenu; + TBarWindow* window = dynamic_cast(Window()); + if (window) { + if (TDeskbarMenu* bemenu = window->DeskbarMenu()) { + bool inDeskbarMenu = false; + if (bemenu->LockLooper()) { + inDeskbarMenu = bemenu->Frame().Contains(loc); + bemenu->UnlockLooper(); } + return inDeskbarMenu; } } @@ -558,7 +538,7 @@ TExpandoMenuBar::TeamItemAtPoint(BPoint point, BMenuItem** _item) TTeamMenuItem* lastApp = NULL; int32 count = CountItems(); - for (int32 i = fFirstApp; i < count; i++) { + for (int32 i = 0; i < count; i++) { BMenuItem* item = ItemAt(i); if (dynamic_cast(item) != NULL) @@ -604,11 +584,11 @@ TExpandoMenuBar::AddTeam(BList* team, BBitmap* icon, char* name, itemWidth, itemHeight, fDrawLabel, fVertical); if (settings->trackerAlwaysFirst && !strcmp(signature, kTrackerSignature)) - AddItem(item, fFirstApp); + AddItem(item, 0); else if (settings->sortRunningApps) { TTeamMenuItem* teamItem - = dynamic_cast(ItemAt(fFirstApp)); - int32 firstApp = fFirstApp; + = dynamic_cast(ItemAt(0)); + int32 firstApp = 0; // if Tracker should always be the first item, we need to skip it // when sorting in the current item @@ -648,7 +628,7 @@ void TExpandoMenuBar::AddTeam(team_id team, const char* signature) { int32 count = CountItems(); - for (int32 i = fFirstApp; i < count; i++) { + for (int32 i = 0; i < count; i++) { // Only add to team menu items if (TTeamMenuItem* item = dynamic_cast(ItemAt(i))) { if (strcasecmp(item->Signature(), signature) == 0) { @@ -665,7 +645,7 @@ void TExpandoMenuBar::RemoveTeam(team_id team, bool partial) { int32 count = CountItems(); - for (int32 i = fFirstApp; i < count; i++) { + for (int32 i = 0; i < count; i++) { if (TTeamMenuItem* item = dynamic_cast(ItemAt(i))) { if (item->Teams()->HasItem((void*)team)) { item->Teams()->RemoveItem(team); @@ -698,61 +678,51 @@ TExpandoMenuBar::CheckItemSizes(int32 delta) if (fBarView->Vertical()) return; + float maxWidth = fBarView->DragRegion()->Frame().left + - fDeskbarMenuWidth - kSepItemWidth; int32 iconSize = static_cast(be_app)->IconSize(); - float maxContentWidth = sMinimumWindowWidth + iconSize - kMinimumIconSize; - - // There are 2 extra items: - // The Be Menu - // The little separator item - int32 count = CountItems() - 2; - float maxWidth = Frame().Width() - fDeskbarMenuWidth - kSepItemWidth * 2; - float fullWidth = maxContentWidth * count + fDeskbarMenuWidth - + kSepItemWidth; float iconOnlyWidth = kIconPadding + iconSize + kIconPadding; + float minItemWidth = fDrawLabel ? iconOnlyWidth + fDeskbarMenuWidth + : iconOnlyWidth; + float maxItemWidth = sMinimumWindowWidth + iconSize - kMinimumIconSize; + float menuWidth = maxItemWidth * CountItems() + fDeskbarMenuWidth + + kSepItemWidth; bool reset = false; float newWidth = 0.0f; - if (delta >= 0 && fullWidth > maxWidth) { + if (delta >= 0 && menuWidth > maxWidth) { fOverflow = true; reset = true; - if (fDrawLabel) - newWidth = floorf(maxWidth / count); - else - newWidth = iconOnlyWidth; + newWidth = floorf(maxWidth / CountItems()); } else if (delta < 0 && fOverflow) { reset = true; - if (fullWidth > maxWidth) { - if (fDrawLabel) - newWidth = floorf(maxWidth / count); - else - newWidth = iconOnlyWidth; - } else - newWidth = maxContentWidth; + if (menuWidth > maxWidth) + newWidth = floorf(maxWidth / CountItems()); + else + newWidth = maxItemWidth; } - if (newWidth > maxContentWidth) - newWidth = maxContentWidth; - - if (newWidth < iconOnlyWidth) - newWidth = iconOnlyWidth; + if (newWidth > maxItemWidth) + newWidth = maxItemWidth; + else if (newWidth < minItemWidth) + newWidth = minItemWidth; if (reset) { SetMaxContentWidth(newWidth); - if (newWidth == maxContentWidth) + if (newWidth == maxItemWidth) fOverflow = false; InvalidateLayout(); - for (int32 index = fFirstApp; ; index++) { + for (int32 index = 0; ; index++) { TTeamMenuItem* item = (TTeamMenuItem*)ItemAt(index); if (!item) break; - if (!fDrawLabel && newWidth > iconOnlyWidth) { + if (!fDrawLabel && newWidth > iconOnlyWidth) item->SetOverrideWidth(iconOnlyWidth); - } else { + else item->SetOverrideWidth(newWidth); - } } Invalidate(); @@ -788,9 +758,9 @@ TExpandoMenuBar::DrawBackground(BRect) rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT); rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_TINT); - int32 last = CountItems() - 1; - if (last >= 0) - bounds.left = ItemAt(last)->Frame().right + 1; + int32 count = CountItems() - 1; + if (count >= 0) + bounds.left = ItemAt(count)->Frame().right + 1; else bounds.left = 0; @@ -820,12 +790,20 @@ TExpandoMenuBar::DrawBackground(BRect) bool TExpandoMenuBar::CheckForSizeOverrun() { - BRect screenFrame = (BScreen(Window())).Frame(); - - if (fVertical) + if (fVertical) { + BRect screenFrame = (BScreen(Window())).Frame(); return Window()->Frame().bottom > screenFrame.bottom; - else - return Frame().right > fBarView->DragRegion()->Frame().left; + } + + // horizontal + int32 count = CountItems() - 1; + if (count < 0) + return false; + + float menuWidth = ItemAt(count)->Frame().right + fDeskbarMenuWidth + + kSepItemWidth + 1; + float maxWidth = fBarView->DragRegion()->Frame().left - 1; + return menuWidth > maxWidth; } diff --git a/src/apps/deskbar/ExpandoMenuBar.h b/src/apps/deskbar/ExpandoMenuBar.h index 5a08a0b67e..79f628cda8 100644 --- a/src/apps/deskbar/ExpandoMenuBar.h +++ b/src/apps/deskbar/ExpandoMenuBar.h @@ -104,11 +104,8 @@ class TExpandoMenuBar : public BMenuBar { float fDeskbarMenuWidth; TBarView* fBarView; - int32 fFirstApp; - TBarMenuTitle* fDeskbarMenuItem; - TTeamMenuItem* fSeparatorItem; - TTeamMenuItem* fPreviousDragTargetItem; + TTeamMenuItem* fPreviousDragTargetItem; TTeamMenuItem* fLastMousedOverItem; BMenuItem* fLastClickItem; diff --git a/src/apps/deskbar/InlineScrollView.cpp b/src/apps/deskbar/InlineScrollView.cpp index 0a44188e3d..ab3ef7a913 100644 --- a/src/apps/deskbar/InlineScrollView.cpp +++ b/src/apps/deskbar/InlineScrollView.cpp @@ -314,7 +314,7 @@ RightScrollArrow::MouseDown(BPoint where) TInlineScrollView::TInlineScrollView(BRect frame, BView* target, - float beginLimit, float endLimit, enum orientation orientation) + enum orientation orientation) : BView(frame, "inline scroll view", B_FOLLOW_NONE, 0), fTarget(target), @@ -323,8 +323,6 @@ TInlineScrollView::TInlineScrollView(BRect frame, BView* target, fScrollStep(kDefaultScrollStep), fScrollValue(0), fScrollLimit(0), - fBeginLimit(beginLimit), - fEndLimit(endLimit), fOrientation(orientation) { } @@ -388,11 +386,11 @@ TInlineScrollView::AttachScrollers() if (HasScrollers()) { if (fOrientation == B_VERTICAL) { - fScrollLimit = Window()->Frame().bottom + 2 * kScrollerDimension - - fEndLimit; + fScrollLimit = fTarget->Bounds().Height() + - (frame.Height() - 2 * kScrollerDimension); } else { - fScrollLimit = fTarget->Frame().right + 2 * kScrollerDimension - - fEndLimit; + fScrollLimit = fTarget->Bounds().Width() + - (frame.Width() - 2 * kScrollerDimension); } return; } @@ -416,8 +414,8 @@ TInlineScrollView::AttachScrollers() fTarget->MoveBy(0, kScrollerDimension); - fScrollLimit = Window()->Frame().bottom + 2 * kScrollerDimension - - fEndLimit; + fScrollLimit = fTarget->Bounds().Height() + - (frame.Height() - 2 * kScrollerDimension); } else { if (fBeginScrollArrow == NULL) { fBeginScrollArrow = new LeftScrollArrow( @@ -435,8 +433,8 @@ TInlineScrollView::AttachScrollers() fTarget->MoveBy(kScrollerDimension, 0); - fScrollLimit = fTarget->Frame().right + 2 * kScrollerDimension - - fEndLimit; + fScrollLimit = fTarget->Bounds().Width() + - (frame.Width() - 2 * kScrollerDimension); } fBeginScrollArrow->SetEnabled(false); diff --git a/src/apps/deskbar/InlineScrollView.h b/src/apps/deskbar/InlineScrollView.h index 74dc97010b..e483e0e2f8 100644 --- a/src/apps/deskbar/InlineScrollView.h +++ b/src/apps/deskbar/InlineScrollView.h @@ -13,15 +13,14 @@ #include -class BLayout; -class ScrollArrow; -class BPoint; +class BLayout; +class BPoint; +class ScrollArrow; class TInlineScrollView : public BView { public: TInlineScrollView(BRect frame, BView* target, - float beginLimit, float endLimit, enum orientation orientation = B_VERTICAL); virtual ~TInlineScrollView(); @@ -33,7 +32,8 @@ public: bool HasScrollers() const; void SetSmallStep(float step); - void GetSteps(float* _smallStep, float* _largeStep) const; + void GetSteps(float* _smallStep, + float* _largeStep) const; void ScrollBy(const float& step); private: @@ -45,9 +45,6 @@ private: float fScrollValue; float fScrollLimit; - float fBeginLimit; - float fEndLimit; - int32 fOrientation; }; diff --git a/src/apps/deskbar/TeamMenuItem.cpp b/src/apps/deskbar/TeamMenuItem.cpp index dd0e07347c..1d33cf66a1 100644 --- a/src/apps/deskbar/TeamMenuItem.cpp +++ b/src/apps/deskbar/TeamMenuItem.cpp @@ -240,7 +240,7 @@ TTeamMenuItem::GetContentSize(float* width, float* height) if (fDrawLabel && iconBounds.Width() > 32) *height += fLabelAscent + fLabelDescent; } else { - *height = iconBounds.Height() - kVPad * 8; + *height = iconBounds.Height() + kVPad * 4; } } *height += 2;