xref: /haiku/src/kits/interface/MenuWindow.cpp (revision 50f8cd14bb40895f9167f44752525386af219513)
1c7023acdSAxel Dörfler /*
24e23bc03SAxel Dörfler  * Copyright 2001-2009, 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>
174e23bc03SAxel Dörfler #include <MenuItem.h>
184e23bc03SAxel Dörfler 
192c11ec31SStefano Ceccherini #include <MenuPrivate.h>
20c7023acdSAxel Dörfler #include <WindowPrivate.h>
21c7023acdSAxel Dörfler 
22e411c658SStefano Ceccherini 
232628e60cSAxel Dörfler namespace BPrivate {
242628e60cSAxel Dörfler 
252628e60cSAxel Dörfler class BMenuScroller : public BView {
262628e60cSAxel Dörfler public:
273616859aSStefano Ceccherini 							BMenuScroller(BRect frame);
282628e60cSAxel Dörfler 
293616859aSStefano Ceccherini 			bool			IsEnabled() const;
30*50f8cd14SAxel Dörfler 			void			SetEnabled(bool enabled);
31*50f8cd14SAxel Dörfler 
322628e60cSAxel Dörfler private:
333616859aSStefano Ceccherini 			bool			fEnabled;
342628e60cSAxel Dörfler };
352628e60cSAxel Dörfler 
363616859aSStefano Ceccherini 
372628e60cSAxel Dörfler class BMenuFrame : public BView {
382628e60cSAxel Dörfler public:
392628e60cSAxel Dörfler 							BMenuFrame(BMenu* menu);
402628e60cSAxel Dörfler 
412628e60cSAxel Dörfler 	virtual	void			AttachedToWindow();
422628e60cSAxel Dörfler 	virtual	void			DetachedFromWindow();
432628e60cSAxel Dörfler 	virtual	void			Draw(BRect updateRect);
442628e60cSAxel Dörfler 
452628e60cSAxel Dörfler private:
462628e60cSAxel Dörfler 	friend class BMenuWindow;
472628e60cSAxel Dörfler 
482628e60cSAxel Dörfler 			BMenu*			fMenu;
492628e60cSAxel Dörfler };
502628e60cSAxel Dörfler 
513616859aSStefano Ceccherini 
523616859aSStefano Ceccherini class UpperScroller : public BMenuScroller {
533616859aSStefano Ceccherini public:
543616859aSStefano Ceccherini 							UpperScroller(BRect frame);
55*50f8cd14SAxel Dörfler 
563616859aSStefano Ceccherini 	virtual	void			Draw(BRect updateRect);
573616859aSStefano Ceccherini };
583616859aSStefano Ceccherini 
59059ca4bdSStefano Ceccherini 
603616859aSStefano Ceccherini class LowerScroller : public BMenuScroller {
613616859aSStefano Ceccherini public:
623616859aSStefano Ceccherini 							LowerScroller(BRect frame);
63*50f8cd14SAxel Dörfler 
643616859aSStefano Ceccherini 	virtual	void			Draw(BRect updateRect);
653616859aSStefano Ceccherini };
663616859aSStefano Ceccherini 
67059ca4bdSStefano Ceccherini 
682628e60cSAxel Dörfler }	// namespace BPrivate
692628e60cSAxel Dörfler 
703616859aSStefano Ceccherini 
712628e60cSAxel Dörfler using namespace BPrivate;
722628e60cSAxel Dörfler 
732628e60cSAxel Dörfler 
7427cc2508SStefano Ceccherini const int kScrollerHeight = 10;
755b752875SStefano Ceccherini 
762628e60cSAxel Dörfler 
773616859aSStefano Ceccherini BMenuScroller::BMenuScroller(BRect frame)
78*50f8cd14SAxel Dörfler 	:
79*50f8cd14SAxel Dörfler 	BView(frame, "menu scroller", 0, B_WILL_DRAW | B_FRAME_EVENTS),
803616859aSStefano Ceccherini 	fEnabled(false)
8127cc2508SStefano Ceccherini {
8227cc2508SStefano Ceccherini 	SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
8327cc2508SStefano Ceccherini }
8427cc2508SStefano Ceccherini 
8527cc2508SStefano Ceccherini 
86c7338938SStefano Ceccherini bool
873616859aSStefano Ceccherini BMenuScroller::IsEnabled() const
8827cc2508SStefano Ceccherini {
893616859aSStefano Ceccherini 	return fEnabled;
9027cc2508SStefano Ceccherini }
9127cc2508SStefano Ceccherini 
9227cc2508SStefano Ceccherini 
9327cc2508SStefano Ceccherini void
94*50f8cd14SAxel Dörfler BMenuScroller::SetEnabled(bool enabled)
953616859aSStefano Ceccherini {
963616859aSStefano Ceccherini 	fEnabled = enabled;
973616859aSStefano Ceccherini }
983616859aSStefano Ceccherini 
993616859aSStefano Ceccherini 
1003616859aSStefano Ceccherini //	#pragma mark -
1013616859aSStefano Ceccherini 
1023616859aSStefano Ceccherini 
1033616859aSStefano Ceccherini UpperScroller::UpperScroller(BRect frame)
1043616859aSStefano Ceccherini 	:
1053616859aSStefano Ceccherini 	BMenuScroller(frame)
1063616859aSStefano Ceccherini {
1073616859aSStefano Ceccherini }
1083616859aSStefano Ceccherini 
1093616859aSStefano Ceccherini 
1103616859aSStefano Ceccherini void
1113616859aSStefano Ceccherini UpperScroller::Draw(BRect updateRect)
11227cc2508SStefano Ceccherini {
11327cc2508SStefano Ceccherini 	SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
11427cc2508SStefano Ceccherini 	float middle = Bounds().right / 2;
11527cc2508SStefano Ceccherini 
11627cc2508SStefano Ceccherini 	// Draw the upper arrow.
1173616859aSStefano Ceccherini 	if (IsEnabled())
11827cc2508SStefano Ceccherini 		SetHighColor(0, 0, 0);
119*50f8cd14SAxel Dörfler 	else {
12027cc2508SStefano Ceccherini 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
12127cc2508SStefano Ceccherini 			B_DARKEN_2_TINT));
122*50f8cd14SAxel Dörfler 	}
12327cc2508SStefano Ceccherini 
1243616859aSStefano Ceccherini 	FillRect(Bounds(), B_SOLID_LOW);
12527cc2508SStefano Ceccherini 
12627cc2508SStefano Ceccherini 	FillTriangle(BPoint(middle, (kScrollerHeight / 2) - 3),
12727cc2508SStefano Ceccherini 		BPoint(middle + 5, (kScrollerHeight / 2) + 2),
12827cc2508SStefano Ceccherini 		BPoint(middle - 5, (kScrollerHeight / 2) + 2));
12927cc2508SStefano Ceccherini }
13027cc2508SStefano Ceccherini 
1313616859aSStefano Ceccherini 
1323616859aSStefano Ceccherini //	#pragma mark -
1333616859aSStefano Ceccherini 
1343616859aSStefano Ceccherini 
1353616859aSStefano Ceccherini LowerScroller::LowerScroller(BRect frame)
1363616859aSStefano Ceccherini 	:
1373616859aSStefano Ceccherini 	BMenuScroller(frame)
1383616859aSStefano Ceccherini {
1393616859aSStefano Ceccherini }
1403616859aSStefano Ceccherini 
1413616859aSStefano Ceccherini 
1423616859aSStefano Ceccherini void
1433616859aSStefano Ceccherini LowerScroller::Draw(BRect updateRect)
1443616859aSStefano Ceccherini {
1453616859aSStefano Ceccherini 	SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
1463616859aSStefano Ceccherini 
1473616859aSStefano Ceccherini 	BRect frame = Bounds();
14827cc2508SStefano Ceccherini 	// Draw the lower arrow.
1493616859aSStefano Ceccherini 	if (IsEnabled())
15027cc2508SStefano Ceccherini 		SetHighColor(0, 0, 0);
151*50f8cd14SAxel Dörfler 	else {
15227cc2508SStefano Ceccherini 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
15327cc2508SStefano Ceccherini 			B_DARKEN_2_TINT));
154*50f8cd14SAxel Dörfler 	}
15527cc2508SStefano Ceccherini 
156059ca4bdSStefano Ceccherini 	FillRect(frame, B_SOLID_LOW);
15727cc2508SStefano Ceccherini 
1583616859aSStefano Ceccherini 	float middle = Bounds().right / 2;
1593616859aSStefano Ceccherini 
1603616859aSStefano Ceccherini 	FillTriangle(BPoint(middle, frame.bottom - (kScrollerHeight / 2) + 3),
1613616859aSStefano Ceccherini 		BPoint(middle + 5, frame.bottom - (kScrollerHeight / 2) - 2),
1623616859aSStefano Ceccherini 		BPoint(middle - 5, frame.bottom - (kScrollerHeight / 2) - 2));
16327cc2508SStefano Ceccherini }
16427cc2508SStefano Ceccherini 
16527cc2508SStefano Ceccherini 
16627cc2508SStefano Ceccherini //	#pragma mark -
1675b752875SStefano Ceccherini 
1685b752875SStefano Ceccherini 
1692628e60cSAxel Dörfler BMenuFrame::BMenuFrame(BMenu *menu)
170*50f8cd14SAxel Dörfler 	:
171*50f8cd14SAxel Dörfler 	BView(BRect(0, 0, 1, 1), "menu frame", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
1722628e60cSAxel Dörfler 	fMenu(menu)
1732628e60cSAxel Dörfler {
1742628e60cSAxel Dörfler }
1752628e60cSAxel Dörfler 
1762628e60cSAxel Dörfler 
1772628e60cSAxel Dörfler void
1782628e60cSAxel Dörfler BMenuFrame::AttachedToWindow()
1792628e60cSAxel Dörfler {
1802628e60cSAxel Dörfler 	BView::AttachedToWindow();
1812628e60cSAxel Dörfler 
1822628e60cSAxel Dörfler 	if (fMenu != NULL)
1832628e60cSAxel Dörfler 		AddChild(fMenu);
1842628e60cSAxel Dörfler 
1852628e60cSAxel Dörfler 	ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height());
1862628e60cSAxel Dörfler 	if (fMenu != NULL) {
1872628e60cSAxel Dörfler 		BFont font;
1882628e60cSAxel Dörfler 		fMenu->GetFont(&font);
1892628e60cSAxel Dörfler 		SetFont(&font);
1902628e60cSAxel Dörfler 	}
1912628e60cSAxel Dörfler }
1922628e60cSAxel Dörfler 
1932628e60cSAxel Dörfler 
1942628e60cSAxel Dörfler void
1952628e60cSAxel Dörfler BMenuFrame::DetachedFromWindow()
1962628e60cSAxel Dörfler {
1972628e60cSAxel Dörfler 	if (fMenu != NULL)
1982628e60cSAxel Dörfler 		RemoveChild(fMenu);
1992628e60cSAxel Dörfler }
2002628e60cSAxel Dörfler 
2012628e60cSAxel Dörfler 
2022628e60cSAxel Dörfler void
2032628e60cSAxel Dörfler BMenuFrame::Draw(BRect updateRect)
2042628e60cSAxel Dörfler {
2052628e60cSAxel Dörfler 	if (fMenu != NULL && fMenu->CountItems() == 0) {
2062f86ba45SStephan Aßmus 		if (be_control_look != NULL) {
2072f86ba45SStephan Aßmus 			BRect rect(Bounds());
2082f86ba45SStephan Aßmus 			be_control_look->DrawMenuBackground(this, rect, updateRect,
2092f86ba45SStephan Aßmus 				ui_color(B_MENU_BACKGROUND_COLOR));
2102f86ba45SStephan Aßmus 			SetDrawingMode(B_OP_OVER);
2112f86ba45SStephan Aßmus 		} else {
2122628e60cSAxel Dörfler 			// TODO: Review this as it's a bit hacky.
2132628e60cSAxel Dörfler 			// Menu has a size of 0, 0, since there are no items in it.
2142628e60cSAxel Dörfler 			// So the BMenuFrame class has to fake it and draw an empty item.
215*50f8cd14SAxel Dörfler 			// Note that we can't add a real "empty" item because then we
216*50f8cd14SAxel Dörfler 			// couldn't tell if the item was added by us or not.
2172628e60cSAxel Dörfler 			// See also BMenu::UpdateWindowViewSize()
2182628e60cSAxel Dörfler 			SetHighColor(ui_color(B_MENU_BACKGROUND_COLOR));
2192628e60cSAxel Dörfler 			SetLowColor(HighColor());
2202628e60cSAxel Dörfler 			FillRect(updateRect);
2212f86ba45SStephan Aßmus 		}
2222628e60cSAxel Dörfler 
2232628e60cSAxel Dörfler 		font_height height;
2242628e60cSAxel Dörfler 		GetFontHeight(&height);
225*50f8cd14SAxel Dörfler 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
226*50f8cd14SAxel Dörfler 			B_DISABLED_LABEL_TINT));
227*50f8cd14SAxel Dörfler 		BPoint where(
228*50f8cd14SAxel Dörfler 			(Bounds().Width() - fMenu->StringWidth(kEmptyMenuLabel)) / 2,
229*50f8cd14SAxel Dörfler 			ceilf(height.ascent + 1));
2302628e60cSAxel Dörfler 		DrawString(kEmptyMenuLabel, where);
2312628e60cSAxel Dörfler 	}
2322628e60cSAxel Dörfler 
2332f86ba45SStephan Aßmus 	if (be_control_look != NULL)
2342f86ba45SStephan Aßmus 		return;
2352f86ba45SStephan Aßmus 
2362628e60cSAxel Dörfler 	SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_2_TINT));
2372628e60cSAxel Dörfler 	BRect bounds(Bounds());
2382628e60cSAxel Dörfler 
2392628e60cSAxel Dörfler 	StrokeLine(BPoint(bounds.right, bounds.top),
2402628e60cSAxel Dörfler 		BPoint(bounds.right, bounds.bottom - 1));
2412628e60cSAxel Dörfler 	StrokeLine(BPoint(bounds.left + 1, bounds.bottom),
2422628e60cSAxel Dörfler 		BPoint(bounds.right, bounds.bottom));
2432628e60cSAxel Dörfler }
2442628e60cSAxel Dörfler 
2452628e60cSAxel Dörfler 
2463616859aSStefano Ceccherini 
2472628e60cSAxel Dörfler //	#pragma mark -
2482628e60cSAxel Dörfler 
2492628e60cSAxel Dörfler 
2504185bd8bSStefano Ceccherini BMenuWindow::BMenuWindow(const char *name)
2511664b981SStefano Ceccherini 	// The window will be resized by BMenu, so just pass a dummy rect
252c7023acdSAxel Dörfler 	: BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
253c7023acdSAxel Dörfler 			B_NOT_ZOOMABLE | B_AVOID_FOCUS),
2543616859aSStefano Ceccherini 	fMenu(NULL),
2553616859aSStefano Ceccherini 	fMenuFrame(NULL),
2563616859aSStefano Ceccherini 	fUpperScroller(NULL),
2574e23bc03SAxel Dörfler 	fLowerScroller(NULL),
2584e23bc03SAxel Dörfler 	fScrollStep(19)
259446b8c19SStefano Ceccherini {
2602f86ba45SStephan Aßmus 	SetSizeLimits(2, 10000, 2, 10000);
261446b8c19SStefano Ceccherini }
262446b8c19SStefano Ceccherini 
263446b8c19SStefano Ceccherini 
264446b8c19SStefano Ceccherini BMenuWindow::~BMenuWindow()
265446b8c19SStefano Ceccherini {
266059ca4bdSStefano Ceccherini 	DetachMenu();
267446b8c19SStefano Ceccherini }
2685aa032f1SStefano Ceccherini 
2695aa032f1SStefano Ceccherini 
27061ba5a32SStefano Ceccherini void
2719e64a7edSStefano Ceccherini BMenuWindow::DispatchMessage(BMessage *message, BHandler *handler)
2729e64a7edSStefano Ceccherini {
2739e64a7edSStefano Ceccherini 	BWindow::DispatchMessage(message, handler);
2749e64a7edSStefano Ceccherini }
2759e64a7edSStefano Ceccherini 
2769e64a7edSStefano Ceccherini 
2779e64a7edSStefano Ceccherini void
2784185bd8bSStefano Ceccherini BMenuWindow::AttachMenu(BMenu *menu)
2794185bd8bSStefano Ceccherini {
28027cc2508SStefano Ceccherini 	if (fMenuFrame)
28127cc2508SStefano Ceccherini 		debugger("BMenuWindow: a menu is already attached!");
2824185bd8bSStefano Ceccherini 	if (menu != NULL) {
28327cc2508SStefano Ceccherini 		fMenuFrame = new BMenuFrame(menu);
28427cc2508SStefano Ceccherini 		AddChild(fMenuFrame);
28507dc2c69SAxel Dörfler 		menu->MakeFocus(true);
2863616859aSStefano Ceccherini 		fMenu = menu;
2874185bd8bSStefano Ceccherini 	}
2884185bd8bSStefano Ceccherini }
2894185bd8bSStefano Ceccherini 
2904185bd8bSStefano Ceccherini 
2914185bd8bSStefano Ceccherini void
2924185bd8bSStefano Ceccherini BMenuWindow::DetachMenu()
29361ba5a32SStefano Ceccherini {
29427cc2508SStefano Ceccherini 	DetachScrollers();
2953616859aSStefano Ceccherini 	if (fMenuFrame) {
29627cc2508SStefano Ceccherini 		RemoveChild(fMenuFrame);
29727cc2508SStefano Ceccherini 		delete fMenuFrame;
29827cc2508SStefano Ceccherini 		fMenuFrame = NULL;
2993616859aSStefano Ceccherini 		fMenu = NULL;
30027cc2508SStefano Ceccherini 	}
30127cc2508SStefano Ceccherini }
30227cc2508SStefano Ceccherini 
30327cc2508SStefano Ceccherini 
30427cc2508SStefano Ceccherini void
30527cc2508SStefano Ceccherini BMenuWindow::AttachScrollers()
30627cc2508SStefano Ceccherini {
30760e1cfbfSStefano Ceccherini 	// We want to attach a scroller only if there's a
30860e1cfbfSStefano Ceccherini 	// menu frame already existing.
3093616859aSStefano Ceccherini 	if (!fMenu || !fMenuFrame)
31027cc2508SStefano Ceccherini 		return;
31127cc2508SStefano Ceccherini 
3123616859aSStefano Ceccherini 	fMenu->MakeFocus(true);
31327cc2508SStefano Ceccherini 
3143616859aSStefano Ceccherini 	BRect frame = Bounds();
31560e1cfbfSStefano Ceccherini 
31660e1cfbfSStefano Ceccherini 	if (fUpperScroller == NULL) {
31760e1cfbfSStefano Ceccherini 		fUpperScroller = new UpperScroller(
318c7bb90f8SStephan Aßmus 			BRect(0, 0, frame.right, kScrollerHeight - 1));
3193616859aSStefano Ceccherini 		AddChild(fUpperScroller);
32060e1cfbfSStefano Ceccherini 	}
32160e1cfbfSStefano Ceccherini 
32260e1cfbfSStefano Ceccherini 	if (fLowerScroller == NULL) {
32360e1cfbfSStefano Ceccherini 		fLowerScroller = new LowerScroller(
324c7bb90f8SStephan Aßmus 			BRect(0, frame.bottom - kScrollerHeight + 1, frame.right,
325c7bb90f8SStephan Aßmus 				frame.bottom));
3263616859aSStefano Ceccherini 		AddChild(fLowerScroller);
32760e1cfbfSStefano Ceccherini 	}
3283616859aSStefano Ceccherini 
3293616859aSStefano Ceccherini 	fUpperScroller->SetEnabled(false);
3303616859aSStefano Ceccherini 	fLowerScroller->SetEnabled(true);
33127cc2508SStefano Ceccherini 
332c7bb90f8SStephan Aßmus 	fMenuFrame->ResizeBy(0, -2 * kScrollerHeight);
33327cc2508SStefano Ceccherini 	fMenuFrame->MoveBy(0, kScrollerHeight);
3343616859aSStefano Ceccherini 
3353616859aSStefano Ceccherini 	fValue = 0;
3363616859aSStefano Ceccherini 	fLimit = fMenu->Bounds().Height() - (frame.Height() - 2 * kScrollerHeight);
33727cc2508SStefano Ceccherini }
33827cc2508SStefano Ceccherini 
33927cc2508SStefano Ceccherini 
34027cc2508SStefano Ceccherini void
34127cc2508SStefano Ceccherini BMenuWindow::DetachScrollers()
34227cc2508SStefano Ceccherini {
34327cc2508SStefano Ceccherini 	// BeOS doesn't remember the position where the last scrolling ended,
34427cc2508SStefano Ceccherini 	// so we just scroll back to the beginning.
345059ca4bdSStefano Ceccherini 	if (fMenu)
3463616859aSStefano Ceccherini 		fMenu->ScrollTo(0, 0);
34727cc2508SStefano Ceccherini 
3483616859aSStefano Ceccherini 	if (fLowerScroller) {
3493616859aSStefano Ceccherini 		RemoveChild(fLowerScroller);
3503616859aSStefano Ceccherini 		delete fLowerScroller;
3513616859aSStefano Ceccherini 		fLowerScroller = NULL;
3523616859aSStefano Ceccherini 	}
35327cc2508SStefano Ceccherini 
3543616859aSStefano Ceccherini 	if (fUpperScroller) {
3553616859aSStefano Ceccherini 		RemoveChild(fUpperScroller);
3563616859aSStefano Ceccherini 		delete fUpperScroller;
3573616859aSStefano Ceccherini 		fUpperScroller = NULL;
3583616859aSStefano Ceccherini 	}
35961ba5a32SStefano Ceccherini }
360c7338938SStefano Ceccherini 
361c7338938SStefano Ceccherini 
3624e23bc03SAxel Dörfler void
3634e23bc03SAxel Dörfler BMenuWindow::SetSmallStep(float step)
3644e23bc03SAxel Dörfler {
3654e23bc03SAxel Dörfler 	fScrollStep = step;
3664e23bc03SAxel Dörfler }
3674e23bc03SAxel Dörfler 
3684e23bc03SAxel Dörfler 
3694e23bc03SAxel Dörfler void
3704e23bc03SAxel Dörfler BMenuWindow::GetSteps(float* _smallStep, float* _largeStep)
3714e23bc03SAxel Dörfler {
3724e23bc03SAxel Dörfler 	if (_smallStep != NULL)
3734e23bc03SAxel Dörfler 		*_smallStep = fScrollStep;
3744e23bc03SAxel Dörfler 	if (_largeStep != NULL) {
3754e23bc03SAxel Dörfler 		if (fMenuFrame != NULL)
3764e23bc03SAxel Dörfler 			*_largeStep = fMenuFrame->Bounds().Height() - fScrollStep;
3774e23bc03SAxel Dörfler 		else
3784e23bc03SAxel Dörfler 			*_largeStep = fScrollStep * 2;
3794e23bc03SAxel Dörfler 	}
3804e23bc03SAxel Dörfler }
3814e23bc03SAxel Dörfler 
3824e23bc03SAxel Dörfler 
3834e23bc03SAxel Dörfler bool
3844e23bc03SAxel Dörfler BMenuWindow::HasScrollers() const
3854e23bc03SAxel Dörfler {
3864e23bc03SAxel Dörfler 	return fMenuFrame != NULL && fUpperScroller != NULL
3874e23bc03SAxel Dörfler 		&& fLowerScroller != NULL;
3884e23bc03SAxel Dörfler }
3894e23bc03SAxel Dörfler 
3904e23bc03SAxel Dörfler 
391c7338938SStefano Ceccherini bool
3924e0c2a79SStefano Ceccherini BMenuWindow::CheckForScrolling(const BPoint &cursor)
393c7338938SStefano Ceccherini {
394059ca4bdSStefano Ceccherini 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
395c7338938SStefano Ceccherini 		return false;
396c7338938SStefano Ceccherini 
3973616859aSStefano Ceccherini 	return _Scroll(cursor);
3983616859aSStefano Ceccherini }
3993616859aSStefano Ceccherini 
4003616859aSStefano Ceccherini 
4013616859aSStefano Ceccherini bool
4024e0c2a79SStefano Ceccherini BMenuWindow::TryScrollBy(const float& step)
4034e0c2a79SStefano Ceccherini {
4044e0c2a79SStefano Ceccherini 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
4054e0c2a79SStefano Ceccherini 		return false;
4064e0c2a79SStefano Ceccherini 
4074e0c2a79SStefano Ceccherini 	_ScrollBy(step);
4084e0c2a79SStefano Ceccherini 	return true;
4094e0c2a79SStefano Ceccherini }
4104e0c2a79SStefano Ceccherini 
4114e0c2a79SStefano Ceccherini 
4124e0c2a79SStefano Ceccherini bool
4134e0c2a79SStefano Ceccherini BMenuWindow::_Scroll(const BPoint& where)
4143616859aSStefano Ceccherini {
415059ca4bdSStefano Ceccherini 	ASSERT((fLowerScroller != NULL));
416059ca4bdSStefano Ceccherini 	ASSERT((fUpperScroller != NULL));
417059ca4bdSStefano Ceccherini 
4184e0c2a79SStefano Ceccherini 	const BPoint cursor = ConvertFromScreen(where);
4193616859aSStefano Ceccherini 
420059ca4bdSStefano Ceccherini 	BRect lowerFrame = fLowerScroller->Frame();
421059ca4bdSStefano Ceccherini 	BRect upperFrame = fUpperScroller->Frame();
4223616859aSStefano Ceccherini 
4234e23bc03SAxel Dörfler 	if (fLowerScroller->IsEnabled() && lowerFrame.Contains(cursor))
4244e0c2a79SStefano Ceccherini 		_ScrollBy(1);
4254e23bc03SAxel Dörfler 	else if (fUpperScroller->IsEnabled() && upperFrame.Contains(cursor))
4264e0c2a79SStefano Ceccherini 		_ScrollBy(-1);
4274e23bc03SAxel Dörfler 	else
4284e0c2a79SStefano Ceccherini 		return false;
4294e0c2a79SStefano Ceccherini 
4302f86ba45SStephan Aßmus 	snooze(5000);
4314e0c2a79SStefano Ceccherini 
4324e0c2a79SStefano Ceccherini 	return true;
4334e0c2a79SStefano Ceccherini }
4344e0c2a79SStefano Ceccherini 
4354e0c2a79SStefano Ceccherini 
4364e0c2a79SStefano Ceccherini void
4374e0c2a79SStefano Ceccherini BMenuWindow::_ScrollBy(const float& step)
4384e0c2a79SStefano Ceccherini {
4394e0c2a79SStefano Ceccherini 	if (step > 0) {
4403616859aSStefano Ceccherini 		if (fValue == 0) {
4413616859aSStefano Ceccherini 			fUpperScroller->SetEnabled(true);
4423616859aSStefano Ceccherini 			fUpperScroller->Invalidate();
4433616859aSStefano Ceccherini 		}
4443616859aSStefano Ceccherini 
4454e23bc03SAxel Dörfler 		if (fValue + step >= fLimit) {
4464e23bc03SAxel Dörfler 			// If we reached the limit, only scroll to the end
4473616859aSStefano Ceccherini 			fMenu->ScrollBy(0, fLimit - fValue);
4483616859aSStefano Ceccherini 			fValue = fLimit;
4493616859aSStefano Ceccherini 			fLowerScroller->SetEnabled(false);
4503616859aSStefano Ceccherini 			fLowerScroller->Invalidate();
4513616859aSStefano Ceccherini 		} else {
4524e23bc03SAxel Dörfler 			fMenu->ScrollBy(0, step);
4534e23bc03SAxel Dörfler 			fValue += step;
4543616859aSStefano Ceccherini 		}
4554e0c2a79SStefano Ceccherini 	} else if (step < 0) {
4563616859aSStefano Ceccherini 		if (fValue == fLimit) {
4573616859aSStefano Ceccherini 			fLowerScroller->SetEnabled(true);
4583616859aSStefano Ceccherini 			fLowerScroller->Invalidate();
4593616859aSStefano Ceccherini 		}
4603616859aSStefano Ceccherini 
4614e23bc03SAxel Dörfler 		if (fValue + step <= 0) {
4623616859aSStefano Ceccherini 			fMenu->ScrollBy(0, -fValue);
4633616859aSStefano Ceccherini 			fValue = 0;
4643616859aSStefano Ceccherini 			fUpperScroller->SetEnabled(false);
4653616859aSStefano Ceccherini 			fUpperScroller->Invalidate();
4663616859aSStefano Ceccherini 		} else {
4674e23bc03SAxel Dörfler 			fMenu->ScrollBy(0, step);
4684e23bc03SAxel Dörfler 			fValue += step;
4693616859aSStefano Ceccherini 		}
4704e0c2a79SStefano Ceccherini 	}
471c7338938SStefano Ceccherini }
472c7338938SStefano Ceccherini 
473