diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index 3c269f7bf5..de92318344 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -1,6 +1,6 @@ /* - * Copyright 2007, Haiku, Inc. All Rights Reserved. - * Distributed under the terms of the MIT License. + * Copyright 2007-2009, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT license. */ #ifndef _MENU_H #define _MENU_H @@ -46,106 +46,113 @@ typedef bool (*menu_tracking_hook)(BMenu* menu, void* state); class BMenu : public BView { public: - BMenu(const char* title, - menu_layout layout = B_ITEMS_IN_COLUMN); - BMenu(const char* title, float width, float height); - virtual ~BMenu(); + BMenu(const char* title, + menu_layout layout = B_ITEMS_IN_COLUMN); + BMenu(const char* title, float width, + float height); + BMenu(BMessage* archive); - BMenu(BMessage* archive); - static BArchivable* Instantiate(BMessage* archive); - virtual status_t Archive(BMessage* archive, bool deep = true) const; + virtual ~BMenu(); - virtual void AttachedToWindow(); - virtual void DetachedFromWindow(); + static BArchivable* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* archive, + bool deep = true) const; - bool AddItem(BMenuItem* item); - bool AddItem(BMenuItem* item, int32 index); - bool AddItem(BMenuItem* item, BRect frame); - bool AddItem(BMenu* menu); - bool AddItem(BMenu* menu, int32 index); - bool AddItem(BMenu* menu, BRect frame); - bool AddList(BList* list, int32 index); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); + virtual void AllAttached(); + virtual void AllDetached(); - bool AddSeparatorItem(); + virtual void Draw(BRect updateRect); - bool RemoveItem(BMenuItem* item); - BMenuItem* RemoveItem(int32 index); - bool RemoveItems(int32 index, int32 count, - bool deleteItems = false); - bool RemoveItem(BMenu* menu); + virtual void MessageReceived(BMessage* message); + virtual void KeyDown(const char* bytes, int32 numBytes); - BMenuItem* ItemAt(int32 index) const; - BMenu* SubmenuAt(int32 index) const; - int32 CountItems() const; - int32 IndexOf(BMenuItem* item) const; - int32 IndexOf(BMenu* menu) const; - BMenuItem* FindItem(uint32 command) const; - BMenuItem* FindItem(const char* name) const; + virtual BSize MinSize(); + virtual BSize MaxSize(); + virtual BSize PreferredSize(); + virtual void GetPreferredSize(float* _width, + float* _height); + virtual void ResizeToPreferred(); + virtual void DoLayout(); + virtual void FrameMoved(BPoint newPosition); + virtual void FrameResized(float newWidth, float newHeight); + void InvalidateLayout(); + virtual void InvalidateLayout(bool descendants); - virtual status_t SetTargetForItems(BHandler* target); - virtual status_t SetTargetForItems(BMessenger messenger); - virtual void SetEnabled(bool state); - virtual void SetRadioMode(bool state); - virtual void SetTriggersEnabled(bool state); - virtual void SetMaxContentWidth(float maxWidth); + virtual void MakeFocus(bool focus = true); - void SetLabelFromMarked(bool state); - bool IsLabelFromMarked(); - bool IsEnabled() const; - bool IsRadioMode() const; - bool AreTriggersEnabled() const; - bool IsRedrawAfterSticky() const; - float MaxContentWidth() const; + bool AddItem(BMenuItem* item); + bool AddItem(BMenuItem* item, int32 index); + bool AddItem(BMenuItem* item, BRect frame); + bool AddItem(BMenu* menu); + bool AddItem(BMenu* menu, int32 index); + bool AddItem(BMenu* menu, BRect frame); + bool AddList(BList* list, int32 index); - BMenuItem* FindMarked(); + bool AddSeparatorItem(); - BMenu* Supermenu() const; - BMenuItem* Superitem() const; + bool RemoveItem(BMenuItem* item); + BMenuItem* RemoveItem(int32 index); + bool RemoveItems(int32 index, int32 count, + bool deleteItems = false); + bool RemoveItem(BMenu* menu); - virtual void MessageReceived(BMessage* message); - virtual void KeyDown(const char* bytes, int32 numBytes); - virtual void Draw(BRect updateRect); - virtual BSize MinSize(); - virtual BSize MaxSize(); - virtual BSize PreferredSize(); - virtual void GetPreferredSize(float* _width, float* _height); - virtual void ResizeToPreferred(); - virtual void DoLayout(); - virtual void FrameMoved(BPoint newPosition); - virtual void FrameResized(float newWidth, float newHeight); - void InvalidateLayout(); - virtual void InvalidateLayout(bool descendants); + BMenuItem* ItemAt(int32 index) const; + BMenu* SubmenuAt(int32 index) const; + int32 CountItems() const; + int32 IndexOf(BMenuItem* item) const; + int32 IndexOf(BMenu* menu) const; + BMenuItem* FindItem(uint32 command) const; + BMenuItem* FindItem(const char* name) const; - virtual BHandler* ResolveSpecifier(BMessage* message, int32 index, - BMessage* specifier, int32 form, - const char* property); - virtual status_t GetSupportedSuites(BMessage* data); + virtual status_t SetTargetForItems(BHandler* target); + virtual status_t SetTargetForItems(BMessenger messenger); + virtual void SetEnabled(bool state); + virtual void SetRadioMode(bool state); + virtual void SetTriggersEnabled(bool state); + virtual void SetMaxContentWidth(float maxWidth); - virtual status_t Perform(perform_code d, void* arg); + void SetLabelFromMarked(bool state); + bool IsLabelFromMarked(); + bool IsEnabled() const; + bool IsRadioMode() const; + bool AreTriggersEnabled() const; + bool IsRedrawAfterSticky() const; + float MaxContentWidth() const; - virtual void MakeFocus(bool focus = true); - virtual void AllAttached(); - virtual void AllDetached(); + BMenuItem* FindMarked(); + + BMenu* Supermenu() const; + BMenuItem* Superitem() const; + + + virtual BHandler* ResolveSpecifier(BMessage* message, + int32 index, BMessage* specifier, + int32 form, const char* property); + virtual status_t GetSupportedSuites(BMessage* data); + + virtual status_t Perform(perform_code d, void* arg); protected: - BMenu(BRect frame, const char* name, - uint32 resizeMask, uint32 flags, - menu_layout layout, bool resizeToFit); + BMenu(BRect frame, const char* name, + uint32 resizeMask, uint32 flags, + menu_layout layout, bool resizeToFit); - virtual BPoint ScreenLocation(); + virtual BPoint ScreenLocation(); - void SetItemMargins(float left, float top, float right, - float bottom); - void GetItemMargins(float* left, float* top, - float* right, float* bottom) const; + void SetItemMargins(float left, float top, + float right, float bottom); + void GetItemMargins(float* _left, float* _top, + float* _right, float* _bottom) const; - menu_layout Layout() const; + menu_layout Layout() const; - virtual void Show(); - void Show(bool selectFirstItem); - void Hide(); - BMenuItem* Track(bool startOpened = false, - BRect* specialRect = NULL); + virtual void Show(); + void Show(bool selectFirstItem); + void Hide(); + BMenuItem* Track(bool startOpened = false, + BRect* specialRect = NULL); public: enum add_state { @@ -153,11 +160,11 @@ public: B_PROCESSING, B_ABORT }; - virtual bool AddDynamicItem(add_state state); - virtual void DrawBackground(BRect update); + virtual bool AddDynamicItem(add_state state); + virtual void DrawBackground(BRect update); - void SetTrackingHook(menu_tracking_hook hook, - void* state); + void SetTrackingHook(menu_tracking_hook hook, + void* state); private: friend class BMenuBar; @@ -168,117 +175,123 @@ private: struct LayoutData; - virtual void _ReservedMenu3(); - virtual void _ReservedMenu4(); - virtual void _ReservedMenu5(); - virtual void _ReservedMenu6(); + virtual void _ReservedMenu3(); + virtual void _ReservedMenu4(); + virtual void _ReservedMenu5(); + virtual void _ReservedMenu6(); - BMenu& operator=(const BMenu& other); + BMenu& operator=(const BMenu& other); - void _InitData(BMessage* archive); - bool _Show(bool selectFirstItem = false); - void _Hide(); - BMenuItem* _Track(int* action, long start = -1); + void _InitData(BMessage* archive); + bool _Show(bool selectFirstItem = false); + void _Hide(); + BMenuItem* _Track(int* action, long start = -1); - void _UpdateNavigationArea(BPoint position, - BRect& navAreaRectAbove, BRect& navAreaBelow); + void _UpdateNavigationArea(BPoint position, + BRect& navAreaRectAbove, + BRect& navAreaBelow); - void _UpdateStateOpenSelect(BMenuItem* item, - BPoint position, BRect& navAreaRectAbove, - BRect& navAreaBelow, bigtime_t& selectedTime, - bigtime_t& navigationAreaTime); - void _UpdateStateClose(BMenuItem* item, const BPoint& where, - const uint32& buttons); + void _UpdateStateOpenSelect(BMenuItem* item, + BPoint position, BRect& navAreaRectAbove, + BRect& navAreaBelow, + bigtime_t& selectedTime, + bigtime_t& navigationAreaTime); + void _UpdateStateClose(BMenuItem* item, + const BPoint& where, + const uint32& buttons); - bool _AddItem(BMenuItem* item, int32 index); - bool _RemoveItems(int32 index, int32 count, - BMenuItem* item, bool deleteItems = false); - bool _RelayoutIfNeeded(); - void _LayoutItems(int32 index); - BSize _ValidatePreferredSize(); - void _ComputeLayout(int32 index, bool bestFit, - bool moveItems, float* width, float* height); - void _ComputeColumnLayout(int32 index, bool bestFit, - bool moveItems, BRect& outRect); - void _ComputeRowLayout(int32 index, bool bestFit, - bool moveItems, BRect& outRect); - void _ComputeMatrixLayout(BRect& outRect); + bool _AddItem(BMenuItem* item, int32 index); + bool _RemoveItems(int32 index, int32 count, + BMenuItem* item, bool deleteItems = false); + bool _RelayoutIfNeeded(); + void _LayoutItems(int32 index); + BSize _ValidatePreferredSize(); + void _ComputeLayout(int32 index, bool bestFit, + bool moveItems, float* width, + float* height); + void _ComputeColumnLayout(int32 index, bool bestFit, + bool moveItems, BRect& outRect); + void _ComputeRowLayout(int32 index, bool bestFit, + bool moveItems, BRect& outRect); + void _ComputeMatrixLayout(BRect& outRect); - BRect _CalcFrame(BPoint where, bool* scrollOn); + BRect _CalcFrame(BPoint where, bool* scrollOn); protected: - void _DrawItems(BRect updateRect); + void _DrawItems(BRect updateRect); private: - bool _OverSuper(BPoint loc); - bool _OverSubmenu(BMenuItem* item, BPoint loc); + bool _OverSuper(BPoint loc); + bool _OverSubmenu(BMenuItem* item, BPoint loc); BPrivate::BMenuWindow* _MenuWindow(); - void _DeleteMenuWindow(); - BMenuItem* _HitTestItems(BPoint where, - BPoint slop = B_ORIGIN) const; - BRect _Superbounds() const; - void _CacheFontInfo(); + void _DeleteMenuWindow(); + BMenuItem* _HitTestItems(BPoint where, + BPoint slop = B_ORIGIN) const; + BRect _Superbounds() const; + void _CacheFontInfo(); - void _ItemMarked(BMenuItem* item); - void _Install(BWindow* target); - void _Uninstall(); - void _SelectItem(BMenuItem* item, - bool showSubmenu = true, - bool selectFirstItem = false); - bool _SelectNextItem(BMenuItem* item, bool forward); - BMenuItem* _NextItem(BMenuItem* item, bool forward) const; - void _SetIgnoreHidden(bool on); - void _SetStickyMode(bool on); - bool _IsStickyMode() const; - void _CalcTriggers(); - bool _ChooseTrigger(const char* title, int32& index, - uint32& trigger, BPrivate::TriggerList& triggers); - void _UpdateWindowViewSize(bool updatePosition = true); - bool _OkToProceed(BMenuItem* item); + void _ItemMarked(BMenuItem* item); + void _Install(BWindow* target); + void _Uninstall(); + void _SelectItem(BMenuItem* item, + bool showSubmenu = true, + bool selectFirstItem = false); + bool _SelectNextItem(BMenuItem* item, bool forward); + BMenuItem* _NextItem(BMenuItem* item, bool forward) const; + void _SetIgnoreHidden(bool on); + void _SetStickyMode(bool on); + bool _IsStickyMode() const; + void _CalcTriggers(); + bool _ChooseTrigger(const char* title, int32& index, + uint32& trigger, + BPrivate::TriggerList& triggers); + void _UpdateWindowViewSize( + bool updatePosition = true); + bool _OkToProceed(BMenuItem* item); - bool _CustomTrackingWantsToQuit(); + bool _CustomTrackingWantsToQuit(); - int _State(BMenuItem** _item = NULL) const; - void _InvokeItem(BMenuItem* item, bool now = false); - void _QuitTracking(bool onlyThis = true); + int _State(BMenuItem** _item = NULL) const; + void _InvokeItem(BMenuItem* item, bool now = false); + void _QuitTracking(bool onlyThis = true); - static menu_info sMenuInfo; - static bool sAltAsCommandKey; + static menu_info sMenuInfo; + static bool sAltAsCommandKey; - BMenuItem* fChosenItem; - BList fItems; - BRect fPad; - BMenuItem* fSelected; + BMenuItem* fChosenItem; + BList fItems; + BRect fPad; + BMenuItem* fSelected; BPrivate::BMenuWindow* fCachedMenuWindow; - BMenu* fSuper; - BMenuItem* fSuperitem; - BRect fSuperbounds; - float fAscent; - float fDescent; - float fFontHeight; - uint32 fState; - menu_layout fLayout; - BRect* fExtraRect; - float fMaxContentWidth; - BPoint* fInitMatrixSize; + BMenu* fSuper; + BMenuItem* fSuperitem; + BRect fSuperbounds; + float fAscent; + float fDescent; + float fFontHeight; + uint32 fState; + menu_layout fLayout; + BRect* fExtraRect; + float fMaxContentWidth; + BPoint* fInitMatrixSize; BPrivate::ExtraMenuData* fExtraMenuData; - LayoutData* fLayoutData; + LayoutData* fLayoutData; - int32 _reserved; + int32 _reserved; - char fTrigger; - bool fResizeToFit; - bool fUseCachedMenuLayout; - bool fEnabled; - bool fDynamicName; - bool fRadioMode; - bool fTrackNewBounds; - bool fStickyMode; - bool fIgnoreHidden; - bool fTriggerEnabled; - bool fRedrawAfterSticky; - bool fAttachAborted; + char fTrigger; + bool fResizeToFit; + bool fUseCachedMenuLayout; + bool fEnabled; + bool fDynamicName; + bool fRadioMode; + bool fTrackNewBounds; + bool fStickyMode; + bool fIgnoreHidden; + bool fTriggerEnabled; + bool fRedrawAfterSticky; + bool fAttachAborted; }; -#endif // _MENU_H +#endif // _MENU_H diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index c7c46761a0..babe00f179 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -1,11 +1,12 @@ /* - * Copyright 2001-2009, Haiku, Inc. - * Distributed under the terms of the MIT License. + * Copyright 2001-2009, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT license. * * Authors: * Marc Flerackers (mflerackers@androme.be) * Stefano Ceccherini (stefano.ceccherini@gmail.com) * Rene Gollent (anevilyak@gmail.com) + * Stephan Aßmus */ @@ -86,8 +87,8 @@ bool BMenu::sAltAsCommandKey; static property_info sPropList[] = { { "Enabled", { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, "Returns true if menu or menu item is enabled; false " - "otherwise.", + { B_DIRECT_SPECIFIER, 0 }, "Returns true if menu or menu item is " + "enabled; false otherwise.", 0, { B_BOOL_TYPE } }, @@ -97,31 +98,34 @@ static property_info sPropList[] = { }, { "Label", { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, "Returns the string label of the menu or menu item.", + { B_DIRECT_SPECIFIER, 0 }, "Returns the string label of the menu or " + "menu item.", 0, { B_STRING_TYPE } }, { "Label", { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, "Sets the string label of the menu or menu item.", + { B_DIRECT_SPECIFIER, 0 }, "Sets the string label of the menu or menu " + "item.", 0, { B_STRING_TYPE } }, { "Mark", { B_GET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, "Returns true if the menu item or the menu's superitem " - "is marked; false otherwise.", + { B_DIRECT_SPECIFIER, 0 }, "Returns true if the menu item or the " + "menu's superitem is marked; false otherwise.", 0, { B_BOOL_TYPE } }, { "Mark", { B_SET_PROPERTY, 0 }, - { B_DIRECT_SPECIFIER, 0 }, "Marks or unmarks the menu item or the menu's superitem.", + { B_DIRECT_SPECIFIER, 0 }, "Marks or unmarks the menu item or the " + "menu's superitem.", 0, { B_BOOL_TYPE } }, { "Menu", { B_CREATE_PROPERTY, 0 }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, - "Adds a new menu item at the specified index with the text label found in \"data\" " - "and the int32 command found in \"what\" (used as the what field in the CMessage " - "sent by the item)." , 0, {}, + "Adds a new menu item at the specified index with the text label " + "found in \"data\" and the int32 command found in \"what\" (used as " + "the what field in the BMessage sent by the item)." , 0, {}, { {{{"data", B_STRING_TYPE}}} } }, @@ -133,20 +137,21 @@ static property_info sPropList[] = { { "Menu", { }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, - "Directs scripting message to the specified menu, first popping the current " - "specifier off the stack.", 0, {} + "Directs scripting message to the specified menu, first popping the " + "current specifier off the stack.", 0, {} }, { "MenuItem", { B_COUNT_PROPERTIES, 0 }, - { B_DIRECT_SPECIFIER, 0 }, "Counts the number of menu items in the specified menu.", + { B_DIRECT_SPECIFIER, 0 }, "Counts the number of menu items in the " + "specified menu.", 0, { B_INT32_TYPE } }, { "MenuItem", { B_CREATE_PROPERTY, 0 }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, - "Adds a new menu item at the specified index with the text label found in \"data\" " - "and the int32 command found in \"what\" (used as the what field in the CMessage " - "sent by the item).", 0, {}, + "Adds a new menu item at the specified index with the text label " + "found in \"data\" and the int32 command found in \"what\" (used as " + "the what field in the BMessage sent by the item).", 0, {}, { { {{"data", B_STRING_TYPE }, {"be:invoke_message", B_MESSAGE_TYPE}, {"what", B_INT32_TYPE}, @@ -166,8 +171,8 @@ static property_info sPropList[] = { { "MenuItem", { }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, - "Directs scripting message to the specified menu, first popping the current " - "specifier off the stack." + "Directs scripting message to the specified menu, first popping the " + "current specifier off the stack." }, {} @@ -183,6 +188,9 @@ struct BMenu::LayoutData { }; +// #pragma mark - + + BMenu::BMenu(const char* name, menu_layout layout) : BView(BRect(0, 0, 0, 0), name, 0, B_WILL_DRAW), @@ -252,18 +260,6 @@ BMenu::BMenu(const char* name, float width, float height) } -BMenu::~BMenu() -{ - _DeleteMenuWindow(); - - RemoveItems(0, CountItems(), true); - - delete fInitMatrixSize; - delete fExtraMenuData; - delete fLayoutData; -} - - BMenu::BMenu(BMessage* archive) : BView(archive), @@ -299,6 +295,21 @@ BMenu::BMenu(BMessage* archive) } +BMenu::~BMenu() +{ + _DeleteMenuWindow(); + + RemoveItems(0, CountItems(), true); + + delete fInitMatrixSize; + delete fExtraMenuData; + delete fLayoutData; +} + + +// #pragma mark - + + BArchivable* BMenu::Instantiate(BMessage* archive) { @@ -347,6 +358,9 @@ BMenu::Archive(BMessage* data, bool deep) const } +// #pragma mark - + + void BMenu::AttachedToWindow() { @@ -393,6 +407,279 @@ BMenu::DetachedFromWindow() } +void +BMenu::AllAttached() +{ + BView::AllAttached(); +} + + +void +BMenu::AllDetached() +{ + BView::AllDetached(); +} + + +// #pragma mark - + + +void +BMenu::Draw(BRect updateRect) +{ + if (_RelayoutIfNeeded()) { + Invalidate(); + return; + } + + + DrawBackground(updateRect); + _DrawItems(updateRect); +} + + +void +BMenu::MessageReceived(BMessage* msg) +{ + switch (msg->what) { + case B_MOUSE_WHEEL_CHANGED: + { + float deltaY = 0; + msg->FindFloat("be:wheel_delta_y", &deltaY); + if (deltaY == 0) + return; + + BMenuWindow* window = dynamic_cast(Window()); + if (window == NULL) + return; + + float largeStep; + float smallStep; + window->GetSteps(&smallStep, &largeStep); + + // pressing the option/command/control key scrolls faster + if (modifiers() & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY)) + deltaY *= largeStep; + else + deltaY *= smallStep; + + window->TryScrollBy(deltaY); + break; + } + + default: + BView::MessageReceived(msg); + break; + } +} + + +void +BMenu::KeyDown(const char* bytes, int32 numBytes) +{ + // TODO: Test how it works on beos and implement it correctly + switch (bytes[0]) { + case B_UP_ARROW: + if (fLayout == B_ITEMS_IN_COLUMN) + _SelectNextItem(fSelected, false); + break; + + case B_DOWN_ARROW: + if (fLayout == B_ITEMS_IN_COLUMN) + _SelectNextItem(fSelected, true); + break; + + case B_LEFT_ARROW: + if (fLayout == B_ITEMS_IN_ROW) + _SelectNextItem(fSelected, false); + else { + // this case has to be handled a bit specially. + BMenuItem* item = Superitem(); + if (item) { + if (dynamic_cast(Supermenu())) { + // If we're at the top menu below the menu bar, pass + // the keypress to the menu bar so we can move to + // another top level menu. + BMessenger msgr(Supermenu()); + msgr.SendMessage(Window()->CurrentMessage()); + } else + Supermenu()->_SelectItem(item, false, false); + } + } + break; + + case B_RIGHT_ARROW: + if (fLayout == B_ITEMS_IN_ROW) + _SelectNextItem(fSelected, true); + else { + if (fSelected && fSelected->Submenu()) { + _SelectItem(fSelected, true, true); + } else if (dynamic_cast(Supermenu())) { + // if we have no submenu and we're an + // item in the top menu below the menubar, + // pass the keypress to the menubar + // so you can use the keypress to switch menus. + BMessenger msgr(Supermenu()); + msgr.SendMessage(Window()->CurrentMessage()); + } + } + break; + + case B_PAGE_UP: + case B_PAGE_DOWN: + { + BMenuWindow* window = dynamic_cast(Window()); + if (window == NULL || !window->HasScrollers()) + break; + + int32 deltaY = bytes[0] == B_PAGE_UP ? -1 : 1; + + float largeStep; + window->GetSteps(NULL, &largeStep); + window->TryScrollBy(deltaY * largeStep); + break; + } + + case B_ENTER: + case B_SPACE: + if (fSelected) { + _InvokeItem(fSelected); + _QuitTracking(false); + } + break; + + case B_ESCAPE: + _QuitTracking(); + break; + + default: + { + uint32 trigger = UTF8ToCharCode(&bytes); + + for (uint32 i = CountItems(); i-- > 0;) { + BMenuItem* item = ItemAt(i); + if (item->fTriggerIndex < 0 || item->fTrigger != trigger) + continue; + + _InvokeItem(item); + } + break; + } + } +} + + +// #pragma mark - + + +BSize +BMenu::MinSize() +{ + _ValidatePreferredSize(); + + BSize size = (GetLayout() ? GetLayout()->MinSize() + : fLayoutData->preferred); + return BLayoutUtils::ComposeSize(ExplicitMinSize(), size); +} + + +BSize +BMenu::MaxSize() +{ + _ValidatePreferredSize(); + + BSize size = (GetLayout() ? GetLayout()->MaxSize() + : fLayoutData->preferred); + return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size); +} + + +BSize +BMenu::PreferredSize() +{ + _ValidatePreferredSize(); + + BSize size = (GetLayout() ? GetLayout()->PreferredSize() + : fLayoutData->preferred); + return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size); +} + + +void +BMenu::GetPreferredSize(float* _width, float* _height) +{ + _ValidatePreferredSize(); + + if (_width) + *_width = fLayoutData->preferred.width; + if (_height) + *_height = fLayoutData->preferred.height; +} + + +void +BMenu::ResizeToPreferred() +{ + BView::ResizeToPreferred(); +} + + +void +BMenu::DoLayout() +{ + // If the user set a layout, we let the base class version call its + // hook. + if (GetLayout()) { + BView::DoLayout(); + return; + } + + if (_RelayoutIfNeeded()) + Invalidate(); +} + + +void +BMenu::FrameMoved(BPoint new_position) +{ + BView::FrameMoved(new_position); +} + + +void +BMenu::FrameResized(float new_width, float new_height) +{ + BView::FrameResized(new_width, new_height); +} + + +void +BMenu::InvalidateLayout() +{ + InvalidateLayout(false); +} + + +void +BMenu::InvalidateLayout(bool descendants) +{ + fUseCachedMenuLayout = false; + fLayoutData->preferred.Set(B_SIZE_UNSET, B_SIZE_UNSET); + + BView::InvalidateLayout(descendants); +} + + +// #pragma mark - + + +void +BMenu::MakeFocus(bool focused) +{ + BView::MakeFocus(focused); +} + + bool BMenu::AddItem(BMenuItem* item) { @@ -589,8 +876,10 @@ bool BMenu::RemoveItem(BMenu* submenu) { for (int32 i = 0; i < fItems.CountItems(); i++) { - if (static_cast(fItems.ItemAtFast(i))->Submenu() == submenu) + if (static_cast(fItems.ItemAtFast(i))->Submenu() + == submenu) { return _RemoveItems(i, 1, NULL, false); + } } return false; @@ -827,246 +1116,7 @@ BMenu::Superitem() const } -void -BMenu::MessageReceived(BMessage* msg) -{ - switch (msg->what) { - case B_MOUSE_WHEEL_CHANGED: - { - float deltaY = 0; - msg->FindFloat("be:wheel_delta_y", &deltaY); - if (deltaY == 0) - return; - - BMenuWindow* window = dynamic_cast(Window()); - if (window == NULL) - return; - - float largeStep; - float smallStep; - window->GetSteps(&smallStep, &largeStep); - - // pressing the option/command/control key scrolls faster - if (modifiers() & (B_OPTION_KEY | B_COMMAND_KEY | B_CONTROL_KEY)) - deltaY *= largeStep; - else - deltaY *= smallStep; - - window->TryScrollBy(deltaY); - break; - } - - default: - BView::MessageReceived(msg); - break; - } -} - - -void -BMenu::KeyDown(const char* bytes, int32 numBytes) -{ - // TODO: Test how it works on beos and implement it correctly - switch (bytes[0]) { - case B_UP_ARROW: - if (fLayout == B_ITEMS_IN_COLUMN) - _SelectNextItem(fSelected, false); - break; - - case B_DOWN_ARROW: - if (fLayout == B_ITEMS_IN_COLUMN) - _SelectNextItem(fSelected, true); - break; - - case B_LEFT_ARROW: - if (fLayout == B_ITEMS_IN_ROW) - _SelectNextItem(fSelected, false); - else { - // this case has to be handled a bit specially. - BMenuItem* item = Superitem(); - if (item) { - if (dynamic_cast(Supermenu())) { - // if we're at the top menu below the menu bar, pass the keypress to - // the menu bar so we can move to another top level menu - BMessenger msgr(Supermenu()); - msgr.SendMessage(Window()->CurrentMessage()); - } else - Supermenu()->_SelectItem(item, false, false); - } - } - break; - - case B_RIGHT_ARROW: - if (fLayout == B_ITEMS_IN_ROW) - _SelectNextItem(fSelected, true); - else { - if (fSelected && fSelected->Submenu()) { - _SelectItem(fSelected, true, true); - } else if (dynamic_cast(Supermenu())) { - // if we have no submenu and we're an - // item in the top menu below the menubar, - // pass the keypress to the menubar - // so you can use the keypress to switch menus. - BMessenger msgr(Supermenu()); - msgr.SendMessage(Window()->CurrentMessage()); - } - } - break; - - case B_PAGE_UP: - case B_PAGE_DOWN: - { - BMenuWindow* window = dynamic_cast(Window()); - if (window == NULL || !window->HasScrollers()) - break; - - int32 deltaY = bytes[0] == B_PAGE_UP ? -1 : 1; - - float largeStep; - window->GetSteps(NULL, &largeStep); - window->TryScrollBy(deltaY * largeStep); - break; - } - - case B_ENTER: - case B_SPACE: - if (fSelected) { - _InvokeItem(fSelected); - _QuitTracking(false); - } - break; - - case B_ESCAPE: - _QuitTracking(); - break; - - default: - { - uint32 trigger = UTF8ToCharCode(&bytes); - - for (uint32 i = CountItems(); i-- > 0;) { - BMenuItem* item = ItemAt(i); - if (item->fTriggerIndex < 0 || item->fTrigger != trigger) - continue; - - _InvokeItem(item); - } - break; - } - } -} - - -void -BMenu::Draw(BRect updateRect) -{ - if (_RelayoutIfNeeded()) { - Invalidate(); - return; - } - - - DrawBackground(updateRect); - _DrawItems(updateRect); -} - - -BSize -BMenu::MinSize() -{ - _ValidatePreferredSize(); - - BSize size = (GetLayout() ? GetLayout()->MinSize() - : fLayoutData->preferred); - return BLayoutUtils::ComposeSize(ExplicitMinSize(), size); -} - - -BSize -BMenu::MaxSize() -{ - _ValidatePreferredSize(); - - BSize size = (GetLayout() ? GetLayout()->MaxSize() - : fLayoutData->preferred); - return BLayoutUtils::ComposeSize(ExplicitMaxSize(), size); -} - - -BSize -BMenu::PreferredSize() -{ - _ValidatePreferredSize(); - - BSize size = (GetLayout() ? GetLayout()->PreferredSize() - : fLayoutData->preferred); - return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), size); -} - - -void -BMenu::GetPreferredSize(float* _width, float* _height) -{ - _ValidatePreferredSize(); - - if (_width) - *_width = fLayoutData->preferred.width; - if (_height) - *_height = fLayoutData->preferred.height; -} - - -void -BMenu::ResizeToPreferred() -{ - BView::ResizeToPreferred(); -} - - -void -BMenu::DoLayout() -{ - // If the user set a layout, we let the base class version call its - // hook. - if (GetLayout()) { - BView::DoLayout(); - return; - } - - if (_RelayoutIfNeeded()) - Invalidate(); -} - - -void -BMenu::FrameMoved(BPoint new_position) -{ - BView::FrameMoved(new_position); -} - - -void -BMenu::FrameResized(float new_width, float new_height) -{ - BView::FrameResized(new_width, new_height); -} - - -void -BMenu::InvalidateLayout() -{ - InvalidateLayout(false); -} - - -void -BMenu::InvalidateLayout(bool descendants) -{ - fUseCachedMenuLayout = false; - fLayoutData->preferred.Set(B_SIZE_UNSET, B_SIZE_UNSET); - - BView::InvalidateLayout(descendants); -} +// #pragma mark - BHandler* @@ -1191,30 +1241,10 @@ BMenu::Perform(perform_code code, void* _data) } -void -BMenu::MakeFocus(bool focused) -{ - BView::MakeFocus(focused); -} - - -void -BMenu::AllAttached() -{ - BView::AllAttached(); -} - - -void -BMenu::AllDetached() -{ - BView::AllDetached(); -} - - BMenu::BMenu(BRect frame, const char* name, uint32 resizingMode, uint32 flags, menu_layout layout, bool resizeToFit) - : BView(frame, name, resizingMode, flags), + : + BView(frame, name, resizingMode, flags), fChosenItem(NULL), fSelected(NULL), fCachedMenuWindow(NULL), @@ -1467,7 +1497,8 @@ BMenu::_Show(bool selectFirstItem) // Menu didn't have the time to add its items: aborting... if (fAttachAborted) { window->DetachMenu(); - // TODO: Probably not needed, we can just let _hide() quit the window + // TODO: Probably not needed, we can just let _hide() quit the + // window. if (ourWindow) window->Quit(); else @@ -1518,7 +1549,8 @@ BMenu::_Hide() const static bigtime_t kOpenSubmenuDelay = 225000; const static bigtime_t kNavigationAreaTimeout = 1000000; -const static bigtime_t kHysteresis = 200000; // TODO: Test and reduce if needed. +const static bigtime_t kHysteresis = 200000; + // TODO: Test and reduce if needed. const static int32 kMouseMotionThreshold = 15; // TODO: Same as above. Actually, we could get rid of the kHysteresis @@ -1795,7 +1827,8 @@ BMenu::_UpdateStateOpenSelect(BMenuItem* item, BPoint position, float yOffset = navAreaRectBelow.bottom - position.y; float ratio = navAreaRectBelow.Width() / navAreaRectBelow.Height(); - inNavArea = yOffset >= (navAreaRectBelow.Height() - xOffset / ratio); + inNavArea = yOffset >= (navAreaRectBelow.Height() - xOffset + / ratio); } bigtime_t systime = system_time(); @@ -1823,7 +1856,8 @@ BMenu::_UpdateStateOpenSelect(BMenuItem* item, BPoint position, if (!navAreaRectAbove.IsValid() && !navAreaRectBelow.IsValid()) { position = ConvertToScreen(position); - _UpdateNavigationArea(position, navAreaRectAbove, navAreaRectBelow); + _UpdateNavigationArea(position, navAreaRectAbove, + navAreaRectBelow); } } @@ -1896,7 +1930,8 @@ BMenu::_AddItem(BMenuItem* item, int32 index) bool -BMenu::_RemoveItems(int32 index, int32 count, BMenuItem* item, bool deleteItems) +BMenu::_RemoveItems(int32 index, int32 count, BMenuItem* item, + bool deleteItems) { bool success = false; bool invalidateLayout = false; @@ -2229,8 +2264,10 @@ BMenu::_CalcFrame(BPoint where, bool* scrollOn) else if (frame.left < screenFrame.left) frame.OffsetBy(-frame.left, 0); } else if (superMenu->Layout() == B_ITEMS_IN_COLUMN) { - if (frame.right > screenFrame.right) - frame.OffsetBy(-superItem->Frame().Width() - frame.Width() - 2, 0); + if (frame.right > screenFrame.right) { + frame.OffsetBy(-superItem->Frame().Width() - frame.Width() - 2, + 0); + } if (frame.left < 0) frame.OffsetBy(-frame.left + 6, 0); @@ -2244,7 +2281,8 @@ BMenu::_CalcFrame(BPoint where, bool* scrollOn) && frame.top < (screenFrame.bottom - 80)) { scroll = true; } else { - frame.OffsetBy(0, -superItem->Frame().Height() - frame.Height() - 3); + frame.OffsetBy(0, -superItem->Frame().Height() + - frame.Height() - 3); } } @@ -2531,8 +2569,10 @@ BMenu::_NextItem(BMenuItem* item, bool forward) const index = 0; } while (!ItemAt(index)->IsEnabled() && index != startIndex); - if (index == startIndex) // we are back where we started and no item was enabled + if (index == startIndex) { + // We are back where we started and no item was enabled. return NULL; + } return ItemAt(index); } @@ -2698,7 +2738,8 @@ BMenu::_OkToProceed(BMenuItem* item) // or releases the mouse button in nonsticky mode // or moves the pointer over another item // TODO: I added the check for BMenuBar to solve a problem with Deskbar. - // BeOS seems to do something similar. This could also be a bug in Deskbar, though. + // BeOS seems to do something similar. This could also be a bug in + // Deskbar, though. if ((buttons != 0 && stickyMode) || ((dynamic_cast(this) == NULL && (buttons == 0 && !stickyMode)) || _HitTestItems(where) != item)) @@ -2713,7 +2754,8 @@ BMenu::_CustomTrackingWantsToQuit() { if (fExtraMenuData != NULL && fExtraMenuData->trackingHook != NULL && fExtraMenuData->trackingState != NULL) { - return fExtraMenuData->trackingHook(this, fExtraMenuData->trackingState); + return fExtraMenuData->trackingHook(this, + fExtraMenuData->trackingState); } return false; @@ -2741,7 +2783,8 @@ BMenu::_QuitTracking(bool onlyThis) // #pragma mark - -// TODO: Maybe the following two methods would fit better into InterfaceDefs.cpp +// TODO: Maybe the following two methods would fit better into +// InterfaceDefs.cpp // In R5, they do all the work client side, we let the app_server handle the // details. status_t