WIP: Created a BScrollMenu class that works like BMenuWindow but works on a view instead of a window. Use this to implement a scrollable BarMenuBar in Deskbar. The basics work but there are issues still with sizing and other issues.
Modify the ScrollMenu class to use the layout kit by adding a constructor that doesn't take a view. Get the BScrollMenu class to follow the size of the BMenu it is a parent of. Adjust the scrollers to appear in the right places. This is a WIP but it works in Deskbar, next step is to integrate this directly into BMenu with the scrollers as children of the menu instead of as children of the BScroller class. Rebase changes on top of master Deskbar scrolling works for the most part, just need to fix the bottom arrow and clean up a bit.
This commit is contained in:
parent
5ad155d720
commit
cb55ef9fb5
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Marc Flerackers (mflerackers@androme.be)
|
||||
* Stefano Ceccherini (stefano.ceccherini@gmail.com)
|
||||
* John Scipione (jscipione@gmail.com)
|
||||
*/
|
||||
#ifndef SCROLL_MENU_H
|
||||
#define SCROLL_MENU_H
|
||||
|
||||
|
||||
#include <View.h>
|
||||
|
||||
class BLayout;
|
||||
class BMenu;
|
||||
class BMenuScroller;
|
||||
|
||||
|
||||
class BScrollMenu : public BView {
|
||||
public:
|
||||
BScrollMenu(BMenu* menu);
|
||||
virtual ~BScrollMenu();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
virtual void DetachedFromWindow();
|
||||
virtual void Draw(BRect updateRect);
|
||||
virtual void FrameResized(float newWidth, float newHeight);
|
||||
|
||||
void AttachScrollers();
|
||||
void DetachScrollers();
|
||||
bool HasScrollers() const;
|
||||
|
||||
void SetSmallStep(float step);
|
||||
void GetSteps(float* _smallStep, float* _largeStep) const;
|
||||
bool CheckForScrolling(const BPoint& cursor);
|
||||
bool TryScrollBy(const float& step);
|
||||
|
||||
protected:
|
||||
bool _Scroll(const BPoint& cursor);
|
||||
void _ScrollBy(const float& step);
|
||||
|
||||
private:
|
||||
BMenu* fMenu;
|
||||
BMenuScroller* fUpperScroller;
|
||||
BMenuScroller* fLowerScroller;
|
||||
|
||||
float fScrollStep;
|
||||
float fValue;
|
||||
float fLimit;
|
||||
};
|
||||
|
||||
|
||||
#endif // SCROLL_MENU_H
|
|
@ -48,6 +48,7 @@ All rights reserved.
|
|||
#include <NodeInfo.h>
|
||||
#include <Roster.h>
|
||||
#include <Screen.h>
|
||||
#include <ScrollMenu.h>
|
||||
#include <String.h>
|
||||
|
||||
#include "icons.h"
|
||||
|
@ -130,6 +131,7 @@ BarViewMessageFilter::Filter(BMessage* message, BHandler** target)
|
|||
TBarView::TBarView(BRect frame, bool vertical, bool left, bool top,
|
||||
uint32 state, float)
|
||||
: BView(frame, "BarView", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
|
||||
fBarScrollMenu(NULL),
|
||||
fBarMenuBar(NULL),
|
||||
fExpando(NULL),
|
||||
fTrayLocation(1),
|
||||
|
@ -347,8 +349,7 @@ TBarView::MouseDown(BPoint where)
|
|||
void
|
||||
TBarView::PlaceDeskbarMenu()
|
||||
{
|
||||
// top or bottom, full
|
||||
if (!fVertical && fBarMenuBar) {
|
||||
if (!fVertical && fBarMenuBar != NULL) {
|
||||
fBarMenuBar->RemoveSelf();
|
||||
delete fBarMenuBar;
|
||||
fBarMenuBar = NULL;
|
||||
|
@ -367,12 +368,13 @@ TBarView::PlaceDeskbarMenu()
|
|||
|
||||
// if there isn't a bemenu at this point,
|
||||
// DB should be in top/bottom mode, else error
|
||||
if (!fBarMenuBar)
|
||||
if (fBarMenuBar == NULL)
|
||||
return;
|
||||
|
||||
float width = sMinimumWindowWidth;
|
||||
BPoint loc(B_ORIGIN);
|
||||
BRect menuFrame(fBarMenuBar->Frame());
|
||||
|
||||
if (fState == kFullState) {
|
||||
fBarMenuBar->RemoveTeamMenu();
|
||||
// TODO: Magic constants need explanation
|
||||
|
@ -441,22 +443,22 @@ TBarView::PlaceTray(bool vertSwap, bool leftSwap)
|
|||
void
|
||||
TBarView::PlaceApplicationBar()
|
||||
{
|
||||
if (fExpando != NULL) {
|
||||
SaveExpandedItems();
|
||||
if (fBarScrollMenu != NULL) {
|
||||
fBarScrollMenu->RemoveSelf();
|
||||
delete fBarScrollMenu;
|
||||
// Also deletes fExpando
|
||||
fBarScrollMenu = NULL;
|
||||
fExpando = NULL;
|
||||
} else if (fExpando != NULL) {
|
||||
fExpando->RemoveSelf();
|
||||
delete fExpando;
|
||||
fExpando = NULL;
|
||||
}
|
||||
|
||||
BRect screenFrame = (BScreen(Window())).Frame();
|
||||
if (fState == kMiniState) {
|
||||
SizeWindow(screenFrame);
|
||||
PositionWindow(screenFrame);
|
||||
Window()->UpdateIfNeeded();
|
||||
Invalidate();
|
||||
if (fState == kMiniState)
|
||||
return;
|
||||
}
|
||||
|
||||
BRect screenFrame = (BScreen(Window())).Frame();
|
||||
BRect expandoFrame(0, 0, 0, 0);
|
||||
if (fVertical) {
|
||||
// top left/right
|
||||
|
@ -485,7 +487,13 @@ TBarView::PlaceApplicationBar()
|
|||
|
||||
fExpando = new TExpandoMenuBar(this, expandoFrame, "ExpandoMenuBar",
|
||||
fVertical, !hideLabels && fState != kFullState);
|
||||
AddChild(fExpando);
|
||||
|
||||
if (fVertical) {
|
||||
fBarScrollMenu = new BScrollMenu(fExpando);
|
||||
AddChild(fBarScrollMenu);
|
||||
//printf("fExpando bottom: %f, fBarScrollMenu bottom: %f\n", fExpando->Frame().bottom, fBarScrollMenu->Frame().bottom);
|
||||
} else
|
||||
AddChild(fExpando);
|
||||
|
||||
if (fVertical)
|
||||
ExpandItems();
|
||||
|
@ -522,7 +530,7 @@ TBarView::GetPreferredWindowSize(BRect screenFrame, float* width, float* height)
|
|||
} else if (fState == kExpandoState) {
|
||||
if (fVertical) {
|
||||
// top left or right
|
||||
windowHeight = fExpando->Frame().bottom;
|
||||
windowHeight = fBarScrollMenu->Frame().bottom;
|
||||
} else {
|
||||
// top or bottom, full
|
||||
fExpando->CheckItemSizes(0);
|
||||
|
|
|
@ -65,7 +65,7 @@ const float kStatusHeight = 22.0f;
|
|||
const float kHiddenDimension = 1.0f;
|
||||
const float kMaxPreventHidingDist = 80.0f;
|
||||
|
||||
|
||||
class BScrollMenu;
|
||||
class BShelf;
|
||||
class TBarMenuBar;
|
||||
class TExpandoMenuBar;
|
||||
|
@ -168,6 +168,7 @@ class TBarView : public BView {
|
|||
void ExpandItems();
|
||||
void _ChangeState(BMessage* message);
|
||||
|
||||
BScrollMenu* fBarScrollMenu;
|
||||
TBarMenuBar* fBarMenuBar;
|
||||
TExpandoMenuBar* fExpando;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ All rights reserved.
|
|||
#include <NodeInfo.h>
|
||||
#include <Roster.h>
|
||||
#include <Screen.h>
|
||||
#include <ScrollMenu.h>
|
||||
|
||||
#include "icons.h"
|
||||
|
||||
|
@ -797,10 +798,22 @@ TExpandoMenuBar::DrawBackground(BRect)
|
|||
void
|
||||
TExpandoMenuBar::CheckForSizeOverrun()
|
||||
{
|
||||
BRect screenFrame = (BScreen(Window())).Frame();
|
||||
if (!fVertical) {
|
||||
fIsScrolling = false;
|
||||
return;
|
||||
}
|
||||
|
||||
fIsScrolling = fVertical ? Window()->Frame().bottom > screenFrame.bottom
|
||||
: false;
|
||||
BScrollMenu* scrollMenu = dynamic_cast<BScrollMenu*>(Parent());
|
||||
if (scrollMenu == NULL)
|
||||
return;
|
||||
|
||||
BRect screenFrame = (BScreen(Window())).Frame();
|
||||
fIsScrolling = Window()->Frame().bottom > screenFrame.bottom;
|
||||
|
||||
if (fIsScrolling)
|
||||
scrollMenu->AttachScrollers();
|
||||
else
|
||||
scrollMenu->DetachScrollers();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -479,8 +479,7 @@ TTeamMenuItem::DrawContentLabel()
|
|||
if (Submenu() && fVertical)
|
||||
cachedWidth += 18;
|
||||
|
||||
const char* label = Label();
|
||||
char* truncLabel = NULL;
|
||||
BString label(Label());
|
||||
float max = 0;
|
||||
|
||||
if (fVertical && static_cast<TBarApp*>(be_app)->Settings()->superExpando)
|
||||
|
@ -492,30 +491,23 @@ TTeamMenuItem::DrawContentLabel()
|
|||
BPoint penloc = menu->PenLocation();
|
||||
BRect frame = Frame();
|
||||
float offset = penloc.x - frame.left;
|
||||
if (cachedWidth + offset > max) {
|
||||
truncLabel = (char*)malloc(strlen(label) + 4);
|
||||
if (!truncLabel)
|
||||
return;
|
||||
TruncateLabel(max-offset, truncLabel);
|
||||
label = truncLabel;
|
||||
}
|
||||
if (cachedWidth + offset > max)
|
||||
menu->TruncateString(&label, B_TRUNCATE_MIDDLE, max - offset);
|
||||
}
|
||||
|
||||
if (!label)
|
||||
label = Label();
|
||||
label = BString(Label());
|
||||
|
||||
TBarView* barview = (static_cast<TBarApp*>(be_app))->BarView();
|
||||
bool canHandle = !barview->Dragging()
|
||||
|| barview->AppCanHandleTypes(Signature());
|
||||
TBarView* barView = (static_cast<TBarApp*>(be_app))->BarView();
|
||||
bool canHandle = !barView->Dragging()
|
||||
|| barView->AppCanHandleTypes(Signature());
|
||||
if (_IsSelected() && IsEnabled() && canHandle)
|
||||
menu->SetLowColor(tint_color(menu->LowColor(),
|
||||
B_HIGHLIGHT_BACKGROUND_TINT));
|
||||
else
|
||||
menu->SetLowColor(menu->LowColor());
|
||||
|
||||
menu->DrawString(label);
|
||||
|
||||
free(truncLabel);
|
||||
menu->DrawString(label.String());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ MergeObject <libbe>interface_kit.o :
|
|||
RegionSupport.cpp
|
||||
Screen.cpp
|
||||
ScrollBar.cpp
|
||||
ScrollMenu.cpp
|
||||
ScrollView.cpp
|
||||
SeparatorItem.cpp
|
||||
SeparatorView.cpp
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <PropertyInfo.h>
|
||||
#include <Screen.h>
|
||||
#include <ScrollBar.h>
|
||||
#include <ScrollMenu.h>
|
||||
#include <SystemCatalog.h>
|
||||
#include <Window.h>
|
||||
|
||||
|
@ -2811,13 +2812,18 @@ BMenu::_ChooseTrigger(const char* title, int32& index, uint32& trigger,
|
|||
void
|
||||
BMenu::_UpdateWindowViewSize(const bool &move)
|
||||
{
|
||||
if (dynamic_cast<BMenuBar*>(this) != NULL) {
|
||||
BScrollMenu* scrollMenu = dynamic_cast<BScrollMenu*>(Parent());
|
||||
if (scrollMenu != NULL)
|
||||
scrollMenu->ResizeTo(Bounds().Width(), Bounds().Height());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
BMenuWindow* window = static_cast<BMenuWindow*>(Window());
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
if (dynamic_cast<BMenuBar*>(this) != NULL)
|
||||
return;
|
||||
|
||||
if (!fResizeToFit)
|
||||
return;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <ControlLook.h>
|
||||
#include <LayoutUtils.h>
|
||||
#include <MenuItem.h>
|
||||
#include <ScrollMenu.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include <AppMisc.h>
|
||||
|
@ -328,7 +329,36 @@ BMenuBar::Draw(BRect updateRect)
|
|||
void
|
||||
BMenuBar::MessageReceived(BMessage* msg)
|
||||
{
|
||||
BMenu::MessageReceived(msg);
|
||||
switch (msg->what) {
|
||||
case B_MOUSE_WHEEL_CHANGED:
|
||||
{
|
||||
float deltaY = 0;
|
||||
msg->FindFloat("be:wheel_delta_y", &deltaY);
|
||||
if (deltaY == 0)
|
||||
return;
|
||||
|
||||
BScrollMenu* scrollMenu = dynamic_cast<BScrollMenu*>(Parent());
|
||||
if (scrollMenu == NULL)
|
||||
return;
|
||||
|
||||
float largeStep;
|
||||
float smallStep;
|
||||
scrollMenu->GetSteps(&smallStep, &largeStep);
|
||||
|
||||
// pressing the option/command/control key scrolls faster
|
||||
if (modifiers() & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY))
|
||||
deltaY *= largeStep;
|
||||
else
|
||||
deltaY *= smallStep;
|
||||
|
||||
scrollMenu->TryScrollBy(deltaY);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
BMenu::MessageReceived(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
* Copyright 2011, Haiku, Inc.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Marc Flerackers (mflerackers@androme.be)
|
||||
* Stefano Ceccherini (stefano.ceccherini@gmail.com)
|
||||
* John Scipione (jscipione@gmail.com)
|
||||
*/
|
||||
|
||||
|
||||
#include <ScrollMenu.h>
|
||||
|
||||
#include <ControlLook.h>
|
||||
#include <Debug.h>
|
||||
#include <InterfaceDefs.h>
|
||||
#include <Layout.h>
|
||||
#include <GroupLayout.h>
|
||||
#include <Menu.h>
|
||||
#include <Screen.h>
|
||||
|
||||
#include <MenuPrivate.h>
|
||||
|
||||
|
||||
const char* kEmptyMenuLabel = "<empty>";
|
||||
const int kDefaultScrollStep = 19;
|
||||
const int kScrollerHeight = 12;
|
||||
|
||||
|
||||
class BMenuScroller : public BView {
|
||||
public:
|
||||
BMenuScroller(BRect frame);
|
||||
virtual ~BMenuScroller();
|
||||
|
||||
bool IsEnabled() const { return fEnabled; };
|
||||
void SetEnabled(bool enabled);
|
||||
|
||||
private:
|
||||
bool fEnabled;
|
||||
};
|
||||
|
||||
|
||||
class BMenuUpScroller : public BMenuScroller {
|
||||
public:
|
||||
BMenuUpScroller(BRect frame);
|
||||
virtual ~BMenuUpScroller();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
};
|
||||
|
||||
|
||||
class BMenuDownScroller : public BMenuScroller {
|
||||
public:
|
||||
BMenuDownScroller(BRect frame);
|
||||
virtual ~BMenuDownScroller();
|
||||
|
||||
virtual void Draw(BRect updateRect);
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BMenuScroller::BMenuScroller(BRect frame)
|
||||
:
|
||||
BView(frame, "menu scroll arrow", 0, B_WILL_DRAW | B_FRAME_EVENTS),
|
||||
fEnabled(false)
|
||||
{
|
||||
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
|
||||
}
|
||||
|
||||
|
||||
BMenuScroller::~BMenuScroller()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMenuScroller::SetEnabled(bool enabled)
|
||||
{
|
||||
fEnabled = enabled;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BMenuUpScroller::BMenuUpScroller(BRect frame)
|
||||
:
|
||||
BMenuScroller(frame)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BMenuUpScroller::~BMenuUpScroller()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMenuUpScroller::Draw(BRect updateRect)
|
||||
{
|
||||
SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
|
||||
|
||||
// Draw the upper arrow.
|
||||
if (IsEnabled())
|
||||
SetHighColor(0, 0, 0);
|
||||
else {
|
||||
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
|
||||
B_DARKEN_2_TINT));
|
||||
}
|
||||
|
||||
FillRect(Bounds(), B_SOLID_LOW);
|
||||
|
||||
float middle = Bounds().right / 2;
|
||||
FillTriangle(BPoint(middle, (kScrollerHeight / 2) - 3),
|
||||
BPoint(middle + 5, (kScrollerHeight / 2) + 2),
|
||||
BPoint(middle - 5, (kScrollerHeight / 2) + 2));
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BMenuDownScroller::BMenuDownScroller(BRect frame)
|
||||
:
|
||||
BMenuScroller(frame)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BMenuDownScroller::~BMenuDownScroller()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BMenuDownScroller::Draw(BRect updateRect)
|
||||
{
|
||||
SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
|
||||
|
||||
// Draw the lower arrow.
|
||||
if (IsEnabled())
|
||||
SetHighColor(0, 0, 0);
|
||||
else {
|
||||
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
|
||||
B_DARKEN_2_TINT));
|
||||
}
|
||||
|
||||
BRect frame = Bounds();
|
||||
FillRect(frame, B_SOLID_LOW);
|
||||
|
||||
float middle = Bounds().right / 2;
|
||||
FillTriangle(BPoint(middle, frame.bottom - (kScrollerHeight / 2) + 3),
|
||||
BPoint(middle + 5, frame.bottom - (kScrollerHeight / 2) - 2),
|
||||
BPoint(middle - 5, frame.bottom - (kScrollerHeight / 2) - 2));
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
BScrollMenu::BScrollMenu(BMenu *menu)
|
||||
:
|
||||
BView("menu scroll view", B_WILL_DRAW | B_FRAME_EVENTS),
|
||||
fMenu(menu),
|
||||
fUpperScroller(NULL),
|
||||
fLowerScroller(NULL),
|
||||
fScrollStep(kDefaultScrollStep)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BScrollMenu::~BScrollMenu()
|
||||
{
|
||||
if (fMenu != NULL) {
|
||||
fMenu->RemoveSelf();
|
||||
delete fMenu;
|
||||
fMenu = NULL;
|
||||
}
|
||||
|
||||
if (fUpperScroller != NULL) {
|
||||
fUpperScroller->RemoveSelf();
|
||||
delete fUpperScroller;
|
||||
fUpperScroller = NULL;
|
||||
}
|
||||
|
||||
if (fLowerScroller != NULL) {
|
||||
fLowerScroller->RemoveSelf();
|
||||
delete fLowerScroller;
|
||||
fLowerScroller = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::AttachedToWindow()
|
||||
{
|
||||
BView::AttachedToWindow();
|
||||
|
||||
if (fMenu == NULL)
|
||||
return;
|
||||
|
||||
AddChild(fMenu);
|
||||
|
||||
// Move the scroll menu into the right position
|
||||
MoveTo(fMenu->Frame().LeftTop());
|
||||
|
||||
BFont font;
|
||||
fMenu->GetFont(&font);
|
||||
SetFont(&font);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::DetachedFromWindow()
|
||||
{
|
||||
BView::DetachedFromWindow();
|
||||
|
||||
if (fMenu != NULL)
|
||||
fMenu->RemoveSelf();
|
||||
|
||||
if (fUpperScroller != NULL)
|
||||
fUpperScroller->RemoveSelf();
|
||||
|
||||
if (fLowerScroller != NULL)
|
||||
fLowerScroller->RemoveSelf();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::Draw(BRect updateRect)
|
||||
{
|
||||
if (be_control_look != NULL)
|
||||
return;
|
||||
|
||||
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_2_TINT));
|
||||
BRect bounds(Bounds());
|
||||
|
||||
StrokeLine(BPoint(bounds.right, bounds.top),
|
||||
BPoint(bounds.right, bounds.bottom - 1));
|
||||
StrokeLine(BPoint(bounds.left + 1, bounds.bottom),
|
||||
BPoint(bounds.right, bounds.bottom));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::FrameResized(float newWidth, float newHeight)
|
||||
{
|
||||
BView::FrameResized(newWidth, newHeight);
|
||||
|
||||
if (fMenu != NULL) {
|
||||
if (HasScrollers())
|
||||
fMenu->MoveTo(0, kScrollerHeight);
|
||||
else
|
||||
fMenu->MoveTo(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::AttachScrollers()
|
||||
{
|
||||
if (fMenu == NULL)
|
||||
return;
|
||||
|
||||
BRect frame = Bounds();
|
||||
BRect screenFrame = (BScreen(Window())).Frame();
|
||||
|
||||
if (HasScrollers()) {
|
||||
fLimit = Frame().bottom + 2 * kScrollerHeight - screenFrame.bottom;
|
||||
return;
|
||||
}
|
||||
|
||||
fMenu->MakeFocus(true);
|
||||
|
||||
if (fUpperScroller == NULL) {
|
||||
fUpperScroller = new BMenuUpScroller(
|
||||
BRect(0, 0, frame.right, kScrollerHeight - 1));
|
||||
AddChild(fUpperScroller, fMenu);
|
||||
}
|
||||
|
||||
if (fLowerScroller == NULL) {
|
||||
fLowerScroller = new BMenuDownScroller(
|
||||
BRect(0, frame.bottom - kScrollerHeight + 1, frame.right,
|
||||
frame.bottom));
|
||||
AddChild(fLowerScroller);
|
||||
}
|
||||
|
||||
fUpperScroller->SetEnabled(false);
|
||||
fLowerScroller->SetEnabled(true);
|
||||
|
||||
fLimit = Frame().bottom + 2 * kScrollerHeight - screenFrame.bottom;
|
||||
fValue = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::DetachScrollers()
|
||||
{
|
||||
if (!HasScrollers())
|
||||
return;
|
||||
|
||||
if (fLowerScroller) {
|
||||
fLowerScroller->RemoveSelf();
|
||||
delete fLowerScroller;
|
||||
fLowerScroller = NULL;
|
||||
}
|
||||
|
||||
if (fUpperScroller) {
|
||||
fUpperScroller->RemoveSelf();
|
||||
delete fUpperScroller;
|
||||
fUpperScroller = NULL;
|
||||
}
|
||||
|
||||
if (fMenu) {
|
||||
// We don't remember the position where the last scrolling
|
||||
// ended, so scroll back to the beginning.
|
||||
fMenu->ScrollTo(0, 0);
|
||||
// Since the scrollers were removed move back up.
|
||||
//fMenu->ResizeBy(0, 2 * kScrollerHeight);
|
||||
//fMenu->MoveBy(0, -kScrollerHeight);
|
||||
fValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BScrollMenu::HasScrollers() const
|
||||
{
|
||||
return fMenu != NULL && fUpperScroller != NULL && fLowerScroller != NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::SetSmallStep(float step)
|
||||
{
|
||||
fScrollStep = step;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::GetSteps(float* _smallStep, float* _largeStep) const
|
||||
{
|
||||
if (_smallStep != NULL)
|
||||
*_smallStep = fScrollStep;
|
||||
if (_largeStep != NULL) {
|
||||
if (fMenu != NULL)
|
||||
*_largeStep = fMenu->Frame().Height() - fScrollStep;
|
||||
else
|
||||
*_largeStep = fScrollStep * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BScrollMenu::CheckForScrolling(const BPoint &cursor)
|
||||
{
|
||||
if (!HasScrollers())
|
||||
return false;
|
||||
|
||||
return _Scroll(cursor);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BScrollMenu::TryScrollBy(const float& step)
|
||||
{
|
||||
if (!HasScrollers())
|
||||
return false;
|
||||
|
||||
_ScrollBy(step);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BScrollMenu::_Scroll(const BPoint& where)
|
||||
{
|
||||
ASSERT((fLowerScroller != NULL));
|
||||
ASSERT((fUpperScroller != NULL));
|
||||
|
||||
const BPoint cursor = ConvertFromScreen(where);
|
||||
const BRect &lowerFrame = fLowerScroller->Frame();
|
||||
const BRect &upperFrame = fUpperScroller->Frame();
|
||||
|
||||
int32 delta = 0;
|
||||
if (fLowerScroller->IsEnabled() && lowerFrame.Contains(cursor))
|
||||
delta = 1;
|
||||
else if (fUpperScroller->IsEnabled() && upperFrame.Contains(cursor))
|
||||
delta = -1;
|
||||
|
||||
if (delta == 0)
|
||||
return false;
|
||||
|
||||
float smallStep;
|
||||
GetSteps(&smallStep, NULL);
|
||||
_ScrollBy(smallStep * delta);
|
||||
|
||||
snooze(5000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BScrollMenu::_ScrollBy(const float& step)
|
||||
{
|
||||
if (step > 0) {
|
||||
if (fValue == 0)
|
||||
fUpperScroller->SetEnabled(true);
|
||||
|
||||
if (fValue + step >= fLimit) {
|
||||
// If we reached the limit, only scroll to the end
|
||||
fMenu->ScrollBy(0, fLimit - fValue);
|
||||
fValue = fLimit;
|
||||
fLowerScroller->SetEnabled(false);
|
||||
} else {
|
||||
fMenu->ScrollBy(0, step);
|
||||
fValue += step;
|
||||
}
|
||||
} else if (step < 0) {
|
||||
if (fValue == fLimit)
|
||||
fLowerScroller->SetEnabled(true);
|
||||
|
||||
if (fValue + step <= 0) {
|
||||
fMenu->ScrollBy(0, -fValue);
|
||||
fValue = 0;
|
||||
fUpperScroller->SetEnabled(false);
|
||||
} else {
|
||||
fMenu->ScrollBy(0, step);
|
||||
fValue += step;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue