[haiku-commits] haiku: hrev53955 - src/apps/deskbar data/artwork/icons

  • From: Adrien Destugues <pulkomandy@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 9 Mar 2020 04:48:52 -0400 (EDT)

hrev53955 adds 1 changeset to branch 'master'
old head: 23be24d2d23793046b7572cf1fcc1ed9536dc231
new head: 0d2645e44f9e7f132df9a90e8f65153c6293e56a
overview: 
https://git.haiku-os.org/haiku/log/?qt=range&q=0d2645e44f9e+%5E23be24d2d237

----------------------------------------------------------------------------

0d2645e44f9e: Deskbar: New single line mini-mode
  
  Mini-mode is when Deskbar is in the 4 corners with the application
  menu tucked away into the leaf menu bar. This commit changes mini-
  mode from putting the clock and replicants below the leaf menu to
  attaching them to the side forming a single line.
  
  The main advantage of this is that if Deskbar is in the top right
  corner you can maximize a window without losing any access to
  Deskbar or any screen real-estate. The other three corners lose screen
  real-estate similar to horizontal mode.
  
  Replace team icon with HVIF version kindly donated by meanwhile.
  Scale icon size according to font size. Grow the vector rendered icon
  size by 1px to match bitmap size. Add Team_Registrar icon to
  data/artwork/icons. Tweak Team_Registrar icon to match the area of the
  bitmap taken up by the bitmap icon so they will render at the same size.
  The bitmap can be now NULL if an invalid icon is passed, handle this
  case with an fInitStatus member in BarMenuTitle.
  
  Switch order of leaf and team menus on the left side so that the
  team menu is always on the screen edge. The team menu is more in
  need of quick corner access than the leaf menu in this mode.
  
  Adjust leaf menu position so that it continues to be cut-off while
  allowing the team menu icon to display normally. Center vertically in
  horizontal mode but it's still cut-off at 16x16. In vertical mode the
  leaf continues to be cut-off at all font sizes. Constrain leaf bitmap
  to its menu item frame as it can bleed out into the adjacent team menu
  item at larger font sizes.
  
  Grow team menu items to fit the widest label up to the max vertical
  expando window width (currently 2x min) before truncating.
  LegacyPackageInstaller now fits in the team menu. More on
  LegacyPackageInstaller in horizontal mode below.
  
  Update SetSizeLimits for mini-mode - no upper limit on height or width.
  
  Switch to mini-mode using 1/4 screen left and right of screen instead
  of using 1/6. Mini mode is now wider and this change makes switching
  between mini mode and horizontal mode more reliable.
   * Rename frame to screenFrame here for clarity.
  
  Set menu bar height to window tab height in vertical mode. This is
  so that when you maximize a window the tab size will match. The menu
  bar height is also a few pixels taller (25px vs 21px) than it was in
  vertical expando mode at the default 12px font size. The change was
  made to match the tab height. 21px was the height of a window tab
  on BeOS R5's default decorator.
  
  Adjust the width of the team menu for larger icon sizes. If app
  names are hidden limit to half of min width so the menu doesn't
  appear too short. SetMaxContentSize to width, this fixes a bug where
  the menu item wasn't quite the right size for the menu.
  
  No longer truncate time in vertical mini mode because the time can now
  expand itself horizontally without limit (within reason.)
  
  Center replicants vertically in mini-mode based on tab height and max
  replicant height. Simplify mini-mode menu width and position calculation.
  Fix a bar menu bar placement bug when Deskbar starts hidden in mini-mode.
  
  Fix numerous layout issues. Put replicant tray where it should be in all
  modes and then start adjusting things. The Replicant tray is now where
  it should be in all modes, any fiddling with replicant icon locations
  now can be relegated solely to LocationForReplicant().
  
  Implements bug #5876 step 1.
  
  *** Other related Deskbar improvements also made in this commit ***
  
  Implemented underflow in horizontal mode ExpandoMenuBar to make items
  wider when you close a team to take up more of available space. Max item
  width is currently set to 1.25x min width so that LegacyPackageInstaller
  fits in horizontal mode as well. In team menu it make sense to calculate
  the widest label but in horizontal mode it would not be very nice if
  ARogueAppWithAVeryVeryLongAndAnnoyingName were to grow all of your team
  menu items. 1.25x is a fair compromise that gets us some extra width but
  not too much. ExpandoMenuBar will truncate items to minimum width to buy
  some space before it turns on the scroll arrows. Eliminate
  kMinMenuItemWidth, create convinience methods to calculate limits.
  
  Add BarView pointer to TimeView. Ditch fVertical and SetOrientation
  in TTimeView and get the information from BarView instead. This way
  we don't have to keep the state in sync. Also pass BarView pointer to
  TTeamMenu constructor and use it instead of getting the pointer in a
  roundabout way from be_app.
  
  Eliminate kMiniHeight constant, the mini-mode height is now based
  on the height of a window tab which changes with be_bold_font size.
  Limit maximum height of replicants by be_bold_font size as well.
  Also limit team menu and leaf menu icon heights by be_bold_font size.
  
  Eliminate TExpandoMenuBar::fVertical, use fBarView instead. Switch the
  order of layout and barView in ctor so that barView can be optional.
  Change the ctor vertical param to layout and use the passed-in menu_layout
  to pass to BMenuBar only. Once TExpandoMenuBar has been constructed, use
  fBarView from then on. In Deskbar the menu_layout can change via
  BMenuPrivate::SetLayout, if we needed to know TExpandoMenuBar's menu_layout
  for some reason, we can call Layout().
  
  Maintain 2px border around replicants in vertical expando mode on all
  sides. Maintain 2px border around replicants in horizontal mode, except for
  at 16x16 reduce the border to 1px because we're really short on height.
  Improve clock centering in vertical expando mode. Also improve clock
  centering in mini-mode across all font sizes. Reduce clock height by 2px
  so that it won't draw over the top and bottom borders in horizontal mode.
  
  Refactor TBarView::PlaceTray(). The code is basically the same but the
  method is now better layed out. Calculate resize dragger location based
  on width setting. This is valid since it is only ever used in vertical
  expando mode. Hide the resize control better by moving it off-screen
  when not in use. Hide() alone was not enough.
  
  Fix size and position of the drag region to prevent minor drawing glitches
  that were occuring in horizontal and left vertical mode because the drag
  region was not in quite the right size and place.
  
  Call DrawDragger() from DrawAfterChildren() instead of Draw() (and set
  B_DRAW_ON_CHILDREN flag) so that the dragger will always be drawn even if
  there are other items on top. In theory this should not be needed but in
  practice this fixes a few drawing glitches. Rename DrawDragRegion() to
  private DrawDragger() method - the name was confusing and other classes
  shouldn't be allowed to draw the dragger directly.
  
  TDragRegion should be renamed to TStatusView since that's what it really is.
  Then we should create a new TDragControl class based on TResizeControl that
  is a child of TStatusView like everybody else. TDragControl would be
  responsible for drawing itself and knowing where its bounds are. For now
  DrawAfterChildren() will have to do.
  
  Rework status tray border drawing. It is identical in vertical exando mode
  and in the same spirit in horizontal mode just a little bit nicer looking.
  Draw hilight on top, left, and bottom edges in horizontal mode. Draw hilight
  on top, and left edges in mini-mode this creates the appearance of a shadow.
  Best appreciated using Magnify.
  
  May the following (Open Tracker License) code forever be memorialized in
  this commit message:
  
  void
  TDragRegion::Draw(BRect updateRect)
  {
        rgb_color menuColor = ViewColor();
        rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
        rgb_color ldark = tint_color(menuColor, 1.02);
        rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
        rgb_color vvdark = tint_color(menuColor, B_DARKEN_4_TINT);
        rgb_color light = tint_color(menuColor, B_LIGHTEN_2_TINT);
  
        BRect frame(Bounds());
        BeginLineArray(4);
  
        if (be_control_look != NULL) {
                if (fBarView->Vertical()) {
                        AddLine(frame.LeftTop(), frame.RightTop(), dark);
                        AddLine(BPoint(frame.left, frame.top + 1),
                                BPoint(frame.right, frame.top + 1), ldark);
                        AddLine(frame.LeftBottom(), frame.RightBottom(), 
hilite);
                } else if (fBarView->AcrossTop() || fBarView->AcrossBottom()) {
                        AddLine(frame.LeftTop(),
                                BPoint(frame.left, frame.bottom), dark);
                        AddLine(BPoint(frame.left + 1, frame.top + 1),
                                BPoint(frame.right - 1, frame.top + 1), light);
                        AddLine(BPoint(frame.right, frame.top + 2),
                                BPoint(frame.right, frame.bottom), hilite);
                        AddLine(BPoint(frame.left + 1, frame.bottom),
                                BPoint(frame.right - 1, frame.bottom), hilite);
                }
        } else {
                if (fBarView->Vertical()) {
                        AddLine(frame.LeftTop(), frame.RightTop(), light);
                        AddLine(frame.LeftTop(), frame.LeftBottom(), light);
                        AddLine(frame.RightBottom(), frame.RightTop(), hilite);
                } else if (fBarView->AcrossTop()) {
                        AddLine(BPoint(frame.left, frame.top + 1),
                                BPoint(frame.right - 1, frame.top + 1), light);
                        AddLine(frame.RightTop(), frame.RightBottom(), vvdark);
                        AddLine(BPoint(frame.right - 1, frame.top + 2),
                                BPoint(frame.right - 1, frame.bottom - 1), 
hilite);
                        AddLine(frame.LeftBottom(),
                                BPoint(frame.right - 1, frame.bottom), hilite);
                } else if (fBarView->AcrossBottom()) {
                        AddLine(BPoint(frame.left, frame.top + 1), 
BPoint(frame.right - 1, frame.top + 1), light);
                        AddLine(frame.LeftBottom(), frame.RightBottom(), 
hilite);
                        AddLine(frame.RightTop(), frame.RightBottom(), vvdark);
                        AddLine(BPoint(frame.right - 1, frame.top + 1),
                                BPoint(frame.right - 1, frame.bottom - 1), 
hilite);
                }
        }
  
        EndLineArray();
  }
  
  Refactor mode switching.
  
  Change TDragRegion::SwitchModeForRect() to SwitchModeForRegion() and pass
  in BRegion's instead of BRect's. Create a new CalculateRegions() method
  which is called once at startup and again on ScreenChanged() instead of
  calculating the rect's over and over again inside MouseMoved(). Simplify
  calculations using BRegion's.
  
  Get the screen_where parameter from the Window()'s CurrentMessage() instead
  of converting the passed in where parameter to screen coordinates. This
  makes mode switching work 100% better.
  
  Restore full state, fix all issues, and disable it again.
  
  Fix issue with the window not resizing itself correctly when hiding the
  scroller arrows in vertical expando mode because Deskbar was using the
  bottom value of a scrolled view rather than its height. We only need to
  call CheckForScrolling() once before we resize the window. Consolidate all
  the window resizing code into ExpandoMenuBar::SizeWindow(), call
  CheckForScrolling() there one time, then resize the window and lay
  everything out again.
  
  Simplify expando menu bar background drawing. The only part of this
  drawing code that was actually being shown was the part where it stroked a
  vertical line like this:
  
  rgb_color menuColor = ui_color(B_MENU_BACKGROUND_COLOR);
  SetHighColor(tint_color(menuColor, 1.22));
  StrokeLine(bounds.LeftTop(), bounds.LeftBottom());
  
  The rest of the code was never seen. May the following code also be forever
  memorialized in this commit message:
  
  void
  TExpandoMenuBar::DrawBackground(BRect updateRect)
  {
        if (Vertical())
                return;
  
        BRect bounds(Bounds());
        rgb_color menuColor = ui_color(B_MENU_BACKGROUND_COLOR);
        rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
        rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_TINT);
  
        int32 count = CountItems() - 1;
        if (count >= 0)
                bounds.left = ItemAt(count)->Frame().right + 1;
        else
                bounds.left = 0;
  
        if (be_control_look != NULL) {
                SetHighColor(tint_color(menuColor, 1.22));
                StrokeLine(bounds.LeftTop(), bounds.LeftBottom());
                bounds.left++;
                uint32 borders = BControlLook::B_TOP_BORDER
                        | BControlLook::B_BOTTOM_BORDER | 
BControlLook::B_RIGHT_BORDER;
  
                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());
        }
  }
  
  Change-Id: Id9ddd60c997a785184208ba02938bee1416aeae9
  Reviewed-on: https://review.haiku-os.org/c/haiku/+/2253
  Reviewed-by: Adrien Destugues <pulkomandy@xxxxxxxxx>

                                     [ John Scipione <jscipione@xxxxxxxxx> ]

----------------------------------------------------------------------------

Revision:    hrev53955
Commit:      0d2645e44f9e7f132df9a90e8f65153c6293e56a
URL:         https://git.haiku-os.org/haiku/commit/?id=0d2645e44f9e
Author:      John Scipione <jscipione@xxxxxxxxx>
Date:        Tue Nov 19 22:21:59 2019 UTC
Committer:   Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Mon Mar  9 08:48:46 2020 UTC

Ticket:      https://dev.haiku-os.org/ticket/5876

----------------------------------------------------------------------------

20 files changed, 858 insertions(+), 619 deletions(-)
data/artwork/icons/Team_Registrar   | Bin 0 -> 33654 bytes
src/apps/deskbar/BarMenuBar.cpp     |  51 +++-
src/apps/deskbar/BarMenuBar.h       |   6 +
src/apps/deskbar/BarMenuTitle.cpp   |  63 +++--
src/apps/deskbar/BarMenuTitle.h     |   9 +-
src/apps/deskbar/BarView.cpp        | 356 +++++++++++++-------------
src/apps/deskbar/BarView.h          |   5 +-
src/apps/deskbar/BarWindow.cpp      |  19 +-
src/apps/deskbar/DeskbarMenu.cpp    |   7 +-
src/apps/deskbar/ExpandoMenuBar.cpp | 279 +++++++++++----------
src/apps/deskbar/ExpandoMenuBar.h   |  16 +-
src/apps/deskbar/StatusView.cpp     | 430 +++++++++++++++++---------------
src/apps/deskbar/StatusView.h       |  32 ++-
src/apps/deskbar/TeamMenu.cpp       |  81 ++++--
src/apps/deskbar/TeamMenu.h         |   6 +-
src/apps/deskbar/TeamMenuItem.cpp   |  12 +-
src/apps/deskbar/TimeView.cpp       |  34 +--
src/apps/deskbar/TimeView.h         |  20 +-
src/apps/deskbar/icons.h            |   4 +-
src/apps/deskbar/icons.rdef         |  47 ++++

----------------------------------------------------------------------------

diff --git a/data/artwork/icons/Team_Registrar 
b/data/artwork/icons/Team_Registrar
new file mode 100644
index 0000000000..2772f68cbd
Binary files /dev/null and b/data/artwork/icons/Team_Registrar differ
diff --git a/src/apps/deskbar/BarMenuBar.cpp b/src/apps/deskbar/BarMenuBar.cpp
index 73e5ead2f8..164945f7aa 100644
--- a/src/apps/deskbar/BarMenuBar.cpp
+++ b/src/apps/deskbar/BarMenuBar.cpp
@@ -52,11 +52,14 @@ All rights reserved.
 #include "DeskbarMenu.h"
 #include "DeskbarUtils.h"
 #include "ResourceSet.h"
+#include "StatusView.h"
 #include "TeamMenu.h"
 
 
 const float kSepItemWidth = 5.0f;
 
+const float kTeamIconBitmapHeight = 19.f;
+
 
 //     #pragma mark - TSeparatorItem
 
@@ -104,7 +107,9 @@ TBarMenuBar::TBarMenuBar(BRect frame, const char* name, 
TBarView* barView)
        BMenuBar(frame, name, B_FOLLOW_NONE, B_ITEMS_IN_ROW, false),
        fBarView(barView),
        fAppListMenuItem(NULL),
-       fSeparatorItem(NULL)
+       fSeparatorItem(NULL),
+       fTeamIconData(NULL),
+       fTeamIconSize(0)
 {
        SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
 
@@ -118,7 +123,10 @@ TBarMenuBar::TBarMenuBar(BRect frame, const char* name, 
TBarView* barView)
        if (data != NULL) {
                // Scale bitmap according to font size
                float width = std::max(63.f, ceilf(63 * be_plain_font->Size() / 
12.f));
+               // but limit by be_bold_font size
+               width = std::min(width, ceilf(63.f * be_bold_font->Size() / 
12.f));
                float height = std::max(22.f, ceilf(22 * be_plain_font->Size() 
/ 12.f));
+               height = std::min(height, ceilf(22.f * be_bold_font->Size() / 
12.f));
                icon = new BBitmap(BRect(0, 0, width - 1, height - 1), 
B_RGBA32);
                if (icon->InitCheck() != B_OK
                        || BIconUtils::GetVectorIcon((const uint8*)data, 
dataSize, icon)
@@ -128,7 +136,7 @@ TBarMenuBar::TBarMenuBar(BRect frame, const char* name, 
TBarView* barView)
                }
        }
 
-       fDeskbarMenuItem = new TBarMenuTitle(0.0f, 0.0f, icon, beMenu);
+       fDeskbarMenuItem = new TBarMenuTitle(0.0f, 0.0f, icon, beMenu, 
fBarView);
        AddItem(fDeskbarMenuItem);
 }
 
@@ -173,10 +181,10 @@ TBarMenuBar::AddTeamMenu()
        BRect frame(Frame());
 
        delete fAppListMenuItem;
-       fAppListMenuItem = new TBarMenuTitle(0.0f, 0.0f,
-               AppResSet()->FindBitmap(B_MESSAGE_TYPE, R_TeamIcon), new 
TTeamMenu());
+       fAppListMenuItem = new TBarMenuTitle(0.0f, 0.0f, FetchTeamIcon(),
+               new TTeamMenu(fBarView), fBarView);
 
-       bool added = AddItem(fAppListMenuItem);
+       bool added = AddItem(fAppListMenuItem, fBarView->Left() ? 0 : 1);
 
        if (added)
                SmartResize(frame.Width() - 1.0f, frame.Height());
@@ -324,3 +332,36 @@ TBarMenuBar::InitTrackingHook(bool (*hookFunction)(BMenu*, 
void*),
        if (fAppListMenuItem && (fAppListMenuItem->Frame().Contains(loc) || 
both))
                init_tracking_hook(fAppListMenuItem, hookFunction, state);
 }
+
+
+const BBitmap*
+TBarMenuBar::FetchTeamIcon()
+{
+       const BBitmap* teamIcon = NULL;
+
+       if (fTeamIconData == NULL || fTeamIconSize == 0) {
+               // we haven't fetched vector icon data yet, fetch it
+               fTeamIconData = (const uint8*)AppResSet()->FindResource(
+                       B_VECTOR_ICON_TYPE, R_TeamIconVector, &fTeamIconSize);
+       }
+
+       if (fTeamIconData != NULL && fTeamIconSize > 0) {
+               // seems valid, scale bitmap according to font size
+               float iconHeight = std::max(kTeamIconBitmapHeight,
+                       ceilf(kTeamIconBitmapHeight * be_plain_font->Size() / 
12.f));
+               // but limit by be_bold_font_size
+               iconHeight = std::min(iconHeight,
+                       ceilf(kTeamIconBitmapHeight * be_bold_font->Size() / 
12.f));
+               BRect iconRect = BRect(0, 0, iconHeight, iconHeight);
+               iconRect.InsetBy(-1, -1);
+                       // grow icon by 1px so that it renders nicely at 12pt 
font size
+               BBitmap* icon = new(std::nothrow) BBitmap(iconRect, B_RGBA32);
+               if (icon != NULL && BIconUtils::GetVectorIcon(fTeamIconData,
+                               fTeamIconSize, icon) == B_OK) {
+                       // rasterize vector icon into a bitmap at the scaled 
size
+                       teamIcon = icon;
+               }
+       }
+
+       return teamIcon;
+}
diff --git a/src/apps/deskbar/BarMenuBar.h b/src/apps/deskbar/BarMenuBar.h
index f470d38b1c..4346e9fa5a 100644
--- a/src/apps/deskbar/BarMenuBar.h
+++ b/src/apps/deskbar/BarMenuBar.h
@@ -79,11 +79,17 @@ public:
                                                                bool (* 
hookfunction)(BMenu*, void*),
                                                                void* state, 
bool both = false);
 
+       const   BBitmap*                FetchTeamIcon();
+
 private:
                        TBarView*               fBarView;
                        TBarMenuTitle*  fDeskbarMenuItem;
                        TBarMenuTitle*  fAppListMenuItem;
                        TSeparatorItem* fSeparatorItem;
+
+       const   uint8*                  fTeamIconData;
+                       size_t                  fTeamIconSize;
 };
 
+
 #endif // BARMENUBAR_H
diff --git a/src/apps/deskbar/BarMenuTitle.cpp 
b/src/apps/deskbar/BarMenuTitle.cpp
index 332793484c..7fce780057 100644
--- a/src/apps/deskbar/BarMenuTitle.cpp
+++ b/src/apps/deskbar/BarMenuTitle.cpp
@@ -39,21 +39,29 @@ All rights reserved.
 #include <Bitmap.h>
 #include <ControlLook.h>
 #include <Debug.h>
+#include <Region.h>
 
 #include "BarApp.h"
 #include "BarView.h"
 #include "BarWindow.h"
+#include "DeskbarMenu.h"
 
 
 TBarMenuTitle::TBarMenuTitle(float width, float height, const BBitmap* icon,
-       BMenu* menu, bool expando)
+       BMenu* menu, TBarView* barView)
        :
        BMenuItem(menu, new BMessage(B_REFS_RECEIVED)),
        fWidth(width),
        fHeight(height),
-       fInExpando(expando),
-       fIcon(icon)
+       fIcon(icon),
+       fMenu(menu),
+       fBarView(barView),
+       fInitStatus(B_NO_INIT)
 {
+       if (fIcon == NULL || fMenu == NULL || fBarView == NULL)
+               fInitStatus = B_BAD_VALUE;
+       else
+               fInitStatus = B_OK;
 }
 
 
@@ -82,7 +90,7 @@ void
 TBarMenuTitle::Draw()
 {
        BMenu* menu = Menu();
-       if (menu == NULL)
+       if (fInitStatus != B_OK || menu == NULL)
                return;
 
        BRect frame(Frame());
@@ -111,37 +119,52 @@ TBarMenuTitle::Draw()
 void
 TBarMenuTitle::DrawContent()
 {
-       if (fIcon == NULL)
+       if (fInitStatus != B_OK)
                return;
 
        BMenu* menu = Menu();
-       BRect frame(Frame());
-       BRect iconRect(fIcon->Bounds());
+       if (menu == NULL)
+               return;
 
        menu->SetDrawingMode(B_OP_ALPHA);
-       iconRect.OffsetTo(frame.LeftTop());
+
+       const BRect frame(Frame());
+       BRect iconRect(fIcon->Bounds().OffsetToCopy(frame.LeftTop()));
 
        float widthOffset = rintf((frame.Width() - iconRect.Width()) / 2);
-       float heightOffset = 0;
-       if (frame.Height() > iconRect.Height() + 2)
-               heightOffset = rintf((frame.Height() - iconRect.Height()) / 2);
-       iconRect.OffsetBy(widthOffset - 1.0f, heightOffset + 2.0f);
+       float heightOffset = rintf((frame.Height() - iconRect.Height()) / 2);
+
+       // cut-off the leaf
+       bool isLeafMenu = dynamic_cast<TDeskbarMenu*>(fMenu) != NULL;
+       if (fBarView->Vertical() && isLeafMenu)
+               iconRect.OffsetBy(widthOffset, frame.Height() - 
iconRect.Height() + 2);
+       else
+               iconRect.OffsetBy(widthOffset, heightOffset);
+
+       // clip to menu item frame
+       if (iconRect.Width() > frame.Width()) {
+               float diff = iconRect.Width() - frame.Width();
+               BRect mask(iconRect.InsetByCopy(floorf(diff / 2), 0));
+               BRegion clipping(mask);
+               menu->ConstrainClippingRegion(&clipping);
+       }
 
        menu->DrawBitmapAsync(fIcon, iconRect);
+       menu->ConstrainClippingRegion(NULL);
 }
 
 
 status_t
 TBarMenuTitle::Invoke(BMessage* message)
 {
-       TBarView* barview = dynamic_cast<TBarApp*>(be_app)->BarView();
-       if (barview) {
-               BLooper* looper = barview->Looper();
-               if (looper->Lock()) {
-                       // tell barview to add the refs to the deskbar menu
-                       barview->HandleDeskbarMenu(NULL);
-                       looper->Unlock();
-               }
+       if (fInitStatus != B_OK || fBarView == NULL)
+               return fInitStatus;
+
+       BLooper* looper = fBarView->Looper();
+       if (looper->Lock()) {
+               // tell barview to add the refs to the deskbar menu
+               fBarView->HandleDeskbarMenu(NULL);
+               looper->Unlock();
        }
 
        return BMenuItem::Invoke(message);
diff --git a/src/apps/deskbar/BarMenuTitle.h b/src/apps/deskbar/BarMenuTitle.h
index f7bcac02ec..1ec5806606 100644
--- a/src/apps/deskbar/BarMenuTitle.h
+++ b/src/apps/deskbar/BarMenuTitle.h
@@ -44,13 +44,12 @@ All rights reserved.
 #include <MenuItem.h>
 
 
-class BBitmap;
-class BMenu;
+class TBarView;
 
 class TBarMenuTitle : public BMenuItem {
 public:
        TBarMenuTitle(float width, float height, const BBitmap* icon,
-               BMenu* menu, bool expando = false);
+               BMenu* menu, TBarView* barView = NULL);
        virtual ~TBarMenuTitle();
 
        void SetContentSize(float width, float height);
@@ -65,8 +64,10 @@ protected:
 private:
        float fWidth;
        float fHeight;
-       bool fInExpando;
        const BBitmap* fIcon;
+       BMenu* fMenu;
+       TBarView* fBarView;
+       status_t fInitStatus;
 };
 
 
diff --git a/src/apps/deskbar/BarView.cpp b/src/apps/deskbar/BarView.cpp
index 13eccea107..09cc4a0f3c 100644
--- a/src/apps/deskbar/BarView.cpp
+++ b/src/apps/deskbar/BarView.cpp
@@ -66,6 +66,8 @@ const int32 kDefaultRecentAppCount = 10;
 const int32 kMenuTrackMargin = 20;
 const float kMinTeamItemHeight = 20.0f;
 const float kVPad = 2.0f;
+const float kIconPadding = 8.0f;
+const float kScrollerDimension = 12.0f;
 
 const uint32 kUpdateOrientation = 'UpOr';
 
@@ -150,22 +152,36 @@ TBarView::TBarView(BRect frame, bool vertical, bool left, 
bool top,
        fMaxRecentDocs(kDefaultRecentDocCount),
        fMaxRecentApps(kDefaultRecentAppCount),
        fLastDragItem(NULL),
-       fMouseFilter(NULL)
+       fMouseFilter(NULL),
+       fTabHeight(kMenuBarHeight)
 {
+       // get window tab height
+       BWindow* tmpWindow = new(std::nothrow) BWindow(BRect(), NULL,
+               B_TITLED_WINDOW, 0);
+       if (tmpWindow != NULL) {
+               BMessage settings;
+               if (tmpWindow->GetDecoratorSettings(&settings) == B_OK) {
+                       BRect tabRect;
+                       if (settings.FindRect("tab frame", &tabRect) == B_OK)
+                               fTabHeight = tabRect.Height();
+               }
+               delete tmpWindow;
+       }
+
        // determine the initial Be menu size
        // (will be updated later)
        BRect menuFrame(frame);
        if (fVertical)
-               menuFrame.bottom = menuFrame.top + kMenuBarHeight;
+               menuFrame.bottom = menuFrame.top + fTabHeight - 1;
        else
-               menuFrame.bottom = menuFrame.top + fBarApp->IconSize() + 4;
+               menuFrame.bottom = menuFrame.top + TeamMenuItemHeight();
 
        // create and add the Be menu
        fBarMenuBar = new TBarMenuBar(menuFrame, "BarMenuBar", this);
        AddChild(fBarMenuBar);
 
        // create the status tray
-       fReplicantTray = new TReplicantTray(this, fVertical);
+       fReplicantTray = new TReplicantTray(this);
 
        // create the resize control
        fResizeControl = new TResizeControl(this);
@@ -180,16 +196,18 @@ TBarView::TBarView(BRect frame, bool vertical, bool left, 
bool top,
        if (fTrayLocation != 0)
                AddChild(fDragRegion);
 
-       // create and add the application menubar
-       fExpandoMenuBar = new TExpandoMenuBar(this, fVertical);
+       // create and add the expando menu bar
+       fExpandoMenuBar = new TExpandoMenuBar(
+               fVertical ? B_ITEMS_IN_COLUMN : B_ITEMS_IN_ROW, this);
        fInlineScrollView = new TInlineScrollView(fExpandoMenuBar,
                fVertical ? B_VERTICAL : B_HORIZONTAL);
        AddChild(fInlineScrollView);
 
-       // If mini mode, hide the application menubar
+       // hide the expando menu bar in mini-mode
        if (state == kMiniState)
                fInlineScrollView->Hide();
 
+       // if auto-hide is on and we're not already hidden, hide ourself
        if (fBarApp->Settings()->autoHide && !IsHidden())
                Hide();
 }
@@ -447,15 +465,18 @@ TBarView::PlaceDeskbarMenu()
        // Calculate the size of the deskbar menu
        BRect menuFrame(Bounds());
        if (fVertical) {
-               width = static_cast<TBarApp*>(be_app)->Settings()->width;
-               height = 4 + fReplicantTray->MaxReplicantHeight();
-               menuFrame.bottom = menuFrame.top + height;
+               if (fState == kMiniState)
+                       width = gMinimumWindowWidth;
+               else
+                       width = fBarApp->Settings()->width;
+
+               height = fTabHeight;
        } else {
-               width = gMinimumWindowWidth;
+               width = gMinimumWindowWidth / 2 + kIconPadding;
                height = std::max(TeamMenuItemHeight(),
                        kGutter + fReplicantTray->MaxReplicantHeight() + 
kGutter);
-               menuFrame.bottom = menuFrame.top + height;
        }
+       menuFrame.bottom = menuFrame.top + height;
 
        if (fBarMenuBar == NULL) {
                // create the Be menu
@@ -464,31 +485,30 @@ TBarView::PlaceDeskbarMenu()
        } else
                fBarMenuBar->SmartResize(-1, -1);
 
-       BPoint loc(B_ORIGIN);
-       if (fState == kFullState) {
-               fBarMenuBar->RemoveTeamMenu();
-               fBarMenuBar->RemoveSeperatorItem();
-               loc = Bounds().LeftTop();
-       } else if (fState == kExpandoState) {
-               fBarMenuBar->RemoveTeamMenu();
-               if (fVertical) {
-                       // shows apps below tray
-                       fBarMenuBar->RemoveSeperatorItem();
-                       width += 1;
-               } else {
-                       // shows apps to the right of bemenu
-                       fBarMenuBar->AddSeparatorItem();
-                       width = floorf(width) / 2 + kSepItemWidth;
+       if (fVertical) {
+               switch (fState) {
+                       case kFullState:
+                       case kExpandoState:
+                       default:
+                               // shows apps below tray
+                               fBarMenuBar->RemoveTeamMenu();
+                               fBarMenuBar->RemoveSeperatorItem();
+                               break;
+
+                       case kMiniState:
+                               // leaf menu next to team menu
+                               fBarMenuBar->RemoveSeperatorItem();
+                               fBarMenuBar->AddTeamMenu();
+                               break;
                }
-               loc = Bounds().LeftTop();
        } else {
-               // mini mode, DeskbarMenu next to team menu
-               fBarMenuBar->RemoveSeperatorItem();
-               fBarMenuBar->AddTeamMenu();
+               // shows apps to the right of the leaf menu
+               fBarMenuBar->RemoveTeamMenu();
+               fBarMenuBar->AddSeparatorItem();
        }
 
        fBarMenuBar->SmartResize(width, height);
-       fBarMenuBar->MoveTo(loc);
+       fBarMenuBar->MoveTo(B_ORIGIN);
 }
 
 
@@ -496,71 +516,71 @@ void
 TBarView::PlaceTray(bool vertSwap, bool leftSwap)
 {
        BPoint statusLoc;
-       if (fState == kFullState) {
-               fDragRegion->ResizeTo(fBarMenuBar->Frame().Width(), 
kMenuBarHeight);
-               statusLoc.y = fBarMenuBar->Frame().bottom + 1;
-               statusLoc.x = 0;
-               fDragRegion->MoveTo(statusLoc);
-               fDragRegion->Invalidate();
-
+       if (fTrayLocation == 0) {
+               // no replicant tray mode, not used
                if (!fReplicantTray->IsHidden())
                        fReplicantTray->Hide();
-
                return;
-       }
-
-       if (fReplicantTray->IsHidden())
+       } else if (fReplicantTray->IsHidden())
                fReplicantTray->Show();
 
-       if (fTrayLocation != 0) {
-               fReplicantTray->SetMultiRow(fVertical);
-               fReplicantTray->RealignReplicants();
-               fDragRegion->ResizeToPreferred();
-                       // also resizes replicant tray
-
-               fResizeControl->ResizeTo(kDragWidth, 
fDragRegion->Bounds().Height()
-                       - 2); // make room for top and bottom border
-
-               if (fVertical) {
-                       if (fResizeControl->IsHidden())
-                               fResizeControl->Show();
+       fReplicantTray->RealignReplicants();
+       fDragRegion->ResizeToPreferred();
+               // also resizes replicant tray
 
+       if (fVertical) {
+               if (fState == kExpandoState || fState == kFullState) {
+                       // move replicant tray down by 2px
                        if (fLeft) {
-                               // move replicant tray past dragger width on 
left
-                               // also down 1px so it won't cover the border
-                               fReplicantTray->MoveTo(kDragWidth + kGutter, 
kGutter);
-
-                               // shrink width by same amount
-                               fReplicantTray->ResizeBy(-(kDragWidth + 
kGutter), 0);
+                               // move replicant tray past dragger and shrink 
by same amount
+                               fReplicantTray->MoveTo(kDragWidth + 1, 2);
+                               fReplicantTray->ResizeBy(-(kDragWidth + 1), -2);
                        } else {
-                               // move replicant tray down 1px so it won't 
cover the border
-                               fReplicantTray->MoveTo(0, kGutter);
+                               fReplicantTray->MoveTo(0, 2);
+                               fReplicantTray->ResizeBy(0, -2);
                        }
 
                        statusLoc.x = 0;
                        statusLoc.y = fBarMenuBar->Frame().bottom + 1;
-               } else {
-                       if (!fResizeControl->IsHidden())
-                               fResizeControl->Hide();
-
-                       // move right and down to not cover border then resize 
to fit
-                       fReplicantTray->MoveTo(kGutter, kGutter);
-                       fReplicantTray->ResizeBy(-kGutter, -kGutter);
-                       BRect screenFrame = (BScreen(Window())).Frame();
-                       statusLoc.x = screenFrame.right - 
fDragRegion->Bounds().Width();
-                       statusLoc.y = -1;
+               } else if (fState == kMiniState) {
+                       statusLoc.x = fLeft ? fBarMenuBar->Frame().right + 1 : 
0;
+                       statusLoc.y = 0;
+
+                       // move past dragger and top border
+                       // and make room for the top and bottom borders
+                       fReplicantTray->MoveTo(fLeft ? kDragWidth : 0, kGutter);
+                       fReplicantTray->ResizeBy(0, -4);
                }
+       } else {
+               // horizontal
+
+               // move tray right and down to not cover border, resize by same
+               fReplicantTray->MoveTo(2, 0);
+               fReplicantTray->ResizeBy(-2, 0);
+               BRect screenFrame = (BScreen(Window())).Frame();
+               statusLoc.x = screenFrame.right - fDragRegion->Bounds().Width();
+               statusLoc.y = 0;
+       }
 
-               fDragRegion->MoveTo(statusLoc);
-               fDragRegion->Invalidate();
+       fDragRegion->MoveTo(statusLoc);
 
-               if (fVertical && fLeft)
-                       fResizeControl->MoveTo(fDragRegion->Bounds().right - 
kDragWidth, 1);
-               else
-                       fResizeControl->MoveTo(0, 1);
+       // make room for top and bottom border
+       fResizeControl->ResizeTo(kDragWidth,  fDragRegion->Bounds().Height() - 
2);
 
-               fResizeControl->Invalidate();
+       // resize control is only used in vertical expando and full state
+       if (fVertical && fState != kMiniState) {
+               // move resize control into place based on width setting
+               fResizeControl->MoveTo(
+                       fLeft ? fBarApp->Settings()->width - kDragWidth : 0, 1);
+               if (fResizeControl->IsHidden())
+                       fResizeControl->Show();
+       } else {
+               // hide resize control
+               if (!fResizeControl->IsHidden())
+                       fResizeControl->Hide();
        }
+
+       fDragRegion->Invalidate();
 }
 
 
@@ -568,12 +588,16 @@ void
 TBarView::PlaceApplicationBar()
 {
        BRect screenFrame = (BScreen(Window())).Frame();
-       if (fState == kMiniState) {
+       if (fVertical && fState == kMiniState) {
                if (!fInlineScrollView->IsHidden())
                        fInlineScrollView->Hide();
+
                SizeWindow(screenFrame);
                PositionWindow(screenFrame);
                Window()->UpdateIfNeeded();
+               // move the menu bar into place after the window has been 
resized
+               // based on replicant tray
+               fBarMenuBar->MoveTo(fLeft ? 0 : fDragRegion->Bounds().right + 
1, 0);
                Invalidate();
                return;
        }
@@ -587,50 +611,36 @@ TBarView::PlaceApplicationBar()
                expandoFrame.left = fDragRegion->Frame().left;
                expandoFrame.top = fTrayLocation != 0 ? 
fDragRegion->Frame().bottom + 1
                        : fBarMenuBar->Frame().bottom + 1;
-               expandoFrame.right = fBarMenuBar->Frame().right;
+               expandoFrame.right = fBarApp->Settings()->width;
                expandoFrame.bottom = fState == kFullState ? screenFrame.bottom
                        : Frame().bottom;
        } else {
                // top or bottom
                expandoFrame.top = 0;
                expandoFrame.bottom = TeamMenuItemHeight();
-
-               if (fBarMenuBar != NULL)
-                       expandoFrame.left = fBarMenuBar->Frame().Width() + 1;
-
-               if (fTrayLocation != 0 && fDragRegion != NULL) {
-                       expandoFrame.right = screenFrame.Width()
-                               - fDragRegion->Frame().Width() - 1;
-               } else
-                       expandoFrame.right = screenFrame.Width();
+               expandoFrame.left = gMinimumWindowWidth / 2 + kIconPadding;
+               expandoFrame.right = screenFrame.Width();
+               if (fTrayLocation != 0 && fDragRegion != NULL)
+                       expandoFrame.right -= fDragRegion->Frame().Width() + 1;
        }
 
        fInlineScrollView->DetachScrollers();
        fInlineScrollView->MoveTo(expandoFrame.LeftTop());
        fInlineScrollView->ResizeTo(expandoFrame.Width(), fVertical
-               ? screenFrame.bottom - expandoFrame.top
-               : expandoFrame.Height());
-       fExpandoMenuBar->MoveTo(0, 0);
+               ? screenFrame.bottom - expandoFrame.top : expandoFrame.bottom);
        fExpandoMenuBar->ResizeTo(expandoFrame.Width(), expandoFrame.Height());
-
-       if (fState == kExpandoState)
-               fExpandoMenuBar->BuildItems();
-
-       SizeWindow(screenFrame);
-       PositionWindow(screenFrame);
-       fExpandoMenuBar->DoLayout();
-               // force menu to resize
-       CheckForScrolling();
-       Window()->UpdateIfNeeded();
-       Invalidate();
+       fExpandoMenuBar->MoveTo(0, 0);
+       fExpandoMenuBar->BuildItems();
+       fExpandoMenuBar->SizeWindow(0);
 }
 
 
 void
-TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* 
height)
+TBarView::GetPreferredWindowSize(BRect screenFrame, float* width,
+       float* height)
 {
        float windowHeight = 0;
-       float windowWidth = fBarApp->Settings()->width;
+       float windowWidth = 0;
        bool setToHiddenSize = fBarApp->Settings()->autoHide && IsHidden()
                && !fDragRegion->IsDragging();
 
@@ -639,36 +649,43 @@ TBarView::GetPreferredWindowSize(BRect screenFrame, 
float* width, float* height)
 
                if (fState == kExpandoState && !fVertical) {
                        // top or bottom, full
-                       fExpandoMenuBar->CheckItemSizes(0);
                        windowWidth = screenFrame.Width();
                } else
                        windowWidth = kHiddenDimension;
+       } else if (!fVertical) {
+               // horizontal top or bottom
+               windowHeight = std::max(TeamMenuItemHeight(),
+                       kGutter + fReplicantTray->MaxReplicantHeight() + 
kGutter);
+               windowWidth = screenFrame.Width();
        } else {
-               if (fState == kFullState) {
-                       windowHeight = screenFrame.bottom;
-                       windowWidth = fBarMenuBar->Frame().Width();
-               } else if (fState == kExpandoState) {
-                       if (fVertical) {
+               // vertical
+               switch (fState) {
+                       case kFullState:
+                       case kExpandoState:
+                       default:
                                // top left or right
                                if (fTrayLocation != 0)
                                        windowHeight = 
fDragRegion->Frame().bottom + 1;
                                else
                                        windowHeight = 
fBarMenuBar->Frame().bottom + 1;
 
-                               windowHeight += 
fExpandoMenuBar->Bounds().Height();
-                       } else {
-                               // top or bottom, full
-                               fExpandoMenuBar->CheckItemSizes(0);
-                               windowHeight = std::max(TeamMenuItemHeight(),
-                                       kGutter + 
fReplicantTray->MaxReplicantHeight() + kGutter);
-                               windowWidth = screenFrame.Width();
-                       }
-               } else {
-                       // four corners
-                       if (fTrayLocation != 0)
-                               windowHeight = fDragRegion->Frame().bottom;
-                       else
+                               // use Height() here not bottom because view 
can be scrolled
+                               if (fExpandoMenuBar != NULL)
+                                       windowHeight += 
fExpandoMenuBar->Bounds().Height();
+
+                               // full state has minimum screen window height
+                               if (fState == kFullState)
+                                       windowHeight = 
std::max(screenFrame.bottom, windowHeight);
+
+                               windowWidth = fBarApp->Settings()->width;
+                               break;
+
+                       case kMiniState:
+                               // four corners
                                windowHeight = fBarMenuBar->Frame().bottom;
+                               windowWidth = fDragRegion->Frame().Width()
+                                       + fBarMenuBar->Frame().Width() + 1;
+                               break;
                }
        }
 
@@ -684,6 +701,7 @@ TBarView::SizeWindow(BRect screenFrame)
        float windowHeight;
        GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
        Window()->ResizeTo(windowWidth, windowHeight);
+       ResizeTo(windowWidth, windowHeight);
 }
 
 
@@ -695,15 +713,11 @@ TBarView::PositionWindow(BRect screenFrame)
        GetPreferredWindowSize(screenFrame, &windowWidth, &windowHeight);
 
        BPoint moveLoc(0, 0);
-       // right, expanded
-       if (!fLeft && fVertical) {
-               if (fState == kFullState)
-                       moveLoc.x = screenFrame.right - 
fBarMenuBar->Frame().Width();
-               else
-                       moveLoc.x = screenFrame.right - windowWidth;
-       }
+       // right, expanded, mini, or full
+       if (!fLeft && fVertical)
+               moveLoc.x = screenFrame.right - windowWidth;
 
-       // bottom, full or corners
+       // bottom, full
        if (!fTop)
                moveLoc.y = screenFrame.bottom - windowHeight;
 
@@ -714,12 +728,13 @@ TBarView::PositionWindow(BRect screenFrame)
 void
 TBarView::CheckForScrolling()
 {
-       if (fInlineScrollView != NULL && fExpandoMenuBar != NULL) {
-               if (fExpandoMenuBar->CheckForSizeOverrun())
-                       fInlineScrollView->AttachScrollers();
-               else
-                       fInlineScrollView->DetachScrollers();
-       }
+       if (fInlineScrollView == NULL && fExpandoMenuBar == NULL)
+               return;
+
+       if (fExpandoMenuBar->CheckForSizeOverrun())
+               fInlineScrollView->AttachScrollers();
+       else
+               fInlineScrollView->DetachScrollers();
 }
 
 
@@ -783,22 +798,19 @@ TBarView::_ChangeState(BMessage* message)
                        // Send a message to the preferences window to let it 
know to
                        // enable or disable preference items.
 
-               if (vertSwap) {
-                       TBarWindow* window = 
dynamic_cast<TBarWindow*>(Window());
-                       if (window != NULL)
-                               window->SetSizeLimits();
-
-                       fReplicantTray->fTime->SetOrientation(fVertical);
-                       if (fExpandoMenuBar != NULL) {
-                               if (fVertical) {
-                                       
fInlineScrollView->SetOrientation(B_VERTICAL);
-                                       
fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN);
-                                       
fExpandoMenuBar->StartMonitoringWindows();
-                               } else {
-                                       
fInlineScrollView->SetOrientation(B_HORIZONTAL);
-                                       
fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW);
-                                       
fExpandoMenuBar->StopMonitoringWindows();
-                               }
+               TBarWindow* barWindow = dynamic_cast<TBarWindow*>(Window());
+               if (barWindow != NULL)
+                       barWindow->SetSizeLimits();
+
+               if (vertSwap && fExpandoMenuBar != NULL) {
+                       if (fVertical) {
+                               fInlineScrollView->SetOrientation(B_VERTICAL);
+                               
fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_COLUMN);
+                               fExpandoMenuBar->StartMonitoringWindows();
+                       } else {
+                               fInlineScrollView->SetOrientation(B_HORIZONTAL);
+                               fExpandoMenuBar->SetMenuLayout(B_ITEMS_IN_ROW);
+                               fExpandoMenuBar->StopMonitoringWindows();
                        }
                }
        }
@@ -917,8 +929,8 @@ TBarView::MenuTrackingHook(BMenu* menu, void* castToThis)
        if (!data)
                return false;
 
-       TBarView* barview = dynamic_cast<TBarView*>(data->fTarget.Target(NULL));
-       if (!barview || !menu->LockLooper())
+       TBarView* barView = dynamic_cast<TBarView*>(data->fTarget.Target(NULL));
+       if (!barView || !menu->LockLooper())
                return false;
 
        uint32 buttons;
@@ -936,30 +948,32 @@ TBarView::MenuTrackingHook(BMenu* menu, void* castToThis)
        } else {
                // see if the mouse is in the team/deskbar menu item
                menu->ConvertToScreen(&location);
-               if (barview->LockLooper()) {
-                       TExpandoMenuBar* expando = barview->ExpandoMenuBar();
-                       TDeskbarMenu* bemenu
-                               = 
(dynamic_cast<TBarWindow*>(barview->Window()))->DeskbarMenu();
-
-                       if (bemenu && bemenu->LockLooper()) {
-                               bemenu->ConvertFromScreen(&location);
-                               if (bemenu->Frame().Contains(location))
+               if (barView->LockLooper()) {
+                       TExpandoMenuBar* expandoMenuBar = 
barView->ExpandoMenuBar();
+                       TBarWindow* barWindow
+                               = dynamic_cast<TBarWindow*>(barView->Window());
+                       TDeskbarMenu* deskbarMenu = barWindow->DeskbarMenu();
+
+                       if (deskbarMenu && deskbarMenu->LockLooper()) {
+                               deskbarMenu->ConvertFromScreen(&location);
+                               if (deskbarMenu->Frame().Contains(location))
                                        endMenu = false;
 
-                               bemenu->UnlockLooper();
+                               deskbarMenu->UnlockLooper();
                        }
 
-                       if (endMenu && expando) {
-                               expando->ConvertFromScreen(&location);
-                               BMenuItem* item = 
expando->TeamItemAtPoint(location);
+                       if (endMenu && expandoMenuBar) {
+                               expandoMenuBar->ConvertFromScreen(&location);
+                               BMenuItem* item = 
expandoMenuBar->TeamItemAtPoint(location);
                                if (item)
                                        endMenu = false;
                        }
-                       barview->UnlockLooper();
+                       barView->UnlockLooper();
                }
        }
 
        menu->UnlockLooper();
+
        return endMenu;
 }
 
diff --git a/src/apps/deskbar/BarView.h b/src/apps/deskbar/BarView.h
index 80dbf344b7..0589bb996f 100644
--- a/src/apps/deskbar/BarView.h
+++ b/src/apps/deskbar/BarView.h
@@ -57,8 +57,6 @@ enum {
        kFullState = 2
 };
 
-
-const float kMiniHeight = 46.0f;
 const float kHModeHeight = 21.0f;
 const float kMenuBarHeight = 21.0f;
 const float kStatusHeight = 22.0f;
@@ -172,6 +170,7 @@ public:
                        TReplicantTray*         ReplicantTray() const { return 
fReplicantTray; }
 
                        float                   TeamMenuItemHeight() const;
+                       float                   TabHeight() const { return 
fTabHeight; };
 
 private:
        friend class TBarApp;
@@ -217,6 +216,8 @@ private:
 
                        TTeamMenuItem*  fLastDragItem;
                        BMessageFilter* fMouseFilter;
+
+                       float                   fTabHeight;
 };
 
 
diff --git a/src/apps/deskbar/BarWindow.cpp b/src/apps/deskbar/BarWindow.cpp
index 27f1e54e3a..98a386cc28 100644
--- a/src/apps/deskbar/BarWindow.cpp
+++ b/src/apps/deskbar/BarWindow.cpp
@@ -244,7 +244,7 @@ TBarWindow::Minimize(bool minimize)
 void
 TBarWindow::FrameResized(float width, float height)
 {
-       if (!fBarView->Vertical())
+       if (fBarView->MiniState() || !fBarView->Vertical())
                return BWindow::FrameResized(width, height);
 
        bool setToHiddenSize = fBarApp->Settings()->autoHide
@@ -266,7 +266,7 @@ TBarWindow::FrameResized(float width, float height)
 
                if (oldWidth != newWidth) {
                        fBarView->ResizeTo(width, fBarView->Bounds().Height());
-                       if (fBarView->Vertical() && fBarView->ExpandoState())
+                       if (fBarView->Vertical() && fBarView->ExpandoMenuBar() 
!= NULL)
                                
fBarView->ExpandoMenuBar()->SetMaxContentWidth(width);
 
                        fBarView->UpdatePlacement();
@@ -312,8 +312,12 @@ TBarWindow::ScreenChanged(BRect size, color_space depth)
 {
        BWindow::ScreenChanged(size, depth);
 
-       fBarView->UpdatePlacement();
        SetSizeLimits();
+
+       if (fBarView != NULL) {
+               fBarView->DragRegion()->CalculateRegions();
+               fBarView->UpdatePlacement();
+       }
 }
 
 
@@ -683,13 +687,18 @@ TBarWindow::SetSizeLimits()
                }
        } else {
                if (fBarView->Vertical()) {
-                       BWindow::SetSizeLimits(gMinimumWindowWidth, 
gMaximumWindowWidth,
-                               kMenuBarHeight - 1, B_SIZE_UNLIMITED);
+                       float minHeight = 0;
+                       float maxHeight = B_SIZE_UNLIMITED;
+                       float minWidth = gMinimumWindowWidth;
+                       float maxWidth = fBarView->MiniState() ? 
B_SIZE_UNLIMITED
+                               : gMaximumWindowWidth;
+                       BWindow::SetSizeLimits(minWidth, maxWidth, minHeight, 
maxHeight);
                } else {
                        BWindow::SetSizeLimits(screenFrame.Width(), 
screenFrame.Width(),
                                kMenuBarHeight - 1, kMaximumIconSize + 4);
                }
        }
+
 }
 
 
diff --git a/src/apps/deskbar/DeskbarMenu.cpp b/src/apps/deskbar/DeskbarMenu.cpp
index ac4a288085..9dd5ba7ac7 100644
--- a/src/apps/deskbar/DeskbarMenu.cpp
+++ b/src/apps/deskbar/DeskbarMenu.cpp
@@ -397,16 +397,17 @@ BPoint
 TDeskbarMenu::ScreenLocation()
 {
        bool vertical = fBarView->Vertical();
-       int32 expando = (fBarView->State() == kExpandoState);
+       int32 expando = fBarView->ExpandoState();
+       bool left = fBarView->Left();
        BPoint point;
 
        BRect rect = Supermenu()->Bounds();
        Supermenu()->ConvertToScreen(&rect);
 
-       if (expando && vertical && fBarView->Left()) {
+       if (vertical && expando && left) {
                PRINT(("Left\n"));
                point = rect.RightTop() + BPoint(0, 3);
-       } else if (expando && vertical && !fBarView->Left()) {
+       } else if (vertical && expando && !left) {
                PRINT(("Right\n"));
                point = rect.LeftTop() - BPoint(Bounds().Width(), 0) + 
BPoint(0, 3);
        } else
diff --git a/src/apps/deskbar/ExpandoMenuBar.cpp 
b/src/apps/deskbar/ExpandoMenuBar.cpp
index f1d9536fdc..70445d2a3c 100644
--- a/src/apps/deskbar/ExpandoMenuBar.cpp
+++ b/src/apps/deskbar/ExpandoMenuBar.cpp
@@ -70,8 +70,8 @@ All rights reserved.
 #include "WindowMenuItem.h"
 
 
-const float kMinMenuItemWidth = 50.0f;
 const float kIconPadding = 8.0f;
+const float kDeskbarMenuWidth = gMinimumWindowWidth / 2 + kIconPadding;
 
 const uint32 kMinimizeTeam = 'mntm';
 const uint32 kBringTeamToFront = 'bftm';
@@ -86,30 +86,19 @@ typedef std::map<BString, TTeamMenuItem*> TeamMenuItemMap;
 //     #pragma mark - TExpandoMenuBar
 
 
-TExpandoMenuBar::TExpandoMenuBar(TBarView* barView, bool vertical)
+TExpandoMenuBar::TExpandoMenuBar(menu_layout layout, TBarView* barView)
        :
-       BMenuBar(BRect(0, 0, 0, 0), "ExpandoMenuBar", B_FOLLOW_NONE,
-               vertical ? B_ITEMS_IN_COLUMN : B_ITEMS_IN_ROW),
+       BMenuBar(BRect(0, 0, 0, 0), "ExpandoMenuBar", B_FOLLOW_NONE, layout),
        fBarView(barView),
-       fVertical(vertical),
        fOverflow(false),
+       fUnderflow(false),
        fFirstBuild(true),
-       fDeskbarMenuWidth(gMinimumWindowWidth),
        fPreviousDragTargetItem(NULL),
        fLastMousedOverItem(NULL),
        fLastClickedItem(NULL)
 {
        SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
        SetFont(be_plain_font);
-
-       // top or bottom mode, add deskbar menu and sep for menubar tracking
-       // consistency
-       // TODO: this is broken code
-       fDeskbarMenuWidth = 63 + 16;
-//     const BBitmap* logoBitmap = AppResSet()->FindBitmap(B_MESSAGE_TYPE,
-//             R_LeafLogoBitmap);
-//     if (logoBitmap != NULL)
-//             fDeskbarMenuWidth = logoBitmap->Bounds().Width() + 16;
 }
 
 
@@ -129,7 +118,7 @@ TExpandoMenuBar::AttachedToWindow()
 
        fTeamList.MakeEmpty();
 
-       if (fVertical)
+       if (Vertical())
                StartMonitoringWindows();
 }
 
@@ -187,7 +176,7 @@ TExpandoMenuBar::MessageReceived(BMessage* message)
 
                        TInlineScrollView* scrollView
                                = dynamic_cast<TInlineScrollView*>(Parent());
-                       if (scrollView == NULL)
+                       if (scrollView == NULL || !scrollView->HasScrollers())
                                return;
 
                        float largeStep;
@@ -267,7 +256,8 @@ TExpandoMenuBar::MouseDown(BPoint where)
        BMenuItem* menuItem;
        TTeamMenuItem* item = TeamItemAtPoint(where, &menuItem);
 
-       if (message == NULL || item == NULL || fBarView->Dragging()) {
+       if (message == NULL || item == NULL || fBarView == NULL
+               || fBarView->Dragging()) {
                BMenuBar::MouseDown(where);
                return;
        }
@@ -304,7 +294,7 @@ TExpandoMenuBar::MouseDown(BPoint where)
        }
 
        // check if within expander bounds to expand window items
-       if (fVertical && static_cast<TBarApp*>(be_app)->Settings()->superExpando
+       if (Vertical() && 
static_cast<TBarApp*>(be_app)->Settings()->superExpando
                && item->ExpanderBounds().Contains(where)) {
                // start the animation here, finish on mouse up
                fLastClickedItem = item;
@@ -364,8 +354,7 @@ TExpandoMenuBar::MouseMoved(BPoint where, uint32 code, 
const BMessage* message)
 
                                TWindowMenuItem* windowMenuItem
                                        = 
dynamic_cast<TWindowMenuItem*>(menuItem);
-
-                               if (windowMenuItem != NULL && 
fBarView->Vertical()
+                               if (windowMenuItem != NULL && fBarView != NULL 
&& Vertical()
                                        && fBarView->ExpandoState() && 
item->IsExpanded()) {
                                        // expando mode window menu item
                                        fLastMousedOverItem = menuItem;
@@ -424,7 +413,7 @@ TExpandoMenuBar::MouseMoved(BPoint where, uint32 code, 
const BMessage* message)
                        break;
 
                case B_INSIDE_VIEW:
-                       if (fBarView->Dragging()) {
+                       if (fBarView != NULL && fBarView->Dragging()) {
                                TTeamMenuItem* item = NULL;
                                int32 itemCount = CountItems();
                                for (int32 i = 0; i < itemCount; i++) {
@@ -450,7 +439,7 @@ TExpandoMenuBar::MouseMoved(BPoint where, uint32 code, 
const BMessage* message)
 void
 TExpandoMenuBar::MouseUp(BPoint where)
 {
-       if (fBarView->Dragging()) {
+       if (fBarView != NULL && fBarView->Dragging()) {
                _FinishedDrag(true);
                return;
                        // absorb the message
@@ -466,12 +455,13 @@ TExpandoMenuBar::BuildItems()
        BMessenger self(this);
        TBarApp::Subscribe(self, &fTeamList);
 
+       desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
+
        float itemWidth = -1.0f;
-       if (fVertical) {
-               itemWidth = Frame().Width();
-               SetMaxContentWidth(itemWidth);
-       } else
-               CheckItemSizes(0, true); // force reset
+       if (Vertical() && (fBarView->ExpandoState() || fBarView->FullState())) {
+               itemWidth = settings->width;
+       }
+       SetMaxContentWidth(itemWidth);
 
        TeamMenuItemMap items;
        int32 itemCount = CountItems();
@@ -484,7 +474,6 @@ TExpandoMenuBar::BuildItems()
                        items[BString(item->Signature()).ToLower()] = item;
        }
 
-       desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
        if (settings->sortRunningApps)
                fTeamList.SortItems(TTeamMenu::CompareByName);
 
@@ -504,7 +493,7 @@ TExpandoMenuBar::BuildItems()
                        } else
                                AddItem(item);
 
-                       if (fFirstBuild && fVertical && 
settings->expandNewTeams)
+                       if (fFirstBuild && Vertical() && 
settings->expandNewTeams)
                                item->ToggleExpandState(true);
                } else {
                        // existing team, update info and add it
@@ -525,7 +514,7 @@ TExpandoMenuBar::BuildItems()
                        bool hasWindowItems = false;
                        while ((windowItem = dynamic_cast<TWindowMenuItem*>(
                                        
(BMenuItem*)(itemList.ItemAt(++index)))) != NULL) {
-                               if (fVertical)
+                               if (Vertical())
                                        AddItem(windowItem);
                                else {
                                        delete windowItem;
@@ -534,7 +523,7 @@ TExpandoMenuBar::BuildItems()
                        }
 
                        // unexpand if turn off show team expander
-                       if (fVertical && !settings->superExpando && 
item->IsExpanded())
+                       if (Vertical() && !settings->superExpando && 
item->IsExpanded())
                                item->ToggleExpandState(false);
 
                        if (hasWindowItems) {
@@ -549,9 +538,10 @@ TExpandoMenuBar::BuildItems()
                // If we're empty, BMenuBar::AttachedToWindow() resizes us to 
some
                // weird value - we just override it again
                ResizeTo(gMinimumWindowWidth, 0);
+       } else {
+               // first build isn't complete until we've gotten here with an 
item
+               fFirstBuild = false;
        }
-
-       fFirstBuild = false;
 }
 
 
@@ -583,9 +573,9 @@ TTeamMenuItem*
 TExpandoMenuBar::TeamItemAtPoint(BPoint point, BMenuItem** _item)
 {
        TTeamMenuItem* lastApp = NULL;
-       int32 count = CountItems();
+       int32 itemCount = CountItems();
 
-       for (int32 i = 0; i < count; i++) {
+       for (int32 i = 0; i < itemCount; i++) {
                BMenuItem* item = ItemAt(i);
 
                if (dynamic_cast<TTeamMenuItem*>(item) != NULL)
@@ -615,7 +605,7 @@ TExpandoMenuBar::AddTeam(BList* team, BBitmap* icon, char* 
name,
        TTeamMenuItem* item = new TTeamMenuItem(team, icon, name, signature);
 
        desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
-       if (settings->trackerAlwaysFirst
+       if (settings != NULL && settings->trackerAlwaysFirst
                && strcasecmp(signature, kTrackerSignature) == 0) {
                AddItem(item, 0);
        } else if (settings->sortRunningApps) {
@@ -649,8 +639,10 @@ TExpandoMenuBar::AddTeam(BList* team, BBitmap* icon, char* 
name,
        } else
                AddItem(item);
 
-       if (fVertical && settings->superExpando && settings->expandNewTeams)
+       if (Vertical() && settings != NULL && settings->superExpando
+               && settings->expandNewTeams) {
                item->ToggleExpandState(false);
+       }
 
        SizeWindow(1);
        Window()->UpdateIfNeeded();
@@ -721,76 +713,92 @@ TExpandoMenuBar::RemoveTeam(team_id team, bool partial)
 void
 TExpandoMenuBar::CheckItemSizes(int32 delta, bool reset)
 {
-       if (fVertical)
+       // horizontal only
+       if (fBarView == NULL || Vertical())
                return;
 
+       // minimum two items before size overrun can occur
        int32 itemCount = CountItems();
-       TTeamMenuItem* item = static_cast<TTeamMenuItem*>(ItemAt(0));
-       if (itemCount < 1 || item == NULL)
+       if (itemCount < 2)
                return;
 
-       int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize();
-       float iconOnlyWidth = kIconPadding + iconSize + kIconPadding;
-
-       float maxItemWidth;
-       float minItemWidth;
-       if (static_cast<TBarApp*>(be_app)->Settings()->hideLabels) {
-               maxItemWidth = iconOnlyWidth;
-               minItemWidth = iconOnlyWidth - kIconPadding * 3 / 4;
-       } else {
-               float labelWidth = gMinimumWindowWidth;
-               labelWidth += (be_plain_font->Size() - 12) * 4 + iconSize
-                       - kMinimumIconSize;
-               maxItemWidth = iconOnlyWidth + labelWidth;
-               minItemWidth = iconOnlyWidth + floorf(labelWidth / 4);
-       }
-
-       float menuWidth = fDeskbarMenuWidth + kSepItemWidth
-               + maxItemWidth * itemCount;
-       float maxWidth = fBarView->DragRegion()->Frame().left - 1
-               - fDeskbarMenuWidth - kSepItemWidth;
+       float minItemWidth = MinHorizontalItemWidth();
+       float maxItemWidth = MaxHorizontalItemWidth();
+       float maxMenuWidth = maxItemWidth * itemCount;
+       float maxWidth = MaxHorizontalWidth();
+       bool tooWide = maxMenuWidth > maxWidth;
 
-       float newWidth = -1.0f;
+       // start at max width
+       float newItemWidth = maxItemWidth;
 
-       if (delta >= 0 && menuWidth > maxWidth) {
-               fOverflow = true;
-               reset = true;
-               newWidth = floorf(maxWidth / CountItems());
-       } else if (reset || (delta < 0 && fOverflow)) {
-               reset = true;
-               if (menuWidth > maxWidth)
-                       newWidth = floorf(maxWidth / CountItems());
+       if (delta < 0 && fOverflow) {
+               // removing an item, check if menu is still too wide
+               if (tooWide)
+                       newItemWidth = floorf(maxWidth / itemCount);
                else
-                       newWidth = maxItemWidth;
+                       newItemWidth = maxItemWidth;
+       } else if (tooWide) {
+               fOverflow = true;
+               newItemWidth = std::min(floorf(maxWidth / itemCount), 
maxItemWidth);
        }
 
-       if (reset) {
-               if (newWidth > maxItemWidth)
-                       newWidth = maxItemWidth;
-               else if (newWidth < minItemWidth)
-                       newWidth = minItemWidth;
+       // see if we should grow items
+       fUnderflow = delta < 0 && newItemWidth < maxItemWidth;
 
-               SetMaxContentWidth(newWidth);
-               if (newWidth == maxItemWidth)
-                       fOverflow = false;
+       if (fOverflow || fUnderflow || fFirstBuild || reset) {
+               // clip within limits
+               if (newItemWidth > maxItemWidth)
+                       newItemWidth = maxItemWidth;
+               else if (newItemWidth < minItemWidth)
+                       newItemWidth = minItemWidth;
 
-               InvalidateLayout();
+               SetMaxContentWidth(newItemWidth);
+               if (newItemWidth == maxItemWidth)
+                       fOverflow = false;
 
                for (int32 index = 0; ; index++) {
                        TTeamMenuItem* item = (TTeamMenuItem*)ItemAt(index);
                        if (item == NULL)
                                break;
 
-                       item->SetOverrideWidth(newWidth);
+                       item->SetOverrideWidth(newItemWidth);
                }
 
-               Invalidate();
-               Window()->UpdateIfNeeded();
-               fBarView->CheckForScrolling();
+               InvalidateLayout();
+
+               ResizeTo(newItemWidth * itemCount, Frame().Height());
        }
 }
 
 
+float
+TExpandoMenuBar::MinHorizontalItemWidth()
+{
+       int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize();
+       float iconOnlyWidth = iconSize + kIconPadding;
+
+       return static_cast<TBarApp*>(be_app)->Settings()->hideLabels
+               ? iconOnlyWidth
+               : (iconSize - kMinimumIconSize) + gMinimumWindowWidth
+                       + (be_plain_font->Size() - 12) * 4;
+}
+
+
+float
+TExpandoMenuBar::MaxHorizontalItemWidth()
+{
+       int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize();
+       float iconOnlyWidth = iconSize + kIconPadding;
+
+       // hide labels
+       if (static_cast<TBarApp*>(be_app)->Settings()->hideLabels)
+               return iconOnlyWidth + kIconPadding; // add an extra icon 
padding
+
+       // set max item width to 1.25x min item width
+       return floorf(MinHorizontalItemWidth() * 1.25);
+}
+
+
 menu_layout
 TExpandoMenuBar::MenuLayout() const
 {
@@ -801,7 +809,6 @@ TExpandoMenuBar::MenuLayout() const
 void
 TExpandoMenuBar::SetMenuLayout(menu_layout layout)
 {
-       fVertical = layout == B_ITEMS_IN_COLUMN;
        BPrivate::MenuPrivate(this).SetLayout(layout);
        InvalidateLayout();
 }
@@ -817,68 +824,60 @@ TExpandoMenuBar::Draw(BRect updateRect)
 void
 TExpandoMenuBar::DrawBackground(BRect updateRect)
 {
-       if (fVertical)
+       if (Vertical())
                return;
 
-       BRect bounds(Bounds());
-       rgb_color menuColor = ui_color(B_MENU_BACKGROUND_COLOR);
-       rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
-       rgb_color vlight = tint_color(menuColor, B_LIGHTEN_2_TINT);
+       SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), 1.22));
+       StrokeLine(Bounds().RightTop(), Bounds().RightBottom());
+}
 
-       int32 count = CountItems() - 1;
-       if (count >= 0)
-               bounds.left = ItemAt(count)->Frame().right + 1;
+
+/*!    Some methods to help determine if we are showing too many apps
+       and need to add or remove in scroll arrows.
+*/
+bool
+TExpandoMenuBar::CheckForSizeOverrun()
+{
+       if (Vertical())
+               return CheckForSizeOverrunVertical();
        else
-               bounds.left = 0;
+               return CheckForSizeOverrunHorizontal();
+}
 
-       if (be_control_look != NULL) {
-               SetHighColor(tint_color(menuColor, 1.22));
-               StrokeLine(bounds.LeftTop(), bounds.LeftBottom());
-               bounds.left++;
-               uint32 borders = BControlLook::B_TOP_BORDER
-                       | BControlLook::B_BOTTOM_BORDER | 
BControlLook::B_RIGHT_BORDER;
 
-               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());
-       }
+bool
+TExpandoMenuBar::CheckForSizeOverrunVertical()
+{
+       if (Window() == NULL || !Vertical())
+               return false;
+
+       return Window()->Frame().bottom > (BScreen(Window())).Frame().bottom;
+
 }
 
 
-/*!    Something to help determine if we are showing too many apps
-       need to add in scrolling functionality.
-*/
 bool
-TExpandoMenuBar::CheckForSizeOverrun()
+TExpandoMenuBar::CheckForSizeOverrunHorizontal()
 {
-       if (fVertical) {
-               if (Window() == NULL)
-                       return false;
-
-               BRect screenFrame = (BScreen(Window())).Frame();
-               return Window()->Frame().bottom > screenFrame.bottom;
-       }
+       if (fBarView == NULL || Vertical())
+               return false;
 
-       // horizontal
+       // minimum two items before size overrun can occur
        int32 itemCount = CountItems();
-       TTeamMenuItem* item = static_cast<TTeamMenuItem*>(ItemAt(0));
-       if (itemCount < 1 || item == NULL)
+       if (itemCount < 2)
                return false;
 
-       float itemWidth = item->Frame().Width();
-       if (itemWidth <= 0)
-               return false;
+       float minMenuWidth = MinHorizontalItemWidth() * itemCount;
+       float maxWidth = MaxHorizontalWidth();
+
+       return minMenuWidth > maxWidth;
+}
 
-       float menuWidth = fDeskbarMenuWidth + kSepItemWidth + itemWidth * 
itemCount;
-       float maxWidth = fBarView->DragRegion()->Frame().left - 1;
 
-       return menuWidth > maxWidth;
+float
+TExpandoMenuBar::MaxHorizontalWidth()
+{
+       return (fBarView->DragRegion()->Frame().left - 1) - kDeskbarMenuWidth;
 }
 
 
@@ -889,13 +888,19 @@ TExpandoMenuBar::SizeWindow(int32 delta)
        // code the resize method will be centered in one place
        // thus, the same behavior (good or bad) will be used
        // wherever window sizing is done
-       if (fVertical) {
-               BRect screenFrame = (BScreen(Window())).Frame();
-               fBarView->SizeWindow(screenFrame);
-               fBarView->PositionWindow(screenFrame);
-               fBarView->CheckForScrolling();
-       } else
+       if (fBarView == NULL || Window() == NULL)
+               return;
+
+       BRect screenFrame = (BScreen(Window())).Frame();
+       fBarView->SizeWindow(screenFrame);
+       fBarView->PositionWindow(screenFrame);
+
+       if (!Vertical())
                CheckItemSizes(delta);
+
+       fBarView->CheckForScrolling();
+       Window()->UpdateIfNeeded();
+       Invalidate();
 }
 
 
@@ -1067,7 +1072,7 @@ TExpandoMenuBar::_FinishedDrag(bool invoke)
                fPreviousDragTargetItem = NULL;
        }
 
-       if (!invoke && fBarView->Dragging())
+       if (!invoke && fBarView != NULL && fBarView->Dragging())
                fBarView->DragStop(true);
 }
 
diff --git a/src/apps/deskbar/ExpandoMenuBar.h 
b/src/apps/deskbar/ExpandoMenuBar.h
index ffb1e518aa..8ed2bbd5e1 100644
--- a/src/apps/deskbar/ExpandoMenuBar.h
+++ b/src/apps/deskbar/ExpandoMenuBar.h
@@ -64,7 +64,8 @@ class TTeamMenuItem;
 
 class TExpandoMenuBar : public BMenuBar {
 public:
-                                                       
TExpandoMenuBar(TBarView* barView, bool vertical);
+                                                       
TExpandoMenuBar(menu_layout layout,
+                                                               TBarView* 
barView = NULL);
 
        virtual void                    AllAttached();
        virtual void                    AttachedToWindow();
@@ -88,6 +89,9 @@ public:
 
                        void                    CheckItemSizes(int32 delta, 
bool reset = false);
 
+                       float                   MinHorizontalItemWidth();
+                       float                   MaxHorizontalItemWidth();
+
                        menu_layout             MenuLayout() const;
                        void                    SetMenuLayout(menu_layout 
layout);
 
@@ -112,13 +116,19 @@ private:
                        void                    _DoneTracking(BPoint where);
                        void                    _Track(BPoint where, uint32);
 
+                       bool                    CheckForSizeOverrunVertical();
+                       bool                    CheckForSizeOverrunHorizontal();
+
+                       float                   MaxHorizontalWidth();
+
+                       bool                    Vertical() const
+                                                               { return 
MenuLayout() == B_ITEMS_IN_COLUMN; };
 private:
                        TBarView*               fBarView;
-                       bool                    fVertical : 1;
                        bool                    fOverflow : 1;
+                       bool                    fUnderflow : 1;
                        bool                    fFirstBuild : 1;
 
-                       float                   fDeskbarMenuWidth;
                        TTeamMenuItem*  fPreviousDragTargetItem;
                        BMenuItem*              fLastMousedOverItem;
                        BMenuItem*              fLastClickedItem;
diff --git a/src/apps/deskbar/StatusView.cpp b/src/apps/deskbar/StatusView.cpp
index 462f67846e..2a311442be 100644
--- a/src/apps/deskbar/StatusView.cpp
+++ b/src/apps/deskbar/StatusView.cpp
@@ -69,6 +69,7 @@ All rights reserved.
 #include "icons.h"
 
 #include "BarApp.h"
+#include "BarMenuBar.h"
 #include "DeskbarUtils.h"
 #include "ExpandoMenuBar.h"
 #include "ResourceSet.h"
@@ -127,30 +128,37 @@ DumpList(BList* itemlist)
 
 // don't change the name of this view to anything other than "Status"!
 
-TReplicantTray::TReplicantTray(TBarView* parent, bool vertical)
+TReplicantTray::TReplicantTray(TBarView* barView)
        :
        BView(BRect(0, 0, 1, 1), "Status", B_FOLLOW_LEFT | B_FOLLOW_TOP,
                B_WILL_DRAW | B_FRAME_EVENTS),
        fTime(NULL),
-       fBarView(parent),
+       fBarView(barView),
        fShelf(new TReplicantShelf(this)),
-       fMultiRowMode(vertical),
        fAlignmentSupport(false)
 {
+       // scale replicants by font size
        fMaxReplicantHeight = std::max(kMinReplicantHeight,
                floorf(kMinReplicantHeight * be_plain_font->Size() / 12));
+       // but not bigger than TabHeight which depends on be_bold_font
+       // TODO this should only apply to mini-mode but we set it once here for 
all
+       fMaxReplicantHeight = std::min(fMaxReplicantHeight,
+               fBarView->TabHeight() - 4);
        // TODO: depends on window size... (so use something like
        // max(129, height * 3), and restrict the minimum window width for it)
+       // Use bold font because it depends on the window tab height.
        fMaxReplicantWidth = 129;
 
        fMinTrayHeight = kGutter + fMaxReplicantHeight + kGutter;
-       if (vertical)
+       if (fBarView != NULL && fBarView->Vertical()
+               && (fBarView->ExpandoState() || fBarView->FullState())) {
                fMinimumTrayWidth = gMinimumWindowWidth - kGutter - 
kDragRegionWidth;
-       else
+       } else
                fMinimumTrayWidth = kMinimumTrayWidth;
 
        // Create the time view
-       fTime = new TTimeView(fMinimumTrayWidth, fMaxReplicantHeight - 1.0);
+       fTime = new TTimeView(fMinimumTrayWidth, fMaxReplicantHeight - 1.0,
+               fBarView);
 }
 
 
@@ -183,7 +191,7 @@ TReplicantTray::AttachedToWindow()
        AddChild(fTime);
 
        fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - kTrayPadding, 
2);
-       fTime->SetOrientation(fMultiRowMode);
+               // will be moved into place later
 
        if (!((TBarApp*)be_app)->Settings()->showClock)
                fTime->Hide();
@@ -221,7 +229,8 @@ TReplicantTray::GetPreferredSize(float* preferredWidth, 
float* preferredHeight)
        float width = 0;
        float height = fMinTrayHeight;
 
-       if (fMultiRowMode) {
+       if (fBarView->Vertical()
+               && (fBarView->ExpandoState() || fBarView->FullState())) {
                width = static_cast<TBarApp*>(be_app)->Settings()->width
                        - kDragWidth - kGutter;
                if (fRightBottomReplicant.IsValid())
@@ -249,7 +258,13 @@ TReplicantTray::GetPreferredSize(float* preferredWidth, 
float* preferredHeight)
 
                // this view has a fixed minimum width
                width = std::max(kMinimumTrayWidth, width);
-               height = fBarView->TeamMenuItemHeight();
+
+               // if mini-mode set to tab height
+               // else if horizontal mode set to team menu item height
+               if (fBarView->Vertical() && fBarView->MiniState())
+                       height = std::max(fMinTrayHeight, 
fBarView->TabHeight());
+               else
+                       height = fBarView->TeamMenuItemHeight();
        }
 
        *preferredWidth = width;
@@ -424,13 +439,6 @@ TReplicantTray::ShowReplicantMenu(BPoint point)
 }
 
 
-void
-TReplicantTray::SetMultiRow(bool state)
-{
-       fMultiRowMode = state;
-}
-
-
 void
 TReplicantTray::ShowHideTime()
 {
@@ -1163,14 +1171,32 @@ TReplicantTray::AcceptAddon(BRect replicantFrame, 
BMessage* message)
 BPoint
 TReplicantTray::LocationForReplicant(int32 index, float replicantWidth)
 {
-       BPoint loc(kTrayPadding, 2);
+       BPoint loc(kTrayPadding, 0);
        if (fBarView->Vertical()) {
-               if (!fBarView->Left())
-                       loc.x += kDragWidth; // move past dragger
-       } else
-               loc.x += 1; // keeps everything lined up nicely
+               if (fBarView->MiniState())
+                       loc.y = floorf((fBarView->TabHeight() - 
fMaxReplicantHeight) / 2);
+               else if (!fBarView->Left()) {
+                       // move past dragger on right
+                       loc.x += kDragWidth;
+                       loc.y += 1;
+               }
+       } else {
+               loc.x -= 2; // keeps everything lined up nicely
+               const int32 iconSize = 
static_cast<TBarApp*>(be_app)->IconSize();
+               float yOffset = iconSize > B_MINI_ICON ? 3 : 2;
+                       // squeeze icons in there at 16x16, reduce border by 1px
+               if (fBarView->Top()) {
+                       // align top
+                       loc.y = yOffset;
+               } else {
+                       // align bottom
+                       loc.y = (fBarView->TeamMenuItemHeight() + 1)
+                               - fMaxReplicantHeight - yOffset;
+               }
+       }
 
-       if (fMultiRowMode) {
+       if (fBarView->Vertical()
+               && (fBarView->ExpandoState() || fBarView->FullState())) {
                // try to find free space in every row
                for (int32 row = 0; ; loc.y += fMaxReplicantHeight + kIconGap, 
row++) {
                        // determine free space in this row
@@ -1206,9 +1232,11 @@ TReplicantTray::LocationForReplicant(int32 index, float 
replicantWidth)
                        // check next row
                }
 
-               fTime->MoveTo(Bounds().right - fTime->Bounds().Width()
-                       - kTrayPadding, 2);
+               // move clock into place vertically centered in first row
+               fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - 
kTrayPadding,
+                       floorf((fMaxReplicantHeight - fTime->fHeight) / 2) + 1);
        } else {
+               // horizontal or mini-mode
                if (index > 0) {
                        // get the last replicant added for placement reference
                        BView* view = NULL;
@@ -1219,22 +1247,9 @@ TReplicantTray::LocationForReplicant(int32 index, float 
replicantWidth)
                        }
                }
 
-               if (fBarView->Vertical()) {
-                       // center vertically
-                       loc.y = floorf((kMenuBarHeight - fMaxReplicantHeight) / 
2) - 1;
-               } else {
-                       if (fBarView->Top()) {
-                               // align top
-                               loc.y = 3;
-                       } else {
-                               // align bottom
-                               loc.y = fBarView->TeamMenuItemHeight() - 
fMaxReplicantHeight - 2;
-                       }
-               }
-
-               // move time in place next to replicants
+               // move clock into place vertically centered next to replicants
                fTime->MoveTo(Bounds().right - fTime->Bounds().Width() - 
kTrayPadding,
-                       loc.y + (fMaxReplicantHeight - 
fTime->Bounds().Height()) / 2);
+                       loc.y + floorf((fMaxReplicantHeight - fTime->fHeight) / 
2));
        }
 
        if (loc.y > fRightBottomReplicant.top
@@ -1341,11 +1356,11 @@ TReplicantTray::SaveTimeSettings()
 /*! Draggable region that is asynchronous so that dragging does not block
        other activities.
 */
-TDragRegion::TDragRegion(TBarView* parent, BView* replicantTray)
+TDragRegion::TDragRegion(TBarView* barView, BView* replicantTray)
        :
        BControl(BRect(0, 0, 0, 0), "", "", NULL, B_FOLLOW_NONE,
-               B_WILL_DRAW | B_FRAME_EVENTS),
-       fBarView(parent),
+               B_WILL_DRAW | B_DRAW_ON_CHILDREN | B_FRAME_EVENTS),
+       fBarView(barView),
        fReplicantTray(replicantTray),
        fDragLocation(kAutoPlaceDragRegion)
 {
@@ -1357,6 +1372,8 @@ TDragRegion::AttachedToWindow()
 {
        BView::AttachedToWindow();
 
+       CalculateRegions();
+
        if (be_control_look != NULL)
                SetViewUIColor(B_MENU_BACKGROUND_COLOR, 1.1);
        else
@@ -1378,7 +1395,12 @@ TDragRegion::GetPreferredSize(float* width, float* 
height)
        else
                *width += 6;
 
-       *height += 2;
+       bool vertical = fBarView->Vertical();
+       bool expandoOrFull = fBarView->ExpandoState() || fBarView->FullState();
+       if (vertical && expandoOrFull)
+               *height += 3; // add a pixel for an extra border on top
+       else
+               *height += 2; // all other modes have a 1px border on top and 
bottom
 }
 
 
@@ -1389,60 +1411,45 @@ TDragRegion::Draw(BRect updateRect)
        rgb_color hilite = tint_color(menuColor, B_DARKEN_1_TINT);
        rgb_color ldark = tint_color(menuColor, 1.02);
        rgb_color dark = tint_color(menuColor, B_DARKEN_2_TINT);
-       rgb_color vvdark = tint_color(menuColor, B_DARKEN_4_TINT);
-       rgb_color light = tint_color(menuColor, B_LIGHTEN_2_TINT);
 
        BRect frame(Bounds());
        BeginLineArray(4);
 
-       if (be_control_look != NULL) {
-               if (fBarView->Vertical()) {
-                       AddLine(frame.LeftTop(), frame.RightTop(), dark);
-                       AddLine(BPoint(frame.left, frame.top + 1),
-                               BPoint(frame.right, frame.top + 1), ldark);
-                       AddLine(frame.LeftBottom(), frame.RightBottom(), 
hilite);
-               } else if (fBarView->AcrossTop() || fBarView->AcrossBottom()) {
-                       AddLine(frame.LeftTop(),
-                               BPoint(frame.left, frame.bottom), dark);
-                       AddLine(BPoint(frame.left + 1, frame.top + 1),
-                               BPoint(frame.right - 1, frame.top + 1), light);
-                       AddLine(BPoint(frame.right, frame.top + 2),
-                               BPoint(frame.right, frame.bottom), hilite);
-                       AddLine(BPoint(frame.left + 1, frame.bottom),
-                               BPoint(frame.right - 1, frame.bottom), hilite);
-               }
-       } else {
-               if (fBarView->Vertical()) {
-                       AddLine(frame.LeftTop(), frame.RightTop(), light);
-                       AddLine(frame.LeftTop(), frame.LeftBottom(), light);
-                       AddLine(frame.RightBottom(), frame.RightTop(), hilite);
-               } else if (fBarView->AcrossTop()) {
-                       AddLine(BPoint(frame.left, frame.top + 1),
-                               BPoint(frame.right - 1, frame.top + 1), light);
-                       AddLine(frame.RightTop(), frame.RightBottom(), vvdark);
-                       AddLine(BPoint(frame.right - 1, frame.top + 2),
-                               BPoint(frame.right - 1, frame.bottom - 1), 
hilite);
-                       AddLine(frame.LeftBottom(),
-                               BPoint(frame.right - 1, frame.bottom), hilite);
-               } else if (fBarView->AcrossBottom()) {
-                       AddLine(BPoint(frame.left, frame.top + 1),
-                               BPoint(frame.right - 1, frame.top + 1), light);
-                       AddLine(frame.LeftBottom(), frame.RightBottom(), 
hilite);
-                       AddLine(frame.RightTop(), frame.RightBottom(), vvdark);
-                       AddLine(BPoint(frame.right - 1, frame.top + 1),
-                               BPoint(frame.right - 1, frame.bottom - 1), 
hilite);
+       if (fBarView->Vertical()
+               && (fBarView->ExpandoState() || fBarView->FullState())) {
+               // vertical expando or full state, draw 2 lines at the top
+               AddLine(frame.LeftTop(), frame.RightTop(), dark);
+               AddLine(BPoint(frame.left, frame.top + 1),
+                       BPoint(frame.right, frame.top + 1), ldark);
+               // add hilight along bottom
+               AddLine(BPoint(frame.left + 1, frame.bottom),
+                       BPoint(frame.right - 1, frame.bottom), hilite);
+       } else if ((fBarView->Vertical() && fBarView->MiniState())
+               || fBarView->AcrossTop() || fBarView->AcrossBottom()) {
+               // mini-mode or horizontal, draw hilight along top left and 
bottom
+               AddLine(frame.LeftTop(), frame.RightTop(), hilite);
+               AddLine(BPoint(frame.left, frame.top + 1), frame.LeftBottom(), 
hilite);
+               if (!fBarView->Vertical()) {
+                       // only draw bottom hilight in horizontal mode
+                       AddLine(BPoint(frame.left + 1, frame.bottom - 3),
+                               BPoint(frame.right - 1, frame.bottom - 3), 
hilite);
                }
        }
 
        EndLineArray();
+}
+
 
+void
+TDragRegion::DrawAfterChildren(BRect updateRect)
+{
        if (fDragLocation != kDontDrawDragRegion || fDragLocation != 
kNoDragRegion)
-               DrawDragRegion();
+               DrawDragger();
 }
 
 
 void
-TDragRegion::DrawDragRegion()
+TDragRegion::DrawDragger()
 {
        BRect dragRegion(DragRegion());
 
@@ -1452,26 +1459,37 @@ TDragRegion::DrawDragRegion()
                // draw drag region highlighted if tracking mouse
                menuHilite = tint_color(menuColor, B_HIGHLIGHT_BACKGROUND_TINT);
                SetHighColor(menuHilite);
-               FillRect(dragRegion);
+               FillRect(dragRegion.InsetByCopy(0, -1));
        } else {
                SetHighColor(menuColor);
-               FillRect(dragRegion);
+               FillRect(dragRegion.InsetByCopy(0, 1));
        }
 
        rgb_color vdark = tint_color(menuHilite, B_DARKEN_3_TINT);
        rgb_color light = tint_color(menuHilite, B_LIGHTEN_2_TINT);
 
-       BeginLineArray(dragRegion.IntegerHeight());
+       rgb_color dark = tint_color(menuHilite, B_DARKEN_2_TINT);
+
+       BeginLineArray(dragRegion.IntegerHeight() + 2);
        BPoint where;
        where.x = floorf((dragRegion.left + dragRegion.right) / 2 + 0.5) - 1;
        where.y = dragRegion.top + 2;
 
-       while (where.y + 1 <= dragRegion.bottom) {
+       while (where.y + 1 <= dragRegion.bottom - 2) {
                AddLine(where, where, vdark);
                AddLine(where + BPoint(1, 1), where + BPoint(1, 1), light);
 
                where.y += 3;
        }
+
+       if (fBarView != NULL && fBarView->Vertical() && fBarView->MiniState()
+               && !fBarView->Top()) {
+               // extend bottom border in bottom mini-mode
+               AddLine(BPoint(dragRegion.left, dragRegion.bottom - 2),
+                       BPoint(dragRegion.right, dragRegion.bottom - 2),
+                               IsTracking() ? menuHilite : dark);
+       }
+
        EndLineArray();
 }
 
@@ -1479,16 +1497,7 @@ TDragRegion::DrawDragRegion()
 BRect
 TDragRegion::DragRegion() const
 {
-       float kTopBottomInset = 2;
-       float kLeftRightInset = 1;
-       if (be_control_look != NULL) {
-               kTopBottomInset = 1;
-               kLeftRightInset = 0;
-       }
-
        BRect dragRegion(Bounds());
-       dragRegion.top += kTopBottomInset;
-       dragRegion.bottom -= kTopBottomInset;
 
        bool placeOnLeft = false;
        if (fDragLocation == kAutoPlaceDragRegion) {
@@ -1499,13 +1508,10 @@ TDragRegion::DragRegion() const
        } else
                placeOnLeft = fDragLocation == kDragRegionLeft;
 
-       if (placeOnLeft) {
-               dragRegion.left += kLeftRightInset;
+       if (placeOnLeft)
                dragRegion.right = dragRegion.left + kDragWidth;
-       } else {
-               dragRegion.right += kLeftRightInset;
+       else
                dragRegion.left = dragRegion.right - kDragWidth;
-       }
 
        return dragRegion;
 }
@@ -1555,11 +1561,11 @@ TDragRegion::MouseUp(BPoint where)
 
 
 bool
-TDragRegion::SwitchModeForRect(BPoint where, BRect rect,
+TDragRegion::SwitchModeForRegion(BPoint where, BRegion region,
        bool newVertical, bool newLeft, bool newTop, int32 newState)
 {
-       if (!rect.Contains(where)) {
-               // not our rect
+       if (!region.Contains(where)) {
+               // not our region
                return false;
        }
 
@@ -1576,81 +1582,114 @@ TDragRegion::SwitchModeForRect(BPoint where, BRect 
rect,
 
 
 void
-TDragRegion::MouseMoved(BPoint where, uint32 code, const BMessage* message)
+TDragRegion::CalculateRegions()
 {
-       if (IsTracking()) {
-               BScreen screen;
-               BRect frame = screen.Frame();
-
-               float hDivider = frame.Width() / 6;
-               hDivider = (hDivider < gMinimumWindowWidth + 10)
-                       ? gMinimumWindowWidth + 10 : hDivider;
-               float miniDivider = frame.top + kMiniHeight + 10;
-               float vDivider = frame.Height() / 2;
-#ifdef FULL_MODE
-               float thirdScreen = frame.Height() / 3;
-#endif
-               BRect topLeft(frame.left, frame.top, frame.left + hDivider,
-                       miniDivider);
-               BRect topMiddle(frame.left + hDivider, frame.top, frame.right
-                       - hDivider, vDivider);
-               BRect topRight(frame.right - hDivider, frame.top, frame.right,
-                       miniDivider);
+       const BRect screenFrame((BScreen(Window())).Frame());
+
+       float menuBarHeight = fBarView->BarMenuBar()->Frame().Height();
+       float hDivider = floorf(screenFrame.Width() / 4);
+       float halfScreen = floorf(screenFrame.Height() / 2);
+
+       // corners
+       fTopLeft.Set(BRect(screenFrame.left, screenFrame.top,
+               screenFrame.left + hDivider, screenFrame.top + menuBarHeight));
+       fTopRight.Set(BRect(screenFrame.right - hDivider, screenFrame.top,
+               screenFrame.right, screenFrame.top + menuBarHeight));
+       fBottomLeft.Set(BRect(screenFrame.left, screenFrame.bottom - 
menuBarHeight,
+               screenFrame.left + hDivider, screenFrame.bottom));
+       fBottomRight.Set(BRect(screenFrame.right - hDivider,
+               screenFrame.bottom - menuBarHeight, screenFrame.right,
+               screenFrame.bottom));
+
+       // left/right expando
+       fMiddleLeft.Set(BRect(screenFrame.left, screenFrame.top,
+               screenFrame.left + hDivider, screenFrame.bottom));
+       fMiddleLeft.Exclude(&fTopLeft);
+       fMiddleLeft.Exclude(&fBottomLeft);
+
+       fMiddleRight.Set(BRect(screenFrame.right - hDivider,
+               screenFrame.top, screenFrame.right, screenFrame.bottom));
+       fMiddleRight.Exclude(&fTopRight);
+       fMiddleRight.Exclude(&fBottomRight);
 
 #ifdef FULL_MODE
-               vDivider = miniDivider + thirdScreen;
+       // left/right full
+       fLeftSide.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
+               screenFrame.left + hDivider, screenFrame.bottom));
+       fLeftSide.Exclude(&fBottomLeft);
+       fMiddleLeft.Exclude(&fLeftSide);
+
+       fRightSide.Set(BRect(screenFrame.right - hDivider,
+               screenFrame.bottom - halfScreen, screenFrame.right,
+               screenFrame.bottom));
+       fRightSide.Exclude(&fBottomRight);
+       fMiddleRight.Exclude(&fRightSide);
 #endif
-               BRect middleLeft(frame.left, miniDivider, frame.left + hDivider,
-                       vDivider);
-               BRect middleRight(frame.right - hDivider, miniDivider, 
frame.right,
-                       vDivider);
 
-#ifdef FULL_MODE
-               BRect leftSide(frame.left, vDivider, frame.left + hDivider,
-                       frame.bottom - thirdScreen);
-               BRect rightSide(frame.right - hDivider, vDivider, frame.right,
-                       frame.bottom - thirdScreen);
+       // top/bottom
+       BRect leftSideRect(screenFrame.left, screenFrame.top,
+               screenFrame.left + hDivider, screenFrame.bottom);
+       BRect rightSideRect(screenFrame.right - hDivider, screenFrame.top,
+               screenFrame.right, screenFrame.bottom);
+
+       fTopHalf.Set(BRect(screenFrame.left, screenFrame.top, screenFrame.right,
+               screenFrame.top + halfScreen));
+       fTopHalf.Exclude(leftSideRect);
+       fTopHalf.Exclude(rightSideRect);
+
+       fBottomHalf.Set(BRect(screenFrame.left, screenFrame.bottom - halfScreen,
+               screenFrame.right, screenFrame.bottom));
+       fBottomHalf.Exclude(leftSideRect);
+       fBottomHalf.Exclude(rightSideRect);
+}
 
-               vDivider = frame.bottom - thirdScreen;
-#endif
-               BRect bottomLeft(frame.left, vDivider, frame.left + hDivider,
-                       frame.bottom);
-               BRect bottomMiddle(frame.left + hDivider, vDivider, frame.right
-                       - hDivider, frame.bottom);
-               BRect bottomRight(frame.right - hDivider, vDivider, frame.right,
-                       frame.bottom);
-
-               if (where != fPreviousPosition) {
-                       fPreviousPosition = where;
-                       ConvertToScreen(&where);
-
-                       // use short circuit evaluation for convenience
-                       if (SwitchModeForRect(where, topLeft, true, true, true, 
kMiniState)
-                               || SwitchModeForRect(where, topMiddle, false, 
true, true,
-                                       kExpandoState)
-                               || SwitchModeForRect(where, topRight, true, 
false, true,
-                                       kMiniState)
-                               || SwitchModeForRect(where, middleLeft, true, 
true, true,
-                                       kExpandoState)
-                               || SwitchModeForRect(where, middleRight, true, 
false, true,
-                                       kExpandoState)
 
+void
+TDragRegion::MouseMoved(BPoint where, uint32 transit,
+       const BMessage* dragMessage)
+{
+       if (!IsTracking() || where == fPreviousPosition)
+               return BControl::MouseMoved(where, transit, dragMessage);
+
+       fPreviousPosition = where;
+
+       // TODO: can't trust the passed in where param, get screen_where from
+       // Window()->CurrentMessage() instead, why is this necessary?
+       BPoint whereScreen;
+       BMessage* currentMessage = Window()->CurrentMessage();
+       if (currentMessage == NULL || currentMessage->FindPoint("screen_where",
+                       &whereScreen) != B_OK) {
+               whereScreen = ConvertToScreen(where);
+       }
+
+       // use short circuit evaluation for convenience
+       if (// mini
+                  SwitchModeForRegion(whereScreen, fTopLeft, true, true, true,
+                       kMiniState)
+               || SwitchModeForRegion(whereScreen, fTopRight, true, false, 
true,
+                       kMiniState)
+               || SwitchModeForRegion(whereScreen, fBottomLeft, true, true, 
false,
+                       kMiniState)
+               || SwitchModeForRegion(whereScreen, fBottomRight, true, false, 
false,
+                       kMiniState)
+               // expando
+               || SwitchModeForRegion(whereScreen, fMiddleLeft, true, true, 
true,
+                       kExpandoState)
+               || SwitchModeForRegion(whereScreen, fMiddleRight, true, false, 
true,
+                       kExpandoState)
 #ifdef FULL_MODE
-                               || SwitchModeForRect(where, leftSide, true, 
true, true,
-                                       kFullState)
-                               || SwitchModeForRect(where, rightSide, true, 
false, true,
-                                       kFullState)
+               // full
+               || SwitchModeForRegion(whereScreen, fLeftSide, true, true, true,
+                       kFullState)
+               || SwitchModeForRegion(whereScreen, fRightSide, true, false, 
true,
+                       kFullState)
 #endif
-                               || SwitchModeForRect(where, bottomLeft, true, 
true, false,
-                                       kMiniState)
-                               || SwitchModeForRect(where, bottomMiddle, 
false, true, false,
-                                       kExpandoState)
-                               || SwitchModeForRect(where, bottomRight, true, 
false, false,
-                                       kMiniState))
-                               ;
-               }
-       } else
-               BControl::MouseMoved(where, code, message);
+               // horizontal
+               || SwitchModeForRegion(whereScreen, fTopHalf, false, true, true,
+                       kExpandoState)
+               || SwitchModeForRegion(whereScreen, fBottomHalf, false, true, 
false,
+                       kExpandoState)
+       );
 }
 
 
@@ -1784,34 +1823,33 @@ void
 TResizeControl::MouseMoved(BPoint where, uint32 code,
        const BMessage* dragMessage)
 {
-       if (fBarView->Vertical()) {
-               if (IsResizing()) {
-                       float windowWidth = Window()->Frame().Width();
-                       float delta = 0;
-                       BPoint whereScreen = ConvertToScreen(where);
-
-                       if (fBarView->Left()) {
-                               delta = whereScreen.x - Window()->Frame().right;
-                               if (delta > 0 && windowWidth >= 
gMaximumWindowWidth)
-                                       ; // do nothing
-                               else if (delta < 0 && windowWidth <= 
gMinimumWindowWidth)
-                                       ; // do nothing
-                               else
-                                       Window()->ResizeBy(delta, 0);
-                       } else {
-                               delta = Window()->Frame().left - whereScreen.x;
-                               if (delta > 0 && windowWidth >= 
gMaximumWindowWidth)
-                                       ; // do nothing
-                               else if (delta < 0 && windowWidth <= 
gMinimumWindowWidth)
-                                       ; // do nothing
-                               else {
-                                       Window()->MoveBy(delta, 0);
-                                       Window()->ResizeBy(delta, 0);
-                               }
+       if (IsResizing() && fBarView->Vertical()
+               && (fBarView->ExpandoState() || fBarView->FullState())) {
+               float windowWidth = Window()->Frame().Width();
+               float delta = 0;
+               BPoint whereScreen = ConvertToScreen(where);
+
+               if (fBarView->Left()) {
+                       delta = whereScreen.x - Window()->Frame().right;
+                       if (delta > 0 && windowWidth >= gMaximumWindowWidth)
+                               ; // do nothing
+                       else if (delta < 0 && windowWidth <= 
gMinimumWindowWidth)
+                               ; // do nothing
+                       else
+                               Window()->ResizeBy(delta, 0);
+               } else {
+                       delta = Window()->Frame().left - whereScreen.x;
+                       if (delta > 0 && windowWidth >= gMaximumWindowWidth)
+                               ; // do nothing
+                       else if (delta < 0 && windowWidth <= 
gMinimumWindowWidth)
+                               ; // do nothing
+                       else {
+                               Window()->MoveBy(delta, 0);
+                               Window()->ResizeBy(delta, 0);
                        }
-
-                       windowWidth = Window()->Frame().Width();
                }
+
+               windowWidth = Window()->Frame().Width();
        }
 
        BControl::MouseMoved(where, code, dragMessage);
diff --git a/src/apps/deskbar/StatusView.h b/src/apps/deskbar/StatusView.h
index aa9326f576..1225a9212d 100644
--- a/src/apps/deskbar/StatusView.h
+++ b/src/apps/deskbar/StatusView.h
@@ -38,6 +38,7 @@ All rights reserved.
 
 #include <Control.h>
 #include <Node.h>
+#include <Region.h>
 #include <Query.h>
 #include <Shelf.h>
 #include <View.h>
@@ -46,6 +47,8 @@ All rights reserved.
 #include "TimeView.h"
 
 
+//#define FULL_MODE
+
 const float kDragWidth = 4.0f;
 const float kMinReplicantHeight = 16.0f;
 const float kMinReplicantWidth = 16.0f;
@@ -79,8 +82,7 @@ class TReplicantShelf;
 
 class TReplicantTray : public BView {
 public:
-                                                                       
TReplicantTray(TBarView* barView,
-                                                                               
bool vertical);
+                                                                       
TReplicantTray(TBarView* barView);
                virtual                                         
~TReplicantTray();
 
                virtual void                            AttachedToWindow();
@@ -92,10 +94,6 @@ public:
                                void                            
AdjustPlacement();
                                void                            
ShowReplicantMenu(BPoint);
 
-                               void                            
SetMultiRow(bool state);
-                               bool                            IsMultiRow() 
const
-                                                                               
{ return fMultiRowMode; }
-
                                TTimeView*                      Time() const { 
return fTime; }
                                void                            ShowHideTime();
 
@@ -181,7 +179,6 @@ private:
                                float                           
fMaxReplicantHeight;
                                float                           fMinTrayHeight;
 
-                               bool                            fMultiRowMode;
                                float                           
fMinimumTrayWidth;
 
                                bool                            
fAlignmentSupport;
@@ -209,26 +206,43 @@ public:
        virtual void AttachedToWindow();
        virtual void GetPreferredSize(float*, float*);
        virtual void Draw(BRect);
+       virtual void DrawAfterChildren(BRect);
        virtual void MouseDown(BPoint);
        virtual void MouseUp(BPoint);
        virtual void MouseMoved(BPoint, uint32, const BMessage*);
 
-       void DrawDragRegion();
        BRect DragRegion() const;
 
-       bool SwitchModeForRect(BPoint mouse, BRect rect,
+       bool SwitchModeForRegion(BPoint where, BRegion region,
                bool newVertical, bool newLeft, bool newTop, int32 newState);
+       void CalculateRegions();
 
        int32 DragRegionLocation() const;
        void SetDragRegionLocation(int32);
 
        bool IsDragging() { return IsTracking(); };
 
+private:
+       void DrawDragger();
+
 private:
        TBarView* fBarView;
        BView* fReplicantTray;
        BPoint fPreviousPosition;
        int32 fDragLocation;
+
+       BRegion fTopLeft;
+       BRegion fTopRight;
+       BRegion fBottomLeft;
+       BRegion fBottomRight;
+       BRegion fMiddleLeft;
+       BRegion fMiddleRight;
+#ifdef FULL_MODE
+       BRegion fLeftSide;
+       BRegion fRightSide;
+#endif
+       BRegion fTopHalf;
+       BRegion fBottomHalf;
 };
 
 class TResizeControl : public BControl {
diff --git a/src/apps/deskbar/TeamMenu.cpp b/src/apps/deskbar/TeamMenu.cpp
index 2816fe4847..fb8ed4acf8 100644
--- a/src/apps/deskbar/TeamMenu.cpp
+++ b/src/apps/deskbar/TeamMenu.cpp
@@ -36,11 +36,13 @@ All rights reserved.
 
 #include "TeamMenu.h"
 
+#include <algorithm>
 #include <strings.h>
 
 #include <Application.h>
 #include <Collator.h>
 #include <Debug.h>
+#include <Mime.h>
 #include <Roster.h>
 
 #include "BarApp.h"
@@ -51,12 +53,16 @@ All rights reserved.
 #include "TeamMenuItem.h"
 
 
+const float kIconPadding = 8.0f;
+
+
 //     #pragma mark - TTeamMenuItem
 
 
-TTeamMenu::TTeamMenu()
+TTeamMenu::TTeamMenu(TBarView* barView)
        :
-       BMenu("Team Menu")
+       BMenu("Team Menu"),
+       fBarView(barView)
 {
        SetItemMargins(0.0f, 0.0f, 0.0f, 0.0f);
        SetFont(be_plain_font);
@@ -85,22 +91,55 @@ TTeamMenu::AttachedToWindow()
        BList teamList;
        TBarApp::Subscribe(self, &teamList);
 
-       TBarView* barview = (dynamic_cast<TBarApp*>(be_app))->BarView();
-       bool dragging = barview && barview->Dragging();
+       bool dragging = fBarView != NULL && fBarView->Dragging();
+       desk_settings* settings = static_cast<TBarApp*>(be_app)->Settings();
        int32 iconSize = static_cast<TBarApp*>(be_app)->IconSize();
-       desk_settings* settings = ((TBarApp*)be_app)->Settings();
+       float iconOnlyWidth = iconSize + kIconPadding;
+
+       // calculate the minimum item width based on font and icon size
+       float minItemWidth = 0;
+       if (settings->hideLabels) {
+               minItemWidth = std::max(floorf(gMinimumWindowWidth / 2),
+                       iconOnlyWidth);
+       } else {
+               float labelWidth = gMinimumWindowWidth - iconOnlyWidth
+                       + (be_plain_font->Size() - 12) * 4;
+               if (iconSize <= B_LARGE_ICON) // label wraps after 32x32
+                       labelWidth += iconSize - kMinimumIconSize;
+               minItemWidth = iconOnlyWidth + labelWidth;
+       }
+
+       float maxItemWidth = minItemWidth;
+
+       int32 itemCount = teamList.CountItems();
+       if (!settings->hideLabels) {
+               // go through list and find the widest label
+               for (int32 i = 0; i < itemCount; i++) {
+                       BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i);
+                       float labelWidth = StringWidth(barInfo->name);
+                       // label wraps after 32x32
+                       float itemWidth = iconSize > B_LARGE_ICON
+                               ? std::max(labelWidth, iconOnlyWidth)
+                               : labelWidth + iconOnlyWidth + kMinimumIconSize
+                                       + (be_plain_font->Size() - 12) * 4;
+                       maxItemWidth = std::max(maxItemWidth, itemWidth);
+               }
+
+               // but not too wide
+               maxItemWidth = std::min(maxItemWidth, gMaximumWindowWidth);
+       }
 
-       float width = gMinimumWindowWidth - iconSize - 4;
+       SetMaxContentWidth(maxItemWidth);
 
        if (settings->sortRunningApps)
                teamList.SortItems(TTeamMenu::CompareByName);
 
-       int32 count = teamList.CountItems();
-       for (int32 i = 0; i < count; i++) {
+       // go through list and add the items
+       for (int32 i = 0; i < itemCount; i++) {
                // add items back
                BarTeamInfo* barInfo = (BarTeamInfo*)teamList.ItemAt(i);
                TTeamMenuItem* item = new TTeamMenuItem(barInfo->teams,
-                       barInfo->icon, barInfo->name, barInfo->sig, width, -1);
+                       barInfo->icon, barInfo->name, barInfo->sig, 
maxItemWidth);
 
                if (settings->trackerAlwaysFirst
                        && strcasecmp(barInfo->sig, kTrackerSignature) == 0) {
@@ -109,15 +148,14 @@ TTeamMenu::AttachedToWindow()
                        AddItem(item);
 
                if (dragging && item != NULL) {
-                       bool canhandle = 
(dynamic_cast<TBarApp*>(be_app))->BarView()->
-                               AppCanHandleTypes(item->Signature());
+                       bool canhandle = 
fBarView->AppCanHandleTypes(item->Signature());
                        if (item->IsEnabled() != canhandle)
                                item->SetEnabled(canhandle);
 
                        BMenu* menu = item->Submenu();
                        if (menu != NULL) {
-                               menu->SetTrackingHook(barview->MenuTrackingHook,
-                                       barview->GetTrackingHookData());
+                               
menu->SetTrackingHook(fBarView->MenuTrackingHook,
+                                       fBarView->GetTrackingHookData());
                        }
                }
        }
@@ -128,11 +166,11 @@ TTeamMenu::AttachedToWindow()
                AddItem(item);
        }
 
-       if (dragging && barview->LockLooper()) {
-               SetTrackingHook(barview->MenuTrackingHook,
-                       barview->GetTrackingHookData());
-               barview->DragStart();
-               barview->UnlockLooper();
+       if (dragging && fBarView->LockLooper()) {
+               SetTrackingHook(fBarView->MenuTrackingHook,
+                       fBarView->GetTrackingHookData());
+               fBarView->DragStart();
+               fBarView->UnlockLooper();
        }
 
        BMenu::AttachedToWindow();
@@ -142,11 +180,10 @@ TTeamMenu::AttachedToWindow()
 void
 TTeamMenu::DetachedFromWindow()
 {
-       TBarView* barView = (dynamic_cast<TBarApp*>(be_app))->BarView();
-       if (barView != NULL) {
-               BLooper* looper = barView->Looper();
+       if (fBarView != NULL) {
+               BLooper* looper = fBarView->Looper();
                if (looper != NULL && looper->Lock()) {
-                       barView->DragStop();
+                       fBarView->DragStop();
                        looper->Unlock();
                }
        }
diff --git a/src/apps/deskbar/TeamMenu.h b/src/apps/deskbar/TeamMenu.h
index 0c3ff41c9f..552ab0e9e4 100644
--- a/src/apps/deskbar/TeamMenu.h
+++ b/src/apps/deskbar/TeamMenu.h
@@ -44,15 +44,19 @@ All rights reserved.
 #include <Menu.h>
 
 
+class TBarView;
+
 class TTeamMenu : public BMenu {
 public:
-                                                       TTeamMenu();
+                                                       TTeamMenu(TBarView* 
barView = NULL);
 
                        void                    AttachedToWindow();
                        void                    DetachedFromWindow();
 
        static  int                             CompareByName(const void* first,
                                                                const void* 
second);
+private:
+                       TBarView*               fBarView;
 };
 
 
diff --git a/src/apps/deskbar/TeamMenuItem.cpp 
b/src/apps/deskbar/TeamMenuItem.cpp
index fd9bf4e8b1..69c8ed9441 100644
--- a/src/apps/deskbar/TeamMenuItem.cpp
+++ b/src/apps/deskbar/TeamMenuItem.cpp
@@ -157,16 +157,8 @@ TTeamMenuItem::GetContentSize(float* width, float* height)
                        else
                                *width = gMinimumWindowWidth - 
(kDragRegionWidth + kGutter) * 2;
                } else if (!fBarView->Vertical()) {
-                       if (hideLabels)
-                               *width = iconOnlyWidth;
-                       else {
-                               float labelWidth = gMinimumWindowWidth;
-                               BFont font;
-                               Menu()->GetFont(&font);
-                               labelWidth += (font.Size() - 12) * 4 + iconSize 
- 16;
-                                       // do font and icon scaling
-                               *width = iconOnlyWidth + labelWidth;
-                       }
+                       TExpandoMenuBar* menu = 
static_cast<TExpandoMenuBar*>(Menu());
+                       *width = menu->MaxHorizontalItemWidth();
                } else
                        *width = 
static_cast<TBarApp*>(be_app)->Settings()->width;
        }
diff --git a/src/apps/deskbar/TimeView.cpp b/src/apps/deskbar/TimeView.cpp
index 3051b326c4..3cc669b480 100644
--- a/src/apps/deskbar/TimeView.cpp
+++ b/src/apps/deskbar/TimeView.cpp
@@ -66,15 +66,15 @@ static const float kHMargin = 2.0;
 #define B_TRANSLATION_CONTEXT "TimeView"
 
 
-TTimeView::TTimeView(float maxWidth, float height)
+TTimeView::TTimeView(float maxWidth, float height, TBarView* barView)
        :
        BView(BRect(-100, -100, -90, -90), "_deskbar_tv_",
                B_FOLLOW_RIGHT | B_FOLLOW_TOP,
                B_WILL_DRAW | B_PULSE_NEEDED | B_FRAME_EVENTS),
+       fBarView(barView),
        fParent(NULL),
        fMaxWidth(maxWidth),
        fHeight(height),
-       fOrientation(true),
        fShowLevel(0),
        fShowSeconds(false),
        fShowDayOfWeek(false),
@@ -133,7 +133,7 @@ status_t
 TTimeView::Archive(BMessage* data, bool deep) const
 {
        BView::Archive(data, deep);
-       data->AddBool("orientation", fOrientation);
+       data->AddBool("orientation", Vertical());
        data->AddInt16("showLevel", fShowLevel);
        data->AddBool("showSeconds", fShowSeconds);
        data->AddBool("showDayOfWeek", fShowDayOfWeek);
@@ -193,9 +193,10 @@ TTimeView::GetPreferredSize(float* width, float* height)
        // set the height based on the font size
        font_height fontHeight;
        GetFontHeight(&fontHeight);
-       fHeight = fontHeight.ascent + fontHeight.descent;
+       fHeight = fontHeight.ascent + fontHeight.descent - 2;
+               // reduce height by 2px so that clock doesn't draw on top of 
border
 
-       if (fOrientation) {
+       if (Vertical()) {
                float appWidth = 
static_cast<TBarApp*>(be_app)->Settings()->width;
                *width = fMaxWidth
                        = std::min(appWidth - (kDragRegionWidth + kHMargin) * 
2, timeWidth);
@@ -320,16 +321,6 @@ TTimeView::ResizeToPreferred()
 //     # pragma mark - Public methods
 
 
-void
-TTimeView::SetOrientation(bool orientation)
-{
-       fOrientation = orientation;
-       ResizeToPreferred();
-       CalculateTextPlacement();
-       Invalidate();
-}
-
-
 bool
 TTimeView::ShowSeconds() const
 {
@@ -480,7 +471,7 @@ TTimeView::CalculateTextPlacement()
        fTimeLocation.y = fDateLocation.y = ceilf((Bounds().Height()
                - rectArray[0].Height() + 1.0) / 2.0 - rectArray[0].top);
 
-       if (fOrientation) {
+       if (Vertical()) {
                float timeWidth = StringWidth(fCurrentTimeStr);
                if (timeWidth > fMaxWidth) {
                        // time does not fit, push it over to truncate the left 
side
@@ -533,3 +524,14 @@ TTimeView::Update()
        if (fParent != NULL)
                fParent->Invalidate();
 }
+
+
+bool
+TTimeView::Vertical()
+{

[ *** diff truncated: 141 lines dropped *** ]




Other related posts:

  • » [haiku-commits] haiku: hrev53955 - src/apps/deskbar data/artwork/icons - Adrien Destugues