xref: /haiku/src/kits/interface/MenuWindow.cpp (revision 9b33a309dab39f04474bc441d8d35e7f402b40ca)
1c7023acdSAxel Dörfler /*
27a96554cSlooncraz  * Copyright 2001-2015, 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;
3050f8cd14SAxel Dörfler 			void			SetEnabled(bool enabled);
3150f8cd14SAxel 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);
5550f8cd14SAxel 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);
6350f8cd14SAxel 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 
743ecf187eSStefano Ceccherini const int kScrollerHeight = 12;
755b752875SStefano Ceccherini 
762628e60cSAxel Dörfler 
BMenuScroller(BRect frame)773616859aSStefano Ceccherini BMenuScroller::BMenuScroller(BRect frame)
7850f8cd14SAxel Dörfler 	:
79*9b33a309SX512 	BView(frame, "menu scroller", 0, B_WILL_DRAW | B_FRAME_EVENTS
80*9b33a309SX512 		| B_FULL_UPDATE_ON_RESIZE),
813616859aSStefano Ceccherini 	fEnabled(false)
8227cc2508SStefano Ceccherini {
837a96554cSlooncraz 	SetViewUIColor(B_MENU_BACKGROUND_COLOR);
8427cc2508SStefano Ceccherini }
8527cc2508SStefano Ceccherini 
8627cc2508SStefano Ceccherini 
87c7338938SStefano Ceccherini bool
IsEnabled() const883616859aSStefano Ceccherini BMenuScroller::IsEnabled() const
8927cc2508SStefano Ceccherini {
903616859aSStefano Ceccherini 	return fEnabled;
9127cc2508SStefano Ceccherini }
9227cc2508SStefano Ceccherini 
9327cc2508SStefano Ceccherini 
9427cc2508SStefano Ceccherini void
SetEnabled(bool enabled)9550f8cd14SAxel Dörfler BMenuScroller::SetEnabled(bool enabled)
963616859aSStefano Ceccherini {
973616859aSStefano Ceccherini 	fEnabled = enabled;
983616859aSStefano Ceccherini }
993616859aSStefano Ceccherini 
1003616859aSStefano Ceccherini 
1013616859aSStefano Ceccherini //	#pragma mark -
1023616859aSStefano Ceccherini 
1033616859aSStefano Ceccherini 
UpperScroller(BRect frame)1043616859aSStefano Ceccherini UpperScroller::UpperScroller(BRect frame)
1053616859aSStefano Ceccherini 	:
1063616859aSStefano Ceccherini 	BMenuScroller(frame)
1073616859aSStefano Ceccherini {
1083616859aSStefano Ceccherini }
1093616859aSStefano Ceccherini 
1103616859aSStefano Ceccherini 
1113616859aSStefano Ceccherini void
Draw(BRect updateRect)1123616859aSStefano Ceccherini UpperScroller::Draw(BRect updateRect)
11327cc2508SStefano Ceccherini {
11427cc2508SStefano Ceccherini 	SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
11527cc2508SStefano Ceccherini 	float middle = Bounds().right / 2;
11627cc2508SStefano Ceccherini 
11727cc2508SStefano Ceccherini 	// Draw the upper arrow.
1183616859aSStefano Ceccherini 	if (IsEnabled())
11927cc2508SStefano Ceccherini 		SetHighColor(0, 0, 0);
12050f8cd14SAxel Dörfler 	else {
12127cc2508SStefano Ceccherini 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
12227cc2508SStefano Ceccherini 			B_DARKEN_2_TINT));
12350f8cd14SAxel Dörfler 	}
12427cc2508SStefano Ceccherini 
1253616859aSStefano Ceccherini 	FillRect(Bounds(), B_SOLID_LOW);
12627cc2508SStefano Ceccherini 
12727cc2508SStefano Ceccherini 	FillTriangle(BPoint(middle, (kScrollerHeight / 2) - 3),
12827cc2508SStefano Ceccherini 		BPoint(middle + 5, (kScrollerHeight / 2) + 2),
12927cc2508SStefano Ceccherini 		BPoint(middle - 5, (kScrollerHeight / 2) + 2));
13027cc2508SStefano Ceccherini }
13127cc2508SStefano Ceccherini 
1323616859aSStefano Ceccherini 
1333616859aSStefano Ceccherini //	#pragma mark -
1343616859aSStefano Ceccherini 
1353616859aSStefano Ceccherini 
LowerScroller(BRect frame)1363616859aSStefano Ceccherini LowerScroller::LowerScroller(BRect frame)
1373616859aSStefano Ceccherini 	:
1383616859aSStefano Ceccherini 	BMenuScroller(frame)
1393616859aSStefano Ceccherini {
1403616859aSStefano Ceccherini }
1413616859aSStefano Ceccherini 
1423616859aSStefano Ceccherini 
1433616859aSStefano Ceccherini void
Draw(BRect updateRect)1443616859aSStefano Ceccherini LowerScroller::Draw(BRect updateRect)
1453616859aSStefano Ceccherini {
1463616859aSStefano Ceccherini 	SetLowColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR), B_DARKEN_1_TINT));
1473616859aSStefano Ceccherini 
1483616859aSStefano Ceccherini 	BRect frame = Bounds();
14927cc2508SStefano Ceccherini 	// Draw the lower arrow.
1503616859aSStefano Ceccherini 	if (IsEnabled())
15127cc2508SStefano Ceccherini 		SetHighColor(0, 0, 0);
15250f8cd14SAxel Dörfler 	else {
15327cc2508SStefano Ceccherini 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
15427cc2508SStefano Ceccherini 			B_DARKEN_2_TINT));
15550f8cd14SAxel Dörfler 	}
15627cc2508SStefano Ceccherini 
157059ca4bdSStefano Ceccherini 	FillRect(frame, B_SOLID_LOW);
15827cc2508SStefano Ceccherini 
1593616859aSStefano Ceccherini 	float middle = Bounds().right / 2;
1603616859aSStefano Ceccherini 
1613616859aSStefano Ceccherini 	FillTriangle(BPoint(middle, frame.bottom - (kScrollerHeight / 2) + 3),
1623616859aSStefano Ceccherini 		BPoint(middle + 5, frame.bottom - (kScrollerHeight / 2) - 2),
1633616859aSStefano Ceccherini 		BPoint(middle - 5, frame.bottom - (kScrollerHeight / 2) - 2));
16427cc2508SStefano Ceccherini }
16527cc2508SStefano Ceccherini 
16627cc2508SStefano Ceccherini 
16727cc2508SStefano Ceccherini //	#pragma mark -
1685b752875SStefano Ceccherini 
1695b752875SStefano Ceccherini 
BMenuFrame(BMenu * menu)1702628e60cSAxel Dörfler BMenuFrame::BMenuFrame(BMenu *menu)
17150f8cd14SAxel Dörfler 	:
17250f8cd14SAxel Dörfler 	BView(BRect(0, 0, 1, 1), "menu frame", B_FOLLOW_ALL_SIDES, B_WILL_DRAW),
1732628e60cSAxel Dörfler 	fMenu(menu)
1742628e60cSAxel Dörfler {
1752628e60cSAxel Dörfler }
1762628e60cSAxel Dörfler 
1772628e60cSAxel Dörfler 
1782628e60cSAxel Dörfler void
AttachedToWindow()1792628e60cSAxel Dörfler BMenuFrame::AttachedToWindow()
1802628e60cSAxel Dörfler {
1812628e60cSAxel Dörfler 	BView::AttachedToWindow();
1822628e60cSAxel Dörfler 
1832628e60cSAxel Dörfler 	if (fMenu != NULL)
1842628e60cSAxel Dörfler 		AddChild(fMenu);
1852628e60cSAxel Dörfler 
1862628e60cSAxel Dörfler 	ResizeTo(Window()->Bounds().Width(), Window()->Bounds().Height());
1872628e60cSAxel Dörfler 	if (fMenu != NULL) {
1882628e60cSAxel Dörfler 		BFont font;
1892628e60cSAxel Dörfler 		fMenu->GetFont(&font);
1902628e60cSAxel Dörfler 		SetFont(&font);
1912628e60cSAxel Dörfler 	}
1922628e60cSAxel Dörfler }
1932628e60cSAxel Dörfler 
1942628e60cSAxel Dörfler 
1952628e60cSAxel Dörfler void
DetachedFromWindow()1962628e60cSAxel Dörfler BMenuFrame::DetachedFromWindow()
1972628e60cSAxel Dörfler {
1982628e60cSAxel Dörfler 	if (fMenu != NULL)
1992628e60cSAxel Dörfler 		RemoveChild(fMenu);
2002628e60cSAxel Dörfler }
2012628e60cSAxel Dörfler 
2022628e60cSAxel Dörfler 
2032628e60cSAxel Dörfler void
Draw(BRect updateRect)2042628e60cSAxel Dörfler BMenuFrame::Draw(BRect updateRect)
2052628e60cSAxel Dörfler {
2062628e60cSAxel Dörfler 	if (fMenu != NULL && fMenu->CountItems() == 0) {
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);
2112628e60cSAxel Dörfler 
212f2de125bSStefano Ceccherini 		// TODO: Review this as it's a bit hacky.
213f2de125bSStefano Ceccherini 		// Since there are no items in this menu, its size is 0x0.
214f2de125bSStefano Ceccherini 		// To show an empty BMenu, we use BMenuFrame to draw an empty item.
215f2de125bSStefano Ceccherini 		// It would be nice to simply add a real "empty" item, but in that case
216f2de125bSStefano Ceccherini 		// we couldn't tell if the item was added by us or not, and applications
217f2de125bSStefano Ceccherini 		// could break (because CountItems() would return 1 for an empty BMenu).
218f2de125bSStefano Ceccherini 		// See also BMenu::UpdateWindowViewSize()
2192628e60cSAxel Dörfler 		font_height height;
2202628e60cSAxel Dörfler 		GetFontHeight(&height);
22150f8cd14SAxel Dörfler 		SetHighColor(tint_color(ui_color(B_MENU_BACKGROUND_COLOR),
22250f8cd14SAxel Dörfler 			B_DISABLED_LABEL_TINT));
22350f8cd14SAxel Dörfler 		BPoint where(
22450f8cd14SAxel Dörfler 			(Bounds().Width() - fMenu->StringWidth(kEmptyMenuLabel)) / 2,
22550f8cd14SAxel Dörfler 			ceilf(height.ascent + 1));
2262628e60cSAxel Dörfler 		DrawString(kEmptyMenuLabel, where);
2272628e60cSAxel Dörfler 	}
2282628e60cSAxel Dörfler }
2292628e60cSAxel Dörfler 
2302628e60cSAxel Dörfler 
2313616859aSStefano Ceccherini 
2322628e60cSAxel Dörfler //	#pragma mark -
2332628e60cSAxel Dörfler 
2342628e60cSAxel Dörfler 
BMenuWindow(const char * name)2354185bd8bSStefano Ceccherini BMenuWindow::BMenuWindow(const char *name)
2361664b981SStefano Ceccherini 	// The window will be resized by BMenu, so just pass a dummy rect
237a937ffd2Sczeidler 	:
238a937ffd2Sczeidler 	BWindow(BRect(0, 0, 0, 0), name, B_BORDERED_WINDOW_LOOK, kMenuWindowFeel,
239a937ffd2Sczeidler 		B_NOT_MOVABLE | B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_AVOID_FOCUS
240931cd377SAxel Dörfler 			| kAcceptKeyboardFocusFlag),
2413616859aSStefano Ceccherini 	fMenu(NULL),
2423616859aSStefano Ceccherini 	fMenuFrame(NULL),
2433616859aSStefano Ceccherini 	fUpperScroller(NULL),
2444e23bc03SAxel Dörfler 	fLowerScroller(NULL),
2454e23bc03SAxel Dörfler 	fScrollStep(19)
246446b8c19SStefano Ceccherini {
2472f86ba45SStephan Aßmus 	SetSizeLimits(2, 10000, 2, 10000);
248446b8c19SStefano Ceccherini }
249446b8c19SStefano Ceccherini 
250446b8c19SStefano Ceccherini 
~BMenuWindow()251446b8c19SStefano Ceccherini BMenuWindow::~BMenuWindow()
252446b8c19SStefano Ceccherini {
253059ca4bdSStefano Ceccherini 	DetachMenu();
254446b8c19SStefano Ceccherini }
2555aa032f1SStefano Ceccherini 
2565aa032f1SStefano Ceccherini 
25761ba5a32SStefano Ceccherini void
DispatchMessage(BMessage * message,BHandler * handler)2589e64a7edSStefano Ceccherini BMenuWindow::DispatchMessage(BMessage *message, BHandler *handler)
2599e64a7edSStefano Ceccherini {
2609e64a7edSStefano Ceccherini 	BWindow::DispatchMessage(message, handler);
2619e64a7edSStefano Ceccherini }
2629e64a7edSStefano Ceccherini 
2639e64a7edSStefano Ceccherini 
2649e64a7edSStefano Ceccherini void
AttachMenu(BMenu * menu)2654185bd8bSStefano Ceccherini BMenuWindow::AttachMenu(BMenu *menu)
2664185bd8bSStefano Ceccherini {
26727cc2508SStefano Ceccherini 	if (fMenuFrame)
26827cc2508SStefano Ceccherini 		debugger("BMenuWindow: a menu is already attached!");
2694185bd8bSStefano Ceccherini 	if (menu != NULL) {
27027cc2508SStefano Ceccherini 		fMenuFrame = new BMenuFrame(menu);
27127cc2508SStefano Ceccherini 		AddChild(fMenuFrame);
27207dc2c69SAxel Dörfler 		menu->MakeFocus(true);
2733616859aSStefano Ceccherini 		fMenu = menu;
2744185bd8bSStefano Ceccherini 	}
2754185bd8bSStefano Ceccherini }
2764185bd8bSStefano Ceccherini 
2774185bd8bSStefano Ceccherini 
2784185bd8bSStefano Ceccherini void
DetachMenu()2794185bd8bSStefano Ceccherini BMenuWindow::DetachMenu()
28061ba5a32SStefano Ceccherini {
28127cc2508SStefano Ceccherini 	DetachScrollers();
2823616859aSStefano Ceccherini 	if (fMenuFrame) {
28327cc2508SStefano Ceccherini 		RemoveChild(fMenuFrame);
28427cc2508SStefano Ceccherini 		delete fMenuFrame;
28527cc2508SStefano Ceccherini 		fMenuFrame = NULL;
2863616859aSStefano Ceccherini 		fMenu = NULL;
28727cc2508SStefano Ceccherini 	}
28827cc2508SStefano Ceccherini }
28927cc2508SStefano Ceccherini 
29027cc2508SStefano Ceccherini 
29127cc2508SStefano Ceccherini void
AttachScrollers()29227cc2508SStefano Ceccherini BMenuWindow::AttachScrollers()
29327cc2508SStefano Ceccherini {
29460e1cfbfSStefano Ceccherini 	// We want to attach a scroller only if there's a
29560e1cfbfSStefano Ceccherini 	// menu frame already existing.
2963616859aSStefano Ceccherini 	if (!fMenu || !fMenuFrame)
29727cc2508SStefano Ceccherini 		return;
29827cc2508SStefano Ceccherini 
2993616859aSStefano Ceccherini 	fMenu->MakeFocus(true);
30027cc2508SStefano Ceccherini 
3013616859aSStefano Ceccherini 	BRect frame = Bounds();
302*9b33a309SX512 	float newLimit = fMenu->Bounds().Height()
303*9b33a309SX512 		- (frame.Height() - 2 * kScrollerHeight);
304*9b33a309SX512 
305*9b33a309SX512 	if (!HasScrollers())
306*9b33a309SX512 		fValue = 0;
307*9b33a309SX512 	else if (fValue > newLimit)
308*9b33a309SX512 		_ScrollBy(newLimit - fValue);
309*9b33a309SX512 
310*9b33a309SX512 	fLimit = newLimit;
31160e1cfbfSStefano Ceccherini 
31260e1cfbfSStefano Ceccherini 	if (fUpperScroller == NULL) {
31360e1cfbfSStefano Ceccherini 		fUpperScroller = new UpperScroller(
314c7bb90f8SStephan Aßmus 			BRect(0, 0, frame.right, kScrollerHeight - 1));
3153616859aSStefano Ceccherini 		AddChild(fUpperScroller);
31660e1cfbfSStefano Ceccherini 	}
31760e1cfbfSStefano Ceccherini 
31860e1cfbfSStefano Ceccherini 	if (fLowerScroller == NULL) {
31960e1cfbfSStefano Ceccherini 		fLowerScroller = new LowerScroller(
320c7bb90f8SStephan Aßmus 			BRect(0, frame.bottom - kScrollerHeight + 1, frame.right,
321c7bb90f8SStephan Aßmus 				frame.bottom));
3223616859aSStefano Ceccherini 		AddChild(fLowerScroller);
32360e1cfbfSStefano Ceccherini 	}
3243616859aSStefano Ceccherini 
325*9b33a309SX512 	fUpperScroller->ResizeTo(frame.right, kScrollerHeight - 1);
326*9b33a309SX512 	fLowerScroller->ResizeTo(frame.right, kScrollerHeight - 1);
32727cc2508SStefano Ceccherini 
328*9b33a309SX512 	fUpperScroller->SetEnabled(fValue > 0);
329*9b33a309SX512 	fLowerScroller->SetEnabled(fValue < fLimit);
3303616859aSStefano Ceccherini 
331*9b33a309SX512 	fMenuFrame->ResizeTo(frame.Width(), frame.Height() - 2 * kScrollerHeight);
332*9b33a309SX512 	fMenuFrame->MoveTo(0, kScrollerHeight);
33327cc2508SStefano Ceccherini }
33427cc2508SStefano Ceccherini 
33527cc2508SStefano Ceccherini 
33627cc2508SStefano Ceccherini void
DetachScrollers()33727cc2508SStefano Ceccherini BMenuWindow::DetachScrollers()
33827cc2508SStefano Ceccherini {
33927cc2508SStefano Ceccherini 	// BeOS doesn't remember the position where the last scrolling ended,
34027cc2508SStefano Ceccherini 	// so we just scroll back to the beginning.
341059ca4bdSStefano Ceccherini 	if (fMenu)
3423616859aSStefano Ceccherini 		fMenu->ScrollTo(0, 0);
34327cc2508SStefano Ceccherini 
3443616859aSStefano Ceccherini 	if (fLowerScroller) {
3453616859aSStefano Ceccherini 		RemoveChild(fLowerScroller);
3463616859aSStefano Ceccherini 		delete fLowerScroller;
3473616859aSStefano Ceccherini 		fLowerScroller = NULL;
3483616859aSStefano Ceccherini 	}
34927cc2508SStefano Ceccherini 
3503616859aSStefano Ceccherini 	if (fUpperScroller) {
3513616859aSStefano Ceccherini 		RemoveChild(fUpperScroller);
3523616859aSStefano Ceccherini 		delete fUpperScroller;
3533616859aSStefano Ceccherini 		fUpperScroller = NULL;
3543616859aSStefano Ceccherini 	}
355*9b33a309SX512 
356*9b33a309SX512 	BRect frame = Bounds();
357*9b33a309SX512 
358*9b33a309SX512 	if (fMenuFrame != NULL) {
359*9b33a309SX512 		fMenuFrame->ResizeTo(frame.Width(), frame.Height());
360*9b33a309SX512 		fMenuFrame->MoveTo(0, 0);
361*9b33a309SX512 	}
36261ba5a32SStefano Ceccherini }
363c7338938SStefano Ceccherini 
364c7338938SStefano Ceccherini 
3654e23bc03SAxel Dörfler void
SetSmallStep(float step)3664e23bc03SAxel Dörfler BMenuWindow::SetSmallStep(float step)
3674e23bc03SAxel Dörfler {
3684e23bc03SAxel Dörfler 	fScrollStep = step;
3694e23bc03SAxel Dörfler }
3704e23bc03SAxel Dörfler 
3714e23bc03SAxel Dörfler 
3724e23bc03SAxel Dörfler void
GetSteps(float * _smallStep,float * _largeStep) const3733ecf187eSStefano Ceccherini BMenuWindow::GetSteps(float* _smallStep, float* _largeStep) const
3744e23bc03SAxel Dörfler {
3754e23bc03SAxel Dörfler 	if (_smallStep != NULL)
3764e23bc03SAxel Dörfler 		*_smallStep = fScrollStep;
3774e23bc03SAxel Dörfler 	if (_largeStep != NULL) {
3784e23bc03SAxel Dörfler 		if (fMenuFrame != NULL)
3794e23bc03SAxel Dörfler 			*_largeStep = fMenuFrame->Bounds().Height() - fScrollStep;
3804e23bc03SAxel Dörfler 		else
3814e23bc03SAxel Dörfler 			*_largeStep = fScrollStep * 2;
3824e23bc03SAxel Dörfler 	}
3834e23bc03SAxel Dörfler }
3844e23bc03SAxel Dörfler 
3854e23bc03SAxel Dörfler 
3864e23bc03SAxel Dörfler bool
HasScrollers() const3874e23bc03SAxel Dörfler BMenuWindow::HasScrollers() const
3884e23bc03SAxel Dörfler {
3894e23bc03SAxel Dörfler 	return fMenuFrame != NULL && fUpperScroller != NULL
3904e23bc03SAxel Dörfler 		&& fLowerScroller != NULL;
3914e23bc03SAxel Dörfler }
3924e23bc03SAxel Dörfler 
3934e23bc03SAxel Dörfler 
394c7338938SStefano Ceccherini bool
CheckForScrolling(const BPoint & cursor)3954e0c2a79SStefano Ceccherini BMenuWindow::CheckForScrolling(const BPoint &cursor)
396c7338938SStefano Ceccherini {
397059ca4bdSStefano Ceccherini 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
398c7338938SStefano Ceccherini 		return false;
399c7338938SStefano Ceccherini 
4003616859aSStefano Ceccherini 	return _Scroll(cursor);
4013616859aSStefano Ceccherini }
4023616859aSStefano Ceccherini 
4033616859aSStefano Ceccherini 
4043616859aSStefano Ceccherini bool
TryScrollBy(const float & step)4054e0c2a79SStefano Ceccherini BMenuWindow::TryScrollBy(const float& step)
4064e0c2a79SStefano Ceccherini {
4074e0c2a79SStefano Ceccherini 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
4084e0c2a79SStefano Ceccherini 		return false;
4094e0c2a79SStefano Ceccherini 
4104e0c2a79SStefano Ceccherini 	_ScrollBy(step);
4114e0c2a79SStefano Ceccherini 	return true;
4124e0c2a79SStefano Ceccherini }
4134e0c2a79SStefano Ceccherini 
4144e0c2a79SStefano Ceccherini 
4154e0c2a79SStefano Ceccherini bool
TryScrollTo(const float & where)4164898c615SJessica Hamilton BMenuWindow::TryScrollTo(const float& where)
4174898c615SJessica Hamilton {
4184898c615SJessica Hamilton 	if (!fMenuFrame || !fUpperScroller || !fLowerScroller)
4194898c615SJessica Hamilton 		return false;
4204898c615SJessica Hamilton 
4214898c615SJessica Hamilton 	_ScrollBy(where - fValue);
4224898c615SJessica Hamilton 	return true;
4234898c615SJessica Hamilton }
4244898c615SJessica Hamilton 
4254898c615SJessica Hamilton 
4264898c615SJessica Hamilton bool
_Scroll(const BPoint & where)4274e0c2a79SStefano Ceccherini BMenuWindow::_Scroll(const BPoint& where)
4283616859aSStefano Ceccherini {
429059ca4bdSStefano Ceccherini 	ASSERT((fLowerScroller != NULL));
430059ca4bdSStefano Ceccherini 	ASSERT((fUpperScroller != NULL));
431059ca4bdSStefano Ceccherini 
4324e0c2a79SStefano Ceccherini 	const BPoint cursor = ConvertFromScreen(where);
43396f041c5SStefano Ceccherini 	const BRect &lowerFrame = fLowerScroller->Frame();
43496f041c5SStefano Ceccherini 	const BRect &upperFrame = fUpperScroller->Frame();
4353616859aSStefano Ceccherini 
43696f041c5SStefano Ceccherini 	int32 delta = 0;
4374e23bc03SAxel Dörfler 	if (fLowerScroller->IsEnabled() && lowerFrame.Contains(cursor))
43896f041c5SStefano Ceccherini 		delta = 1;
4394e23bc03SAxel Dörfler 	else if (fUpperScroller->IsEnabled() && upperFrame.Contains(cursor))
44096f041c5SStefano Ceccherini 		delta = -1;
44196f041c5SStefano Ceccherini 
44296f041c5SStefano Ceccherini 	if (delta == 0)
4434e0c2a79SStefano Ceccherini 		return false;
4444e0c2a79SStefano Ceccherini 
44596f041c5SStefano Ceccherini 	float smallStep;
44696f041c5SStefano Ceccherini 	GetSteps(&smallStep, NULL);
44796f041c5SStefano Ceccherini 	_ScrollBy(smallStep * delta);
44896f041c5SStefano Ceccherini 
4492f86ba45SStephan Aßmus 	snooze(5000);
4504e0c2a79SStefano Ceccherini 
4514e0c2a79SStefano Ceccherini 	return true;
4524e0c2a79SStefano Ceccherini }
4534e0c2a79SStefano Ceccherini 
4544e0c2a79SStefano Ceccherini 
4554e0c2a79SStefano Ceccherini void
_ScrollBy(const float & step)4564e0c2a79SStefano Ceccherini BMenuWindow::_ScrollBy(const float& step)
4574e0c2a79SStefano Ceccherini {
4584e0c2a79SStefano Ceccherini 	if (step > 0) {
4593616859aSStefano Ceccherini 		if (fValue == 0) {
4603616859aSStefano Ceccherini 			fUpperScroller->SetEnabled(true);
4613616859aSStefano Ceccherini 			fUpperScroller->Invalidate();
4623616859aSStefano Ceccherini 		}
4633616859aSStefano Ceccherini 
4644e23bc03SAxel Dörfler 		if (fValue + step >= fLimit) {
4654e23bc03SAxel Dörfler 			// If we reached the limit, only scroll to the end
4663616859aSStefano Ceccherini 			fMenu->ScrollBy(0, fLimit - fValue);
4673616859aSStefano Ceccherini 			fValue = fLimit;
4683616859aSStefano Ceccherini 			fLowerScroller->SetEnabled(false);
4693616859aSStefano Ceccherini 			fLowerScroller->Invalidate();
4703616859aSStefano Ceccherini 		} else {
4714e23bc03SAxel Dörfler 			fMenu->ScrollBy(0, step);
4724e23bc03SAxel Dörfler 			fValue += step;
4733616859aSStefano Ceccherini 		}
4744e0c2a79SStefano Ceccherini 	} else if (step < 0) {
4753616859aSStefano Ceccherini 		if (fValue == fLimit) {
4763616859aSStefano Ceccherini 			fLowerScroller->SetEnabled(true);
4773616859aSStefano Ceccherini 			fLowerScroller->Invalidate();
4783616859aSStefano Ceccherini 		}
4793616859aSStefano Ceccherini 
4804e23bc03SAxel Dörfler 		if (fValue + step <= 0) {
4813616859aSStefano Ceccherini 			fMenu->ScrollBy(0, -fValue);
4823616859aSStefano Ceccherini 			fValue = 0;
4833616859aSStefano Ceccherini 			fUpperScroller->SetEnabled(false);
4843616859aSStefano Ceccherini 			fUpperScroller->Invalidate();
4853616859aSStefano Ceccherini 		} else {
4864e23bc03SAxel Dörfler 			fMenu->ScrollBy(0, step);
4874e23bc03SAxel Dörfler 			fValue += step;
4883616859aSStefano Ceccherini 		}
4894e0c2a79SStefano Ceccherini 	}
490c7338938SStefano Ceccherini }
491c7338938SStefano Ceccherini 
492