xref: /haiku/src/kits/interface/MenuWindow.cpp (revision c7bb90f8de3de030bd9b9e670cbc12543658dd8a)
1c7023acdSAxel Dörfler /*
2059ca4bdSStefano Ceccherini  * Copyright 2001-2007, Haiku, Inc.
3c7023acdSAxel Dörfler  * Distributed under the terms of the MIT License.
4c7023acdSAxel Dörfler  *
5c7023acdSAxel Dörfler  * Authors:
6c7023acdSAxel Dörfler  *		Marc Flerackers (mflerackers@androme.be)
7059ca4bdSStefano Ceccherini  *		Stefano Ceccherini (stefano.ceccherini@gmail.com)
8c7023acdSAxel Dörfler  */
9c7023acdSAxel Dörfler 
10c7023acdSAxel Dörfler //!	BMenuWindow is a custom BWindow for BMenus.
11c7023acdSAxel Dörfler 
122f86ba45SStephan Aßmus #include <MenuWindow.h>
132f86ba45SStephan Aßmus 
142f86ba45SStephan Aßmus #include <ControlLook.h>
15059ca4bdSStefano Ceccherini #include <Debug.h>
16446b8c19SStefano Ceccherini #include <Menu.h>
172c11ec31SStefano Ceccherini #include <MenuPrivate.h>
18c7023acdSAxel Dörfler #include <WindowPrivate.h>
19c7023acdSAxel Dörfler 
20e411c658SStefano Ceccherini 
212628e60cSAxel Dörfler namespace BPrivate {
222628e60cSAxel Dörfler 
232628e60cSAxel Dörfler class BMenuScroller : public BView {
242628e60cSAxel Dörfler 	public:
253616859aSStefano Ceccherini 		BMenuScroller(BRect frame);
262628e60cSAxel Dörfler 
273616859aSStefano Ceccherini 		bool IsEnabled() const;
283616859aSStefano Ceccherini 		void SetEnabled(const bool &enabled);
292628e60cSAxel Dörfler 	private:
303616859aSStefano Ceccherini 		bool fEnabled;
312628e60cSAxel Dörfler };
322628e60cSAxel Dörfler 
333616859aSStefano Ceccherini 
342628e60cSAxel Dörfler class BMenuFrame : public BView {
352628e60cSAxel Dörfler 	public:
362628e60cSAxel Dörfler 		BMenuFrame(BMenu *menu);
372628e60cSAxel Dörfler 
382628e60cSAxel Dörfler 		virtual void AttachedToWindow();
392628e60cSAxel Dörfler 		virtual void DetachedFromWindow();
402628e60cSAxel Dörfler 		virtual void Draw(BRect updateRect);
412628e60cSAxel Dörfler 
422628e60cSAxel Dörfler 	private:
432628e60cSAxel Dörfler 		friend class BMenuWindow;
442628e60cSAxel Dörfler 
452628e60cSAxel Dörfler 		BMenu *fMenu;
462628e60cSAxel Dörfler };
472628e60cSAxel Dörfler 
483616859aSStefano Ceccherini 
493616859aSStefano Ceccherini class UpperScroller : public BMenuScroller {
503616859aSStefano Ceccherini public:
513616859aSStefano Ceccherini 	UpperScroller(BRect frame);
523616859aSStefano Ceccherini 	virtual void Draw(BRect updateRect);
533616859aSStefano Ceccherini };
543616859aSStefano Ceccherini 
55059ca4bdSStefano Ceccherini 
563616859aSStefano Ceccherini class LowerScroller : public BMenuScroller {
573616859aSStefano Ceccherini public:
583616859aSStefano Ceccherini 	LowerScroller(BRect frame);
593616859aSStefano Ceccherini 	virtual void Draw(BRect updateRect);
603616859aSStefano Ceccherini };
613616859aSStefano Ceccherini 
62059ca4bdSStefano Ceccherini 
632628e60cSAxel Dörfler }	// namespace BPrivate
642628e60cSAxel Dörfler 
653616859aSStefano Ceccherini 
662628e60cSAxel Dörfler using namespace BPrivate;
672628e60cSAxel Dörfler 
682628e60cSAxel Dörfler 
6927cc2508SStefano Ceccherini const int kScrollerHeight = 10;
70c7338938SStefano Ceccherini const int kScrollStep = 19;
715b752875SStefano Ceccherini 
722628e60cSAxel Dörfler 
733616859aSStefano Ceccherini BMenuScroller::BMenuScroller(BRect frame)
74c7338938SStefano Ceccherini 	: BView(frame, "menu scroller", 0, B_WILL_DRAW | B_FRAME_EVENTS),
753616859aSStefano Ceccherini 	fEnabled(false)
7627cc2508SStefano Ceccherini {
7727cc2508SStefano Ceccherini 	SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
7827cc2508SStefano Ceccherini }
7927cc2508SStefano Ceccherini 
8027cc2508SStefano Ceccherini 
81c7338938SStefano Ceccherini bool
823616859aSStefano Ceccherini BMenuScroller::IsEnabled() const
8327cc2508SStefano Ceccherini {
843616859aSStefano Ceccherini 	return fEnabled;
8527cc2508SStefano Ceccherini }
8627cc2508SStefano Ceccherini 
8727cc2508SStefano Ceccherini 
8827cc2508SStefano Ceccherini void
893616859aSStefano Ceccherini BMenuScroller::SetEnabled(const bool &enabled)
903616859aSStefano Ceccherini {
913616859aSStefano Ceccherini 	fEnabled = enabled;
923616859aSStefano Ceccherini }
933616859aSStefano Ceccherini 
943616859aSStefano Ceccherini 
953616859aSStefano Ceccherini //	#pragma mark -
963616859aSStefano Ceccherini 
973616859aSStefano Ceccherini 
983616859aSStefano Ceccherini UpperScroller::UpperScroller(BRect frame)
993616859aSStefano Ceccherini 	:
1003616859aSStefano Ceccherini 	BMenuScroller(frame)
1013616859aSStefano Ceccherini {
1023616859aSStefano Ceccherini }
1033616859aSStefano Ceccherini 
1043616859aSStefano Ceccherini 
1053616859aSStefano Ceccherini void
1063616859aSStefano Ceccherini UpperScroller::Draw(BRect updateRect)
10727cc2508SStefano Ceccherini {
10827cc2508SStefano Ceccherini 	SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
10927cc2508SStefano Ceccherini 	float middle = Bounds().right / 2;
11027cc2508SStefano Ceccherini 
11127cc2508SStefano Ceccherini 	// Draw the upper arrow.
1123616859aSStefano Ceccherini 	if (IsEnabled())
11327cc2508SStefano Ceccherini 		SetHighColor(0, 0, 0);
11427cc2508SStefano Ceccherini 	else
11527cc2508SStefano Ceccherini 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
11627cc2508SStefano Ceccherini 					B_DARKEN_2_TINT));
11727cc2508SStefano Ceccherini 
1183616859aSStefano Ceccherini 	FillRect(Bounds(), B_SOLID_LOW);
11927cc2508SStefano Ceccherini 
12027cc2508SStefano Ceccherini 	FillTriangle(BPoint(middle, (kScrollerHeight / 2) - 3),
12127cc2508SStefano Ceccherini 			BPoint(middle + 5, (kScrollerHeight / 2) + 2),
12227cc2508SStefano Ceccherini 			BPoint(middle - 5, (kScrollerHeight / 2) + 2));
12327cc2508SStefano Ceccherini }
12427cc2508SStefano Ceccherini 
1253616859aSStefano Ceccherini 
1263616859aSStefano Ceccherini //	#pragma mark -
1273616859aSStefano Ceccherini 
1283616859aSStefano Ceccherini 
1293616859aSStefano Ceccherini LowerScroller::LowerScroller(BRect frame)
1303616859aSStefano Ceccherini 	:
1313616859aSStefano Ceccherini 	BMenuScroller(frame)
1323616859aSStefano Ceccherini {
1333616859aSStefano Ceccherini }
1343616859aSStefano Ceccherini 
1353616859aSStefano Ceccherini 
1363616859aSStefano Ceccherini void
1373616859aSStefano Ceccherini LowerScroller::Draw(BRect updateRect)
1383616859aSStefano Ceccherini {
1393616859aSStefano Ceccherini 	SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
1403616859aSStefano Ceccherini 
1413616859aSStefano Ceccherini 	BRect frame = Bounds();
14227cc2508SStefano Ceccherini 	// Draw the lower arrow.
1433616859aSStefano Ceccherini 	if (IsEnabled())
14427cc2508SStefano Ceccherini 		SetHighColor(0, 0, 0);
14527cc2508SStefano Ceccherini 	else
14627cc2508SStefano Ceccherini 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
14727cc2508SStefano Ceccherini 			B_DARKEN_2_TINT));
14827cc2508SStefano Ceccherini 
149059ca4bdSStefano Ceccherini 	FillRect(frame, B_SOLID_LOW);
15027cc2508SStefano Ceccherini 
1513616859aSStefano Ceccherini 	float middle = Bounds().right / 2;
1523616859aSStefano Ceccherini 
1533616859aSStefano Ceccherini 	FillTriangle(BPoint(middle, frame.bottom - (kScrollerHeight / 2) + 3),
1543616859aSStefano Ceccherini 			BPoint(middle + 5, frame.bottom - (kScrollerHeight / 2) - 2),
1553616859aSStefano Ceccherini 			BPoint(middle - 5, frame.bottom - (kScrollerHeight / 2) - 2));
15627cc2508SStefano Ceccherini }
15727cc2508SStefano Ceccherini 
15827cc2508SStefano Ceccherini 
15927cc2508SStefano Ceccherini //	#pragma mark -
1605b752875SStefano Ceccherini 
1615b752875SStefano Ceccherini 
1622628e60cSAxel Dörfler BMenuFrame::BMenuFrame(BMenu *menu)
1632628e60cSAxel Dörfler 	: BView(BRect(0, 0, 1, 1), "menu frame", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
1642628e60cSAxel Dörfler 	fMenu(menu)
1652628e60cSAxel Dörfler {
1662628e60cSAxel Dörfler }
1672628e60cSAxel Dörfler 
1682628e60cSAxel Dörfler 
1692628e60cSAxel Dörfler void
1702628e60cSAxel Dörfler BMenuFrame::AttachedToWindow()
1712628e60cSAxel Dörfler {
1722628e60cSAxel Dörfler 	BView::AttachedToWindow();
1732628e60cSAxel Dörfler 
1742628e60cSAxel Dörfler 	if (fMenu != NULL)
1752628e60cSAxel Dörfler 		AddChild(fMenu);
1762628e60cSAxel Dörfler 
1772628e60cSAxel Dörfler 	ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height());
1782628e60cSAxel Dörfler 	if (fMenu != NULL) {
1792628e60cSAxel Dörfler 		BFont font;
1802628e60cSAxel Dörfler 		fMenu->GetFont(&font);
1812628e60cSAxel Dörfler 		SetFont(&font);
1822628e60cSAxel Dörfler 	}
1832628e60cSAxel Dörfler }
1842628e60cSAxel Dörfler 
1852628e60cSAxel Dörfler 
1862628e60cSAxel Dörfler void
1872628e60cSAxel Dörfler BMenuFrame::DetachedFromWindow()
1882628e60cSAxel Dörfler {
1892628e60cSAxel Dörfler 	if (fMenu != NULL)
1902628e60cSAxel Dörfler 		RemoveChild(fMenu);
1912628e60cSAxel Dörfler }
1922628e60cSAxel Dörfler 
1932628e60cSAxel Dörfler 
1942628e60cSAxel Dörfler void
1952628e60cSAxel Dörfler BMenuFrame::Draw(BRect updateRect)
1962628e60cSAxel Dörfler {
1972628e60cSAxel Dörfler 	if (fMenu != NULL && fMenu->CountItems() == 0) {
1982f86ba45SStephan Aßmus 		if (be_control_look != NULL) {
1992f86ba45SStephan Aßmus 			BRect rect(Bounds());
2002f86ba45SStephan Aßmus 			be_control_look->DrawMenuBackground(this, rect, updateRect,
2012f86ba45SStephan Aßmus 				ui_color(B_MENU_BACKGROUND_COLOR));
2022f86ba45SStephan Aßmus 			SetDrawingMode(B_OP_OVER);
2032f86ba45SStephan Aßmus 		} else {
2042628e60cSAxel Dörfler 			// TODO: Review this as it's a bit hacky.
2052628e60cSAxel Dörfler 			// Menu has a size of 0, 0, since there are no items in it.
2062628e60cSAxel Dörfler 			// So the BMenuFrame class has to fake it and draw an empty item.
2072628e60cSAxel Dörfler 			// Note that we can't add a real "empty" item because then we couldn't
2082628e60cSAxel Dörfler 			// tell if the item was added by us or not.
2092628e60cSAxel Dörfler 			// See also BMenu::UpdateWindowViewSize()
2102628e60cSAxel Dörfler 			SetHighColor(ui_color(B_MENU_BACKGROUND_COLOR));
2112628e60cSAxel Dörfler 			SetLowColor(HighColor());
2122628e60cSAxel Dörfler 			FillRect(updateRect);
2132f86ba45SStephan Aßmus 		}
2142628e60cSAxel Dörfler 
2152628e60cSAxel Dörfler 		font_height height;
2162628e60cSAxel Dörfler 		GetFontHeight(&height);
2172628e60cSAxel Dörfler 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DISABLED_LABEL_TINT));
2182628e60cSAxel Dörfler 		BPoint where((Bounds().Width() - fMenu->StringWidth(kEmptyMenuLabel)) / 2, ceilf(height.ascent + 1));
2192628e60cSAxel Dörfler 		DrawString(kEmptyMenuLabel, where);
2202628e60cSAxel Dörfler 	}
2212628e60cSAxel Dörfler 
2222f86ba45SStephan Aßmus 	if (be_control_look != NULL)
2232f86ba45SStephan Aßmus 		return;
2242f86ba45SStephan Aßmus 
2252628e60cSAxel Dörfler 	SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_2_TINT));
2262628e60cSAxel Dörfler 	BRect bounds(Bounds());
2272628e60cSAxel Dörfler 
2282628e60cSAxel Dörfler 	StrokeLine(BPoint(bounds.right, bounds.top),
2292628e60cSAxel Dörfler 		BPoint(bounds.right, bounds.bottom - 1));
2302628e60cSAxel Dörfler 	StrokeLine(BPoint(bounds.left + 1, bounds.bottom),
2312628e60cSAxel Dörfler 		BPoint(bounds.right, bounds.bottom));
2322628e60cSAxel Dörfler }
2332628e60cSAxel Dörfler 
2342628e60cSAxel Dörfler 
2353616859aSStefano Ceccherini 
2362628e60cSAxel Dörfler //	#pragma mark -
2372628e60cSAxel Dörfler 
2382628e60cSAxel Dörfler 
2394185bd8bSStefano Ceccherini BMenuWindow::BMenuWindow(const char *name)
2401664b981SStefano Ceccherini 	// The window will be resized by BMenu, so just pass a dummy rect
241c7023acdSAxel Dörfler 	: BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
242c7023acdSAxel Dörfler 			B_NOT_ZOOMABLE | B_AVOID_FOCUS),
2433616859aSStefano Ceccherini 	fMenu(NULL),
2443616859aSStefano Ceccherini 	fMenuFrame(NULL),
2453616859aSStefano Ceccherini 	fUpperScroller(NULL),
2463616859aSStefano Ceccherini 	fLowerScroller(NULL)
247446b8c19SStefano Ceccherini {
2482f86ba45SStephan Aßmus 	SetSizeLimits(2, 10000, 2, 10000);
249446b8c19SStefano Ceccherini }
250446b8c19SStefano Ceccherini 
251446b8c19SStefano Ceccherini 
252446b8c19SStefano Ceccherini BMenuWindow::~BMenuWindow()
253446b8c19SStefano Ceccherini {
254059ca4bdSStefano Ceccherini 	DetachMenu();
255446b8c19SStefano Ceccherini }
2565aa032f1SStefano Ceccherini 
2575aa032f1SStefano Ceccherini 
25861ba5a32SStefano Ceccherini void
2599e64a7edSStefano Ceccherini BMenuWindow::DispatchMessage(BMessage *message, BHandler *handler)
2609e64a7edSStefano Ceccherini {
2619e64a7edSStefano Ceccherini 	BWindow::DispatchMessage(message, handler);
2629e64a7edSStefano Ceccherini }
2639e64a7edSStefano Ceccherini 
2649e64a7edSStefano Ceccherini 
2659e64a7edSStefano Ceccherini void
2664185bd8bSStefano Ceccherini BMenuWindow::AttachMenu(BMenu *menu)
2674185bd8bSStefano Ceccherini {
26827cc2508SStefano Ceccherini 	if (fMenuFrame)
26927cc2508SStefano Ceccherini 		debugger("BMenuWindow: a menu is already attached!");
2704185bd8bSStefano Ceccherini 	if (menu != NULL) {
27127cc2508SStefano Ceccherini 		fMenuFrame = new BMenuFrame(menu);
27227cc2508SStefano Ceccherini 		AddChild(fMenuFrame);
27307dc2c69SAxel Dörfler 		menu->MakeFocus(true);
2743616859aSStefano Ceccherini 		fMenu = menu;
2754185bd8bSStefano Ceccherini 	}
2764185bd8bSStefano Ceccherini }
2774185bd8bSStefano Ceccherini 
2784185bd8bSStefano Ceccherini 
2794185bd8bSStefano Ceccherini void
2804185bd8bSStefano Ceccherini BMenuWindow::DetachMenu()
28161ba5a32SStefano Ceccherini {
28227cc2508SStefano Ceccherini 	DetachScrollers();
2833616859aSStefano Ceccherini 	if (fMenuFrame) {
28427cc2508SStefano Ceccherini 		RemoveChild(fMenuFrame);
28527cc2508SStefano Ceccherini 		delete fMenuFrame;
28627cc2508SStefano Ceccherini 		fMenuFrame = NULL;
2873616859aSStefano Ceccherini 		fMenu = NULL;
28827cc2508SStefano Ceccherini 	}
28927cc2508SStefano Ceccherini }
29027cc2508SStefano Ceccherini 
29127cc2508SStefano Ceccherini 
29227cc2508SStefano Ceccherini void
29327cc2508SStefano Ceccherini BMenuWindow::AttachScrollers()
29427cc2508SStefano Ceccherini {
29560e1cfbfSStefano Ceccherini 	// We want to attach a scroller only if there's a
29660e1cfbfSStefano Ceccherini 	// menu frame already existing.
2973616859aSStefano Ceccherini 	if (!fMenu || !fMenuFrame)
29827cc2508SStefano Ceccherini 		return;
29927cc2508SStefano Ceccherini 
3003616859aSStefano Ceccherini 	fMenu->MakeFocus(true);
30127cc2508SStefano Ceccherini 
3023616859aSStefano Ceccherini 	BRect frame = Bounds();
30360e1cfbfSStefano Ceccherini 
30460e1cfbfSStefano Ceccherini 	if (fUpperScroller == NULL) {
30560e1cfbfSStefano Ceccherini 		fUpperScroller = new UpperScroller(
306*c7bb90f8SStephan Aßmus 			BRect(0, 0, frame.right, kScrollerHeight - 1));
3073616859aSStefano Ceccherini 		AddChild(fUpperScroller);
30860e1cfbfSStefano Ceccherini 	}
30960e1cfbfSStefano Ceccherini 
31060e1cfbfSStefano Ceccherini 	if (fLowerScroller == NULL) {
31160e1cfbfSStefano Ceccherini 		fLowerScroller = new LowerScroller(
312*c7bb90f8SStephan Aßmus 			BRect(0, frame.bottom - kScrollerHeight + 1, frame.right,
313*c7bb90f8SStephan Aßmus 				frame.bottom));
3143616859aSStefano Ceccherini 		AddChild(fLowerScroller);
31560e1cfbfSStefano Ceccherini 	}
3163616859aSStefano Ceccherini 
3173616859aSStefano Ceccherini 	fUpperScroller->SetEnabled(false);
3183616859aSStefano Ceccherini 	fLowerScroller->SetEnabled(true);
31927cc2508SStefano Ceccherini 
320*c7bb90f8SStephan Aßmus 	fMenuFrame->ResizeBy(0, -2 * kScrollerHeight);
32127cc2508SStefano Ceccherini 	fMenuFrame->MoveBy(0, kScrollerHeight);
3223616859aSStefano Ceccherini 
3233616859aSStefano Ceccherini 	fValue = 0;
3243616859aSStefano Ceccherini 	fLimit = fMenu->Bounds().Height() - (frame.Height() - 2 * kScrollerHeight);
32527cc2508SStefano Ceccherini }
32627cc2508SStefano Ceccherini 
32727cc2508SStefano Ceccherini 
32827cc2508SStefano Ceccherini void
32927cc2508SStefano Ceccherini BMenuWindow::DetachScrollers()
33027cc2508SStefano Ceccherini {
33127cc2508SStefano Ceccherini 	// BeOS doesn't remember the position where the last scrolling ended,
33227cc2508SStefano Ceccherini 	// so we just scroll back to the beginning.
333059ca4bdSStefano Ceccherini 	if (fMenu)
3343616859aSStefano Ceccherini 		fMenu->ScrollTo(0, 0);
33527cc2508SStefano Ceccherini 
3363616859aSStefano Ceccherini 	if (fLowerScroller) {
3373616859aSStefano Ceccherini 		RemoveChild(fLowerScroller);
3383616859aSStefano Ceccherini 		delete fLowerScroller;
3393616859aSStefano Ceccherini 		fLowerScroller = NULL;
3403616859aSStefano Ceccherini 	}
34127cc2508SStefano Ceccherini 
3423616859aSStefano Ceccherini 	if (fUpperScroller) {
3433616859aSStefano Ceccherini 		RemoveChild(fUpperScroller);
3443616859aSStefano Ceccherini 		delete fUpperScroller;
3453616859aSStefano Ceccherini 		fUpperScroller = NULL;
3463616859aSStefano Ceccherini 	}
34761ba5a32SStefano Ceccherini }
348c7338938SStefano Ceccherini 
349c7338938SStefano Ceccherini 
350c7338938SStefano Ceccherini bool
3514e0c2a79SStefano Ceccherini BMenuWindow::CheckForScrolling(const BPoint &cursor)
352c7338938SStefano Ceccherini {
353059ca4bdSStefano Ceccherini 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
354c7338938SStefano Ceccherini 		return false;
355c7338938SStefano Ceccherini 
3563616859aSStefano Ceccherini 	return _Scroll(cursor);
3573616859aSStefano Ceccherini }
3583616859aSStefano Ceccherini 
3593616859aSStefano Ceccherini 
3603616859aSStefano Ceccherini bool
3614e0c2a79SStefano Ceccherini BMenuWindow::TryScrollBy(const float &step)
3624e0c2a79SStefano Ceccherini {
3634e0c2a79SStefano Ceccherini 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
3644e0c2a79SStefano Ceccherini 		return false;
3654e0c2a79SStefano Ceccherini 
3664e0c2a79SStefano Ceccherini 	_ScrollBy(step);
3674e0c2a79SStefano Ceccherini 
3684e0c2a79SStefano Ceccherini 	return true;
3694e0c2a79SStefano Ceccherini }
3704e0c2a79SStefano Ceccherini 
3714e0c2a79SStefano Ceccherini 
3724e0c2a79SStefano Ceccherini bool
3734e0c2a79SStefano Ceccherini BMenuWindow::_Scroll(const BPoint &where)
3743616859aSStefano Ceccherini {
375059ca4bdSStefano Ceccherini 	ASSERT((fLowerScroller != NULL));
376059ca4bdSStefano Ceccherini 	ASSERT((fUpperScroller != NULL));
377059ca4bdSStefano Ceccherini 
3784e0c2a79SStefano Ceccherini 	const BPoint cursor = ConvertFromScreen(where);
3793616859aSStefano Ceccherini 
380059ca4bdSStefano Ceccherini 	BRect lowerFrame = fLowerScroller->Frame();
381059ca4bdSStefano Ceccherini 	BRect upperFrame = fUpperScroller->Frame();
3823616859aSStefano Ceccherini 
383059ca4bdSStefano Ceccherini 	if (fLowerScroller->IsEnabled() && lowerFrame.Contains(cursor)) {
3844e0c2a79SStefano Ceccherini 		_ScrollBy(1);
3854e0c2a79SStefano Ceccherini 	} else if (fUpperScroller->IsEnabled() && upperFrame.Contains(cursor)) {
3864e0c2a79SStefano Ceccherini 		_ScrollBy(-1);
3874e0c2a79SStefano Ceccherini 	} else
3884e0c2a79SStefano Ceccherini 		return false;
3894e0c2a79SStefano Ceccherini 
3902f86ba45SStephan Aßmus 	snooze(5000);
3914e0c2a79SStefano Ceccherini 
3924e0c2a79SStefano Ceccherini 	return true;
3934e0c2a79SStefano Ceccherini }
3944e0c2a79SStefano Ceccherini 
3954e0c2a79SStefano Ceccherini 
3964e0c2a79SStefano Ceccherini void
3974e0c2a79SStefano Ceccherini BMenuWindow::_ScrollBy(const float &step)
3984e0c2a79SStefano Ceccherini {
3994e0c2a79SStefano Ceccherini 	if (step > 0) {
4003616859aSStefano Ceccherini 		if (fValue == 0) {
4013616859aSStefano Ceccherini 			fUpperScroller->SetEnabled(true);
4023616859aSStefano Ceccherini 			fUpperScroller->Invalidate();
4033616859aSStefano Ceccherini 		}
4043616859aSStefano Ceccherini 
4053616859aSStefano Ceccherini 		if (fValue + kScrollStep >= fLimit) {
4063616859aSStefano Ceccherini 			// If we reached the limit, we don't want to scroll a whole
4073616859aSStefano Ceccherini 			// 'step' if not needed.
4083616859aSStefano Ceccherini 			fMenu->ScrollBy(0, fLimit - fValue);
4093616859aSStefano Ceccherini 			fValue = fLimit;
4103616859aSStefano Ceccherini 			fLowerScroller->SetEnabled(false);
4113616859aSStefano Ceccherini 			fLowerScroller->Invalidate();
4123616859aSStefano Ceccherini 
4133616859aSStefano Ceccherini 		} else {
4143616859aSStefano Ceccherini 			fMenu->ScrollBy(0, kScrollStep);
4153616859aSStefano Ceccherini 			fValue += kScrollStep;
4163616859aSStefano Ceccherini 		}
4174e0c2a79SStefano Ceccherini 	} else if (step < 0) {
4183616859aSStefano Ceccherini 		if (fValue == fLimit) {
4193616859aSStefano Ceccherini 			fLowerScroller->SetEnabled(true);
4203616859aSStefano Ceccherini 			fLowerScroller->Invalidate();
4213616859aSStefano Ceccherini 		}
4223616859aSStefano Ceccherini 
4233616859aSStefano Ceccherini 		if (fValue - kScrollStep <= 0) {
4243616859aSStefano Ceccherini 			fMenu->ScrollBy(0, -fValue);
4253616859aSStefano Ceccherini 			fValue = 0;
4263616859aSStefano Ceccherini 			fUpperScroller->SetEnabled(false);
4273616859aSStefano Ceccherini 			fUpperScroller->Invalidate();
4283616859aSStefano Ceccherini 
4293616859aSStefano Ceccherini 		} else {
4303616859aSStefano Ceccherini 			fMenu->ScrollBy(0, -kScrollStep);
4313616859aSStefano Ceccherini 			fValue -= kScrollStep;
4323616859aSStefano Ceccherini 		}
4334e0c2a79SStefano Ceccherini 	}
434c7338938SStefano Ceccherini }
435c7338938SStefano Ceccherini 
436