Changed the interaction between BMenuFrame, BMenuScroller and
BMenuWindow. BMenuScroller now is just the scroller button, and it's a child of BMenuWindow. This simplifies attaching/detaching the scrollers, and it's also a bit cleaner. The lower scroller wasn't shown anymore for some reason, and this commit also fixes this problem. A drawing bug shows up now, though: when scrolling the menu UP, some spurious lines are drawn over the menu. I wonder if this is an app_server bug or what. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21326 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -35,8 +35,15 @@ class BMenuWindow : public BWindow {
|
|||||||
bool CheckForScrolling(BPoint cursor);
|
bool CheckForScrolling(BPoint cursor);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMenuScroller *fScroller;
|
BMenu *fMenu;
|
||||||
BMenuFrame *fMenuFrame;
|
BMenuFrame *fMenuFrame;
|
||||||
|
BMenuScroller *fUpperScroller;
|
||||||
|
BMenuScroller *fLowerScroller;
|
||||||
|
|
||||||
|
float fValue;
|
||||||
|
float fLimit;
|
||||||
|
|
||||||
|
bool _Scroll(BPoint cursor);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
+177
-136
@@ -20,44 +20,45 @@ namespace BPrivate {
|
|||||||
|
|
||||||
class BMenuScroller : public BView {
|
class BMenuScroller : public BView {
|
||||||
public:
|
public:
|
||||||
BMenuScroller(BRect frame, BMenu *menu);
|
BMenuScroller(BRect frame);
|
||||||
virtual ~BMenuScroller();
|
|
||||||
|
bool IsEnabled() const;
|
||||||
virtual void Draw(BRect updateRect);
|
void SetEnabled(const bool &enabled);
|
||||||
bool Scroll(BPoint cursor);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BMenu *fMenu;
|
bool fEnabled;
|
||||||
BRect fUpperButton;
|
|
||||||
BRect fLowerButton;
|
|
||||||
|
|
||||||
float fValue;
|
|
||||||
float fLimit;
|
|
||||||
|
|
||||||
bool fUpperEnabled;
|
|
||||||
bool fLowerEnabled;
|
|
||||||
|
|
||||||
uint32 fButton;
|
|
||||||
BPoint fPosition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BMenuFrame : public BView {
|
class BMenuFrame : public BView {
|
||||||
public:
|
public:
|
||||||
BMenuFrame(BMenu *menu);
|
BMenuFrame(BMenu *menu);
|
||||||
virtual ~BMenuFrame();
|
|
||||||
|
|
||||||
virtual void AttachedToWindow();
|
virtual void AttachedToWindow();
|
||||||
virtual void DetachedFromWindow();
|
virtual void DetachedFromWindow();
|
||||||
virtual void Draw(BRect updateRect);
|
virtual void Draw(BRect updateRect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class BMenuWindow;
|
friend class BMenuWindow;
|
||||||
|
|
||||||
BMenu *fMenu;
|
BMenu *fMenu;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class UpperScroller : public BMenuScroller {
|
||||||
|
public:
|
||||||
|
UpperScroller(BRect frame);
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
};
|
||||||
|
|
||||||
|
class LowerScroller : public BMenuScroller {
|
||||||
|
public:
|
||||||
|
LowerScroller(BRect frame);
|
||||||
|
virtual void Draw(BRect updateRect);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|
||||||
using namespace BPrivate;
|
using namespace BPrivate;
|
||||||
|
|
||||||
|
|
||||||
@@ -65,113 +66,89 @@ const int kScrollerHeight = 10;
|
|||||||
const int kScrollStep = 19;
|
const int kScrollStep = 19;
|
||||||
|
|
||||||
|
|
||||||
BMenuScroller::BMenuScroller(BRect frame, BMenu *menu)
|
BMenuScroller::BMenuScroller(BRect frame)
|
||||||
: BView(frame, "menu scroller", 0, B_WILL_DRAW | B_FRAME_EVENTS),
|
: BView(frame, "menu scroller", 0, B_WILL_DRAW | B_FRAME_EVENTS),
|
||||||
fMenu(menu),
|
fEnabled(false)
|
||||||
fUpperButton(0, 0, frame.right, kScrollerHeight),
|
|
||||||
fLowerButton(0, frame.bottom - kScrollerHeight, frame.right, frame.bottom),
|
|
||||||
fValue(0),
|
|
||||||
fUpperEnabled(false),
|
|
||||||
fLowerEnabled(true)
|
|
||||||
{
|
|
||||||
if (!menu)
|
|
||||||
debugger("BMenuScroller(): Scroller not attached to a menu!");
|
|
||||||
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
|
|
||||||
|
|
||||||
fLimit = menu->Bounds().Height() - (frame.Height() - 2 * kScrollerHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BMenuScroller::~BMenuScroller()
|
|
||||||
{
|
{
|
||||||
|
SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BMenuScroller::Scroll(BPoint cursor)
|
BMenuScroller::IsEnabled() const
|
||||||
{
|
{
|
||||||
ConvertFromScreen(&cursor);
|
return fEnabled;
|
||||||
|
|
||||||
if (fLowerEnabled && fLowerButton.Contains(cursor)) {
|
|
||||||
if (fValue == 0) {
|
|
||||||
fUpperEnabled = true;
|
|
||||||
|
|
||||||
Invalidate(fUpperButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fValue + kScrollStep >= fLimit) {
|
|
||||||
// If we reached the limit, we don't want to scroll a whole
|
|
||||||
// 'step' if not needed.
|
|
||||||
fMenu->ScrollBy(0, fLimit - fValue);
|
|
||||||
fValue = fLimit;
|
|
||||||
fLowerEnabled = false;
|
|
||||||
Invalidate(fLowerButton);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
fMenu->ScrollBy(0, kScrollStep);
|
|
||||||
fValue += kScrollStep;
|
|
||||||
}
|
|
||||||
} else if (fUpperEnabled && fUpperButton.Contains(cursor)) {
|
|
||||||
if (fValue == fLimit) {
|
|
||||||
fLowerEnabled = true;
|
|
||||||
Invalidate(fLowerButton);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fValue - kScrollStep <= 0) {
|
|
||||||
fMenu->ScrollBy(0, -fValue);
|
|
||||||
fValue = 0;
|
|
||||||
fUpperEnabled = false;
|
|
||||||
Invalidate(fUpperButton);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
fMenu->ScrollBy(0, -kScrollStep);
|
|
||||||
fValue -= kScrollStep;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
snooze(10000);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMenuScroller::Draw(BRect updateRect)
|
BMenuScroller::SetEnabled(const bool &enabled)
|
||||||
|
{
|
||||||
|
fEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
UpperScroller::UpperScroller(BRect frame)
|
||||||
|
:
|
||||||
|
BMenuScroller(frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
UpperScroller::Draw(BRect updateRect)
|
||||||
{
|
{
|
||||||
SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
|
SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
|
||||||
float middle = Bounds().right / 2;
|
float middle = Bounds().right / 2;
|
||||||
|
|
||||||
// Draw the upper arrow.
|
// Draw the upper arrow.
|
||||||
if (updateRect.Intersects(fUpperButton)) {
|
if (IsEnabled())
|
||||||
if (fUpperEnabled)
|
SetHighColor(0, 0, 0);
|
||||||
SetHighColor(0, 0, 0);
|
else
|
||||||
else
|
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
|
||||||
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
|
B_DARKEN_2_TINT));
|
||||||
B_DARKEN_2_TINT));
|
|
||||||
|
|
||||||
FillRect(fUpperButton, B_SOLID_LOW);
|
FillRect(Bounds(), B_SOLID_LOW);
|
||||||
|
|
||||||
FillTriangle(BPoint(middle, (kScrollerHeight / 2) - 3),
|
FillTriangle(BPoint(middle, (kScrollerHeight / 2) - 3),
|
||||||
BPoint(middle + 5, (kScrollerHeight / 2) + 2),
|
BPoint(middle + 5, (kScrollerHeight / 2) + 2),
|
||||||
BPoint(middle - 5, (kScrollerHeight / 2) + 2));
|
BPoint(middle - 5, (kScrollerHeight / 2) + 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
LowerScroller::LowerScroller(BRect frame)
|
||||||
|
:
|
||||||
|
BMenuScroller(frame)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
LowerScroller::Draw(BRect updateRect)
|
||||||
|
{
|
||||||
|
SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
|
||||||
|
|
||||||
|
BRect frame = Bounds();
|
||||||
// Draw the lower arrow.
|
// Draw the lower arrow.
|
||||||
if (updateRect.Intersects(fLowerButton)) {
|
if (IsEnabled())
|
||||||
if (fLowerEnabled)
|
SetHighColor(0, 0, 0);
|
||||||
SetHighColor(0, 0, 0);
|
else
|
||||||
else
|
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
|
||||||
SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
|
B_DARKEN_2_TINT));
|
||||||
B_DARKEN_2_TINT));
|
|
||||||
|
|
||||||
FillRect(fLowerButton, B_SOLID_LOW);
|
FillRect(Bounds(), B_SOLID_LOW);
|
||||||
|
|
||||||
FillTriangle(BPoint(middle, fLowerButton.bottom - (kScrollerHeight / 2) + 3),
|
float middle = Bounds().right / 2;
|
||||||
BPoint(middle + 5, fLowerButton.bottom - (kScrollerHeight / 2) - 2),
|
|
||||||
BPoint(middle - 5, fLowerButton.bottom - (kScrollerHeight / 2) - 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -185,11 +162,6 @@ BMenuFrame::BMenuFrame(BMenu *menu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BMenuFrame::~BMenuFrame()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMenuFrame::AttachedToWindow()
|
BMenuFrame::AttachedToWindow()
|
||||||
{
|
{
|
||||||
@@ -246,6 +218,7 @@ BMenuFrame::Draw(BRect updateRect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -253,8 +226,10 @@ BMenuWindow::BMenuWindow(const char *name)
|
|||||||
// The window will be resized by BMenu, so just pass a dummy rect
|
// The window will be resized by BMenu, so just pass a dummy rect
|
||||||
: BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
|
: BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
|
||||||
B_NOT_ZOOMABLE | B_AVOID_FOCUS),
|
B_NOT_ZOOMABLE | B_AVOID_FOCUS),
|
||||||
fScroller(NULL),
|
fMenu(NULL),
|
||||||
fMenuFrame(NULL)
|
fMenuFrame(NULL),
|
||||||
|
fUpperScroller(NULL),
|
||||||
|
fLowerScroller(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,6 +248,7 @@ BMenuWindow::AttachMenu(BMenu *menu)
|
|||||||
fMenuFrame = new BMenuFrame(menu);
|
fMenuFrame = new BMenuFrame(menu);
|
||||||
AddChild(fMenuFrame);
|
AddChild(fMenuFrame);
|
||||||
menu->MakeFocus(true);
|
menu->MakeFocus(true);
|
||||||
|
fMenu = menu;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,14 +256,12 @@ BMenuWindow::AttachMenu(BMenu *menu)
|
|||||||
void
|
void
|
||||||
BMenuWindow::DetachMenu()
|
BMenuWindow::DetachMenu()
|
||||||
{
|
{
|
||||||
|
DetachScrollers();
|
||||||
if (fMenuFrame) {
|
if (fMenuFrame) {
|
||||||
if (fScroller) {
|
RemoveChild(fMenuFrame);
|
||||||
DetachScrollers();
|
|
||||||
} else {
|
|
||||||
RemoveChild(fMenuFrame);
|
|
||||||
}
|
|
||||||
delete fMenuFrame;
|
delete fMenuFrame;
|
||||||
fMenuFrame = NULL;
|
fMenuFrame = NULL;
|
||||||
|
fMenu = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,45 +271,112 @@ BMenuWindow::AttachScrollers()
|
|||||||
{
|
{
|
||||||
// We want to attach a scroller only if there's a menu frame already
|
// We want to attach a scroller only if there's a menu frame already
|
||||||
// existing.
|
// existing.
|
||||||
if (fScroller || !fMenuFrame)
|
if (!fMenu || !fMenuFrame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
fMenu->MakeFocus(true);
|
||||||
|
|
||||||
RemoveChild(fMenuFrame);
|
BRect frame = Bounds();
|
||||||
fScroller = new BMenuScroller(Bounds(), fMenuFrame->fMenu);
|
fUpperScroller = new UpperScroller(BRect(0, 0, frame.right, kScrollerHeight));
|
||||||
fScroller->AddChild(fMenuFrame);
|
AddChild(fUpperScroller);
|
||||||
AddChild(fScroller);
|
fLowerScroller = new LowerScroller(BRect(0, frame.bottom - kScrollerHeight, frame.right, frame.bottom));
|
||||||
|
AddChild(fLowerScroller);
|
||||||
fMenuFrame->fMenu->MakeFocus(true);
|
|
||||||
|
fUpperScroller->SetEnabled(false);
|
||||||
|
fLowerScroller->SetEnabled(true);
|
||||||
|
|
||||||
fMenuFrame->ResizeBy(0, -2 * kScrollerHeight);
|
fMenuFrame->ResizeBy(0, -2 * kScrollerHeight);
|
||||||
fMenuFrame->MoveBy(0, kScrollerHeight);
|
fMenuFrame->MoveBy(0, kScrollerHeight);
|
||||||
|
|
||||||
|
fMenuFrame->Bounds().PrintToStream();
|
||||||
|
fValue = 0;
|
||||||
|
fLimit = fMenu->Bounds().Height() - (frame.Height() - 2 * kScrollerHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BMenuWindow::DetachScrollers()
|
BMenuWindow::DetachScrollers()
|
||||||
{
|
{
|
||||||
if(!fScroller || !fMenuFrame)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// BeOS doesn't remember the position where the last scrolling ended,
|
// BeOS doesn't remember the position where the last scrolling ended,
|
||||||
// so we just scroll back to the beginning.
|
// so we just scroll back to the beginning.
|
||||||
fMenuFrame->fMenu->ScrollTo(0, 0);
|
fMenu->ScrollTo(0, 0);
|
||||||
|
|
||||||
fScroller->RemoveChild(fMenuFrame);
|
if (fLowerScroller) {
|
||||||
RemoveChild(fScroller);
|
RemoveChild(fLowerScroller);
|
||||||
|
delete fLowerScroller;
|
||||||
|
fLowerScroller = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
delete fScroller;
|
if (fUpperScroller) {
|
||||||
fScroller = NULL;
|
RemoveChild(fUpperScroller);
|
||||||
|
delete fUpperScroller;
|
||||||
|
fUpperScroller = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BMenuWindow::CheckForScrolling(BPoint cursor)
|
BMenuWindow::CheckForScrolling(BPoint cursor)
|
||||||
{
|
{
|
||||||
if (!fScroller)
|
if (!fMenuFrame)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return fScroller->Scroll(cursor);
|
return _Scroll(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
BMenuWindow::_Scroll(BPoint cursor)
|
||||||
|
{
|
||||||
|
ConvertFromScreen(&cursor);
|
||||||
|
|
||||||
|
BRect lowerFrame;
|
||||||
|
BRect upperFrame;
|
||||||
|
if (fLowerScroller)
|
||||||
|
lowerFrame = fLowerScroller->Frame();
|
||||||
|
if (fUpperScroller)
|
||||||
|
upperFrame = fUpperScroller->Frame();
|
||||||
|
|
||||||
|
if (fLowerScroller && fLowerScroller->IsEnabled() && lowerFrame.Contains(cursor)) {
|
||||||
|
if (fValue == 0) {
|
||||||
|
fUpperScroller->SetEnabled(true);
|
||||||
|
fUpperScroller->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fValue + kScrollStep >= fLimit) {
|
||||||
|
// If we reached the limit, we don't want to scroll a whole
|
||||||
|
// 'step' if not needed.
|
||||||
|
fMenu->ScrollBy(0, fLimit - fValue);
|
||||||
|
fValue = fLimit;
|
||||||
|
fLowerScroller->SetEnabled(false);
|
||||||
|
fLowerScroller->Invalidate();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fMenu->ScrollBy(0, kScrollStep);
|
||||||
|
fValue += kScrollStep;
|
||||||
|
}
|
||||||
|
} else if (fUpperScroller && fUpperScroller->IsEnabled() && upperFrame.Contains(cursor)) {
|
||||||
|
if (fValue == fLimit) {
|
||||||
|
fLowerScroller->SetEnabled(true);
|
||||||
|
fLowerScroller->Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fValue - kScrollStep <= 0) {
|
||||||
|
fMenu->ScrollBy(0, -fValue);
|
||||||
|
fValue = 0;
|
||||||
|
fUpperScroller->SetEnabled(false);
|
||||||
|
fUpperScroller->Invalidate();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fMenu->ScrollBy(0, -kScrollStep);
|
||||||
|
fValue -= kScrollStep;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
snooze(10000);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user