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