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
  <none> 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.
This commit is contained in:
John Scipione 2012-10-26 02:00:29 -04:00
parent e6d8c22a7d
commit c07e6ff292
8 changed files with 144 additions and 128 deletions

View File

@ -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;
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)
{

View File

@ -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;
};

View File

@ -42,6 +42,7 @@ All rights reserved.
#include <AppFileInfo.h>
#include <Bitmap.h>
#include <ControlLook.h>
#include <Debug.h>
#include <Directory.h>
#include <LocaleRoster.h>
@ -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<TBarApp*>(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<TBarApp*>(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);

View File

@ -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<TBarApp*>(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,10 +511,6 @@ 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<TBarWindow*>(Window());
if (window) {
if (TDeskbarMenu* bemenu = window->DeskbarMenu()) {
@ -541,7 +522,6 @@ TExpandoMenuBar::InDeskbarMenu(BPoint loc) const
return inDeskbarMenu;
}
}
}
return false;
}
@ -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<TTeamMenuItem*>(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<TTeamMenuItem*>(ItemAt(fFirstApp));
int32 firstApp = fFirstApp;
= dynamic_cast<TTeamMenuItem*>(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<TTeamMenuItem*>(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<TTeamMenuItem*>(ItemAt(i))) {
if (item->Teams()->HasItem((void*)team)) {
item->Teams()->RemoveItem(team);
@ -698,62 +678,52 @@ TExpandoMenuBar::CheckItemSizes(int32 delta)
if (fBarView->Vertical())
return;
float maxWidth = fBarView->DragRegion()->Frame().left
- fDeskbarMenuWidth - kSepItemWidth;
int32 iconSize = static_cast<TBarApp*>(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);
if (menuWidth > maxWidth)
newWidth = floorf(maxWidth / CountItems());
else
newWidth = iconOnlyWidth;
} else
newWidth = maxContentWidth;
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();
Window()->UpdateIfNeeded();
@ -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()
{
if (fVertical) {
BRect screenFrame = (BScreen(Window())).Frame();
if (fVertical)
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;
}

View File

@ -104,10 +104,7 @@ class TExpandoMenuBar : public BMenuBar {
float fDeskbarMenuWidth;
TBarView* fBarView;
int32 fFirstApp;
TBarMenuTitle* fDeskbarMenuItem;
TTeamMenuItem* fSeparatorItem;
TTeamMenuItem* fPreviousDragTargetItem;
TTeamMenuItem* fLastMousedOverItem;

View File

@ -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);

View File

@ -13,15 +13,14 @@
#include <View.h>
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;
};

View File

@ -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;