diff --git a/headers/os/interface/Menu.h b/headers/os/interface/Menu.h index 4d69cf0da4..bca34ab445 100644 --- a/headers/os/interface/Menu.h +++ b/headers/os/interface/Menu.h @@ -1,33 +1,25 @@ -/******************************************************************************* -/ -/ File: Menu.h -/ -/ Description: BMenu display a menu of selectable items. -/ -/ Copyright 1994-98, Be Incorporated, All Rights Reserved -/ -*******************************************************************************/ - +/* + * Copyright 2007, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ #ifndef _MENU_H #define _MENU_H -#include + #include #include #include -/*----------------------------------------------------------------*/ -/*----- Menu declarations and structures -------------------------*/ - class BMenuItem; class BMenuBar; + namespace BPrivate { class BMenuWindow; + class ExtraMenuData; + class TriggerList; } -class _ExtraMenuData_; - enum menu_layout { B_ITEMS_IN_ROW = 0, B_ITEMS_IN_COLUMN, @@ -44,281 +36,242 @@ struct menu_info { bool triggers_always_shown; }; -_IMPEXP_BE status_t set_menu_info(menu_info *info); -_IMPEXP_BE status_t get_menu_info(menu_info *info); +status_t get_menu_info(menu_info* info); +status_t set_menu_info(menu_info* info); -typedef bool (* menu_tracking_hook )(BMenu *, void *); +typedef bool (*menu_tracking_hook)(BMenu* menu, void* state); -/*----------------------------------------------------------------*/ -/*----- BMenu class ----------------------------------------------*/ -class BMenu : public BView -{ +class BMenu : public BView { public: - BMenu( const char *title, + 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, float width, float height); + virtual ~BMenu(); - BMenu(BMessage *data); -static BArchivable *Instantiate(BMessage *data); -virtual status_t Archive(BMessage *data, bool deep = true) const; + BMenu(BMessage* archive); + static BArchivable* Instantiate(BMessage* archive); + virtual status_t Archive(BMessage* archive, bool deep = true) const; -virtual void AttachedToWindow(); -virtual void DetachedFromWindow(); + virtual void AttachedToWindow(); + virtual void DetachedFromWindow(); - 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); - bool AddSeparatorItem(); - bool RemoveItem(BMenuItem *item); - BMenuItem *RemoveItem(int32 index); - bool RemoveItems(int32 index, - int32 count, - bool del = false); - bool RemoveItem(BMenu *menu); + 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 *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; + bool AddSeparatorItem(); -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 max); + bool RemoveItem(BMenuItem* item); + BMenuItem* RemoveItem(int32 index); + bool RemoveItems(int32 index, int32 count, + bool deleteItems = false); + bool RemoveItem(BMenu* menu); - void SetLabelFromMarked(bool on); - bool IsLabelFromMarked(); - bool IsEnabled() const; - bool IsRadioMode() const; - bool AreTriggersEnabled() const; - bool IsRedrawAfterSticky() const; - float MaxContentWidth() const; + 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; - BMenuItem *FindMarked(); + 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); - BMenu *Supermenu() const; - BMenuItem *Superitem() const; + void SetLabelFromMarked(bool state); + bool IsLabelFromMarked(); + bool IsEnabled() const; + bool IsRadioMode() const; + bool AreTriggersEnabled() const; + bool IsRedrawAfterSticky() const; + float MaxContentWidth() const; -virtual void MessageReceived(BMessage *msg); -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 new_position); -virtual void FrameResized(float new_width, float new_height); - void InvalidateLayout(); -virtual void InvalidateLayout(bool descendants); - -virtual BHandler *ResolveSpecifier(BMessage *msg, - int32 index, - BMessage *specifier, - int32 form, - const char *property); -virtual status_t GetSupportedSuites(BMessage *data); + BMenuItem* FindMarked(); -virtual status_t Perform(perform_code d, void *arg); + BMenu* Supermenu() const; + BMenuItem* Superitem() const; -virtual void MakeFocus(bool state = true); -virtual void AllAttached(); -virtual void AllDetached(); + 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); + + 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); + + virtual void MakeFocus(bool focus = true); + virtual void AllAttached(); + virtual void AllDetached(); protected: - - BMenu( BRect frame, - const char *viewName, - 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 start_opened = false, - BRect *special_rect = NULL); - public: - enum add_state { - B_INITIAL_ADD, - B_PROCESSING, - B_ABORT - }; -virtual bool AddDynamicItem(add_state s); -virtual void DrawBackground(BRect update); + enum add_state { + B_INITIAL_ADD, + B_PROCESSING, + B_ABORT + }; + virtual bool AddDynamicItem(add_state state); + virtual void DrawBackground(BRect update); + + void SetTrackingHook(menu_tracking_hook hook, + void* state); - void SetTrackingHook(menu_tracking_hook func, void *state); - -/*----- Private or reserved -----------------------------------------*/ private: -friend class BWindow; -friend class BMenuBar; -friend class BMenuItem; -friend status_t _init_interface_kit_(); -friend status_t set_menu_info(menu_info *); -friend status_t get_menu_info(menu_info *); + friend class BWindow; + friend class BMenuBar; + friend class BMenuItem; + friend status_t _init_interface_kit_(); + friend status_t set_menu_info(menu_info* info); + friend status_t get_menu_info(menu_info* info); -struct LayoutData; + 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 &); + BMenu& operator=(const BMenu& other); - void InitData(BMessage *data = NULL); - 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 _UpdateStateOpenSelect(BMenuItem *item, bigtime_t &openTime, bigtime_t &closeTime); - 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 del = 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); + void _UpdateStateOpenSelect(BMenuItem* item, + bigtime_t& openTime, bigtime_t& closeTime); + void _UpdateStateClose(BMenuItem* item, + const BPoint& where, const uint32& buttons); - BRect Bump(BRect current, BPoint extent, int32 index) const; - BPoint ItemLocInRect(BRect frame) const; - BRect CalcFrame(BPoint where, bool *scrollOn); - bool ScrollMenu(BRect bounds, BPoint loc, bool *fast); - void ScrollIntoView(BMenuItem *item); + 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); - void DrawItems(BRect updateRect); - int State(BMenuItem **item = NULL) const; - void InvokeItem(BMenuItem *item, bool now = false); + BRect _CalcFrame(BPoint where, bool* scrollOn); - 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 _DrawItems(BRect updateRect); - void ItemMarked(BMenuItem *item); - void Install(BWindow *target); - void Uninstall(); - void _SelectItem(BMenuItem* item, bool showSubmenu = true, - bool selectFirstItem = false); - BMenuItem *CurrentSelection() const; - bool SelectNextItem(BMenuItem *item, bool forward); - BMenuItem *NextItem(BMenuItem *item, bool forward) const; - bool IsItemVisible(BMenuItem *item) const; - void SetIgnoreHidden(bool on); - void SetStickyMode(bool on); - bool IsStickyMode() const; - void CalcTriggers(); - const char *ChooseTrigger(const char *title, BList *chars); - void UpdateWindowViewSize(bool upWind = true); - bool IsStickyPrefOn(); - void RedrawAfterSticky(BRect bounds); - bool OkToProceed(BMenuItem *); - - bool CustomTrackingWantsToQuit(); + 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 QuitTracking(); - + 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); - status_t ParseMsg(BMessage *msg, int32 *sindex, BMessage *spec, - int32 *form, const char **prop, - BMenu **tmenu, BMenuItem **titem, int32 *user_data, - BMessage *reply) const; + bool _CustomTrackingWantsToQuit(); - status_t DoMenuMsg(BMenuItem **next, BMenu *tar, BMessage *m, - BMessage *r, BMessage *spec, int32 f) const; - status_t DoMenuItemMsg(BMenuItem **next, BMenu *tar, BMessage *m, - BMessage *r, BMessage *spec, int32 f) const; + // private methods called by BWindow + int State(BMenuItem** _item = NULL) const; + void InvokeItem(BMenuItem* item, bool now = false); + void QuitTracking(); - status_t DoEnabledMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const; - status_t DoLabelMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const; - status_t DoMarkMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const; - status_t DoDeleteMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const; - status_t DoCreateMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r, bool menu) const; + static menu_info sMenuInfo; + static bool sAltAsCommandKey; -static menu_info sMenuInfo; -static bool sAltAsCommandKey; + 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; + BPrivate::ExtraMenuData* fExtraMenuData; - 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; - _ExtraMenuData_ *fExtraMenuData; + LayoutData* fLayoutData; - LayoutData* fLayoutData; + int32 fSubmenus; - int32 fSubmenus; - - 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/headers/os/interface/MenuItem.h b/headers/os/interface/MenuItem.h index 6ccd24cfbf..8e3fe9664f 100644 --- a/headers/os/interface/MenuItem.h +++ b/headers/os/interface/MenuItem.h @@ -1,5 +1,5 @@ /* - * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _MENU_ITEM_H @@ -65,7 +65,7 @@ class BMenuItem : public BArchivable, public BInvoker { void Uninstall(); void SetSuper(BMenu* superMenu); void Select(bool select); - void SetAutomaticTrigger(char trigger); + void SetAutomaticTrigger(int32 index, uint32 trigger); protected: virtual status_t Invoke(BMessage *msg = NULL); @@ -91,13 +91,13 @@ class BMenuItem : public BArchivable, public BInvoker { float fCachedWidth; int16 fTriggerIndex; char fUserTrigger; - char fAutomaticTrigger; char fShortcutChar; bool fMark; bool fEnabled; bool fSelected; + uint32 fTrigger; - uint32 _reserved[4]; + uint32 _reserved[3]; }; // BSeparatorItem now has its own declaration file, but for source diff --git a/src/kits/interface/Menu.cpp b/src/kits/interface/Menu.cpp index 3e24220cf7..d88aad52aa 100644 --- a/src/kits/interface/Menu.cpp +++ b/src/kits/interface/Menu.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006, Haiku, Inc. + * Copyright 2001-2007, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -30,61 +30,82 @@ #include #include +#include "utf8_functions.h" + + using std::nothrow; using BPrivate::BMenuWindow; +namespace BPrivate { -class _ExtraMenuData_ { +class TriggerList { +public: + TriggerList() {} + ~TriggerList() {} + + // TODO: make this work with Unicode characters! + + bool HasTrigger(uint32 c) + { return fList.HasItem((void*)tolower(c)); } + bool AddTrigger(uint32 c) + { return fList.AddItem((void*)tolower(c)); } + +private: + BList fList; +}; + +class ExtraMenuData { public: menu_tracking_hook trackingHook; void *trackingState; - _ExtraMenuData_(menu_tracking_hook func, void *state) + ExtraMenuData(menu_tracking_hook func, void *state) { trackingHook = func; trackingState = state; - }; + } }; +} // namespace BPrivate + menu_info BMenu::sMenuInfo; bool BMenu::sAltAsCommandKey; -static property_info -sPropList[] = { +static property_info sPropList[] = { { "Enabled", { B_GET_PROPERTY, 0 }, { B_DIRECT_SPECIFIER, 0 }, "Returns true if menu or menu item is enabled; false " "otherwise.", 0, { B_BOOL_TYPE } }, - + { "Enabled", { B_SET_PROPERTY, 0 }, { B_DIRECT_SPECIFIER, 0 }, "Enables or disables menu or menu item.", 0, { B_BOOL_TYPE } }, - + { "Label", { B_GET_PROPERTY, 0 }, { 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.", 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.", 0, { B_BOOL_TYPE } }, - + { "Mark", { B_SET_PROPERTY, 0 }, { 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\" " @@ -93,7 +114,7 @@ sPropList[] = { { {{{"data", B_STRING_TYPE}}} } }, - + { "Menu", { B_DELETE_PROPERTY, 0 }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, "Removes the selected menu or menus.", 0, {} @@ -104,12 +125,12 @@ sPropList[] = { "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.", 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\" " @@ -126,12 +147,12 @@ sPropList[] = { { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, "Removes the specified menu item from its parent menu." }, - + { "MenuItem", { B_EXECUTE_PROPERTY, 0 }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, "Invokes the specified menu item." }, - + { "MenuItem", { }, { B_NAME_SPECIFIER, B_INDEX_SPECIFIER, B_REVERSE_INDEX_SPECIFIER, 0 }, "Directs scripting message to the specified menu, first popping the current " @@ -151,80 +172,80 @@ struct BMenu::LayoutData { BMenu::BMenu(const char *name, menu_layout layout) - : BView(BRect(0, 0, 0, 0), name, 0, B_WILL_DRAW), - fChosenItem(NULL), - fPad(14.0f, 2.0f, 20.0f, 0.0f), - fSelected(NULL), - fCachedMenuWindow(NULL), - fSuper(NULL), - fSuperitem(NULL), - fAscent(-1.0f), - fDescent(-1.0f), - fFontHeight(-1.0f), - fState(0), - fLayout(layout), - fExtraRect(NULL), - fMaxContentWidth(0.0f), - fInitMatrixSize(NULL), - fExtraMenuData(NULL), - fSubmenus(0), - fTrigger(0), - fResizeToFit(true), - fUseCachedMenuLayout(false), - fEnabled(true), - fDynamicName(false), - fRadioMode(false), - fTrackNewBounds(false), - fStickyMode(false), - fIgnoreHidden(true), - fTriggerEnabled(true), - fRedrawAfterSticky(false), - fAttachAborted(false) + : BView(BRect(0, 0, 0, 0), name, 0, B_WILL_DRAW), + fChosenItem(NULL), + fPad(14.0f, 2.0f, 20.0f, 0.0f), + fSelected(NULL), + fCachedMenuWindow(NULL), + fSuper(NULL), + fSuperitem(NULL), + fAscent(-1.0f), + fDescent(-1.0f), + fFontHeight(-1.0f), + fState(0), + fLayout(layout), + fExtraRect(NULL), + fMaxContentWidth(0.0f), + fInitMatrixSize(NULL), + fExtraMenuData(NULL), + fSubmenus(0), + fTrigger(0), + fResizeToFit(true), + fUseCachedMenuLayout(false), + fEnabled(true), + fDynamicName(false), + fRadioMode(false), + fTrackNewBounds(false), + fStickyMode(false), + fIgnoreHidden(true), + fTriggerEnabled(true), + fRedrawAfterSticky(false), + fAttachAborted(false) { - InitData(NULL); + _InitData(NULL); } BMenu::BMenu(const char *name, float width, float height) - : BView(BRect(0.0f, width, 0.0f, height), name, 0, B_WILL_DRAW), - fChosenItem(NULL), - fSelected(NULL), - fCachedMenuWindow(NULL), - fSuper(NULL), - fSuperitem(NULL), - fAscent(-1.0f), - fDescent(-1.0f), - fFontHeight(-1.0f), - fState(0), - fLayout(B_ITEMS_IN_MATRIX), - fExtraRect(NULL), - fMaxContentWidth(0.0f), - fInitMatrixSize(NULL), - fExtraMenuData(NULL), - fSubmenus(0), - fTrigger(0), - fResizeToFit(true), - fUseCachedMenuLayout(false), - fEnabled(true), - fDynamicName(false), - fRadioMode(false), - fTrackNewBounds(false), - fStickyMode(false), - fIgnoreHidden(true), - fTriggerEnabled(true), - fRedrawAfterSticky(false), - fAttachAborted(false) + : BView(BRect(0.0f, width, 0.0f, height), name, 0, B_WILL_DRAW), + fChosenItem(NULL), + fSelected(NULL), + fCachedMenuWindow(NULL), + fSuper(NULL), + fSuperitem(NULL), + fAscent(-1.0f), + fDescent(-1.0f), + fFontHeight(-1.0f), + fState(0), + fLayout(B_ITEMS_IN_MATRIX), + fExtraRect(NULL), + fMaxContentWidth(0.0f), + fInitMatrixSize(NULL), + fExtraMenuData(NULL), + fSubmenus(0), + fTrigger(0), + fResizeToFit(true), + fUseCachedMenuLayout(false), + fEnabled(true), + fDynamicName(false), + fRadioMode(false), + fTrackNewBounds(false), + fStickyMode(false), + fIgnoreHidden(true), + fTriggerEnabled(true), + fRedrawAfterSticky(false), + fAttachAborted(false) { - InitData(NULL); + _InitData(NULL); } BMenu::~BMenu() { - DeleteMenuWindow(); + _DeleteMenuWindow(); RemoveItems(0, CountItems(), true); - + delete fInitMatrixSize; delete fExtraMenuData; delete fLayoutData; @@ -232,46 +253,46 @@ BMenu::~BMenu() BMenu::BMenu(BMessage *archive) - : BView(archive), - fChosenItem(NULL), - fPad(14.0f, 2.0f, 20.0f, 0.0f), - fSelected(NULL), - fCachedMenuWindow(NULL), - fSuper(NULL), - fSuperitem(NULL), - fAscent(-1.0f), - fDescent(-1.0f), - fFontHeight(-1.0f), - fState(0), - fLayout(B_ITEMS_IN_ROW), - fExtraRect(NULL), - fMaxContentWidth(0.0f), - fInitMatrixSize(NULL), - fExtraMenuData(NULL), - fSubmenus(0), - fTrigger(0), - fResizeToFit(true), - fUseCachedMenuLayout(false), - fEnabled(true), - fDynamicName(false), - fRadioMode(false), - fTrackNewBounds(false), - fStickyMode(false), - fIgnoreHidden(true), - fTriggerEnabled(true), - fRedrawAfterSticky(false), - fAttachAborted(false) + : BView(archive), + fChosenItem(NULL), + fPad(14.0f, 2.0f, 20.0f, 0.0f), + fSelected(NULL), + fCachedMenuWindow(NULL), + fSuper(NULL), + fSuperitem(NULL), + fAscent(-1.0f), + fDescent(-1.0f), + fFontHeight(-1.0f), + fState(0), + fLayout(B_ITEMS_IN_ROW), + fExtraRect(NULL), + fMaxContentWidth(0.0f), + fInitMatrixSize(NULL), + fExtraMenuData(NULL), + fSubmenus(0), + fTrigger(0), + fResizeToFit(true), + fUseCachedMenuLayout(false), + fEnabled(true), + fDynamicName(false), + fRadioMode(false), + fTrackNewBounds(false), + fStickyMode(false), + fIgnoreHidden(true), + fTriggerEnabled(true), + fRedrawAfterSticky(false), + fAttachAborted(false) { - InitData(archive); + _InitData(archive); } -BArchivable * -BMenu::Instantiate(BMessage *data) +BArchivable* +BMenu::Instantiate(BMessage* archive) { - if (validate_instantiation(data, "BMenu")) - return new (nothrow) BMenu(data); - + if (validate_instantiation(archive, "BMenu")) + return new (nothrow) BMenu(archive); + return NULL; } @@ -323,7 +344,8 @@ BMenu::AttachedToWindow() key_map *keys = NULL; char *chars = NULL; get_key_map(&keys, &chars); - if (keys == NULL || keys->left_command_key != 0x5d || keys->right_command_key != 0x5f) + if (keys == NULL || keys->left_command_key != 0x5d + || keys->right_command_key != 0x5f) sAltAsCommandKey = false; free(chars); free(keys); @@ -332,7 +354,7 @@ BMenu::AttachedToWindow() BMenu *superMenu = Supermenu(); if (AddDynamicItem(B_INITIAL_ADD)) { do { - if (superMenu != NULL && !superMenu->OkToProceed(superItem)) { + if (superMenu != NULL && !superMenu->_OkToProceed(superItem)) { AddDynamicItem(B_ABORT); fAttachAborted = true; break; @@ -341,9 +363,9 @@ BMenu::AttachedToWindow() } if (!fAttachAborted) { - CacheFontInfo(); - LayoutItems(0); - UpdateWindowViewSize(false); + _CacheFontInfo(); + _LayoutItems(0); + _UpdateWindowViewSize(false); } } @@ -375,8 +397,8 @@ BMenu::AddItem(BMenuItem *item, int32 index) InvalidateLayout(); if (LockLooper()) { if (!Window()->IsHidden()) { - LayoutItems(index); - UpdateWindowViewSize(false); + _LayoutItems(index); + _UpdateWindowViewSize(false); Invalidate(); } UnlockLooper(); @@ -404,7 +426,7 @@ BMenu::AddItem(BMenuItem *item, BRect frame) if (LockLooper()) { if (!Window()->IsHidden()) { - LayoutItems(index); + _LayoutItems(index); Invalidate(); } UnlockLooper(); @@ -494,8 +516,8 @@ BMenu::AddList(BList *list, int32 index) InvalidateLayout(); if (locked && Window() != NULL && !Window()->IsHidden()) { // Make sure we update the layout if needed. - LayoutItems(index); - UpdateWindowViewSize(false); + _LayoutItems(index); + _UpdateWindowViewSize(false); Invalidate(); } @@ -522,8 +544,7 @@ BMenu::AddSeparatorItem() bool BMenu::RemoveItem(BMenuItem *item) { - // TODO: Check if item is also deleted - return RemoveItems(0, 0, item, false); + return _RemoveItems(0, 0, item, false); } @@ -532,15 +553,15 @@ BMenu::RemoveItem(int32 index) { BMenuItem *item = ItemAt(index); if (item != NULL) - RemoveItems(0, 0, item, false); + _RemoveItems(0, 0, item, false); return item; } bool -BMenu::RemoveItems(int32 index, int32 count, bool del) +BMenu::RemoveItems(int32 index, int32 count, bool deleteItems) { - return RemoveItems(index, count, NULL, del); + return _RemoveItems(index, count, NULL, deleteItems); } @@ -549,7 +570,7 @@ BMenu::RemoveItem(BMenu *submenu) { for (int32 i = 0; i < fItems.CountItems(); i++) { if (static_cast(fItems.ItemAtFast(i))->Submenu() == submenu) - return RemoveItems(i, 1, NULL, false); + return _RemoveItems(i, 1, NULL, false); } return false; @@ -800,37 +821,47 @@ BMenu::KeyDown(const char *bytes, int32 numBytes) switch (bytes[0]) { case B_UP_ARROW: if (fLayout == B_ITEMS_IN_COLUMN) - SelectNextItem(fSelected, false); + _SelectNextItem(fSelected, false); break; case B_DOWN_ARROW: if (fLayout == B_ITEMS_IN_COLUMN) - SelectNextItem(fSelected, true); + _SelectNextItem(fSelected, true); break; case B_LEFT_ARROW: if (fLayout == B_ITEMS_IN_ROW) - SelectNextItem(fSelected, false); + _SelectNextItem(fSelected, false); break; case B_RIGHT_ARROW: if (fLayout == B_ITEMS_IN_ROW) - SelectNextItem(fSelected, true); + _SelectNextItem(fSelected, true); break; case B_ENTER: case B_SPACE: if (fSelected) InvokeItem(fSelected); - break; - + case B_ESCAPE: QuitTracking(); break; default: - BView::KeyDown(bytes, numBytes); + { + 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; + } } } @@ -838,13 +869,13 @@ BMenu::KeyDown(const char *bytes, int32 numBytes) void BMenu::Draw(BRect updateRect) { - if (RelayoutIfNeeded()) { + if (_RelayoutIfNeeded()) { Invalidate(); return; } DrawBackground(updateRect); - DrawItems(updateRect); + _DrawItems(updateRect); } @@ -910,7 +941,7 @@ BMenu::DoLayout() return; } - if (RelayoutIfNeeded()) + if (_RelayoutIfNeeded()) Invalidate(); } @@ -1041,37 +1072,37 @@ BMenu::AllDetached() BMenu::BMenu(BRect frame, const char *name, uint32 resizingMode, uint32 flags, - menu_layout layout, bool resizeToFit) - : BView(frame, name, resizingMode, flags), - fChosenItem(NULL), - fSelected(NULL), - fCachedMenuWindow(NULL), - fSuper(NULL), - fSuperitem(NULL), - fAscent(-1.0f), - fDescent(-1.0f), - fFontHeight(-1.0f), - fState(0), - fLayout(layout), - fExtraRect(NULL), - fMaxContentWidth(0.0f), - fInitMatrixSize(NULL), - fExtraMenuData(NULL), - fSubmenus(0), - fTrigger(0), - fResizeToFit(resizeToFit), - fUseCachedMenuLayout(false), - fEnabled(true), - fDynamicName(false), - fRadioMode(false), - fTrackNewBounds(false), - fStickyMode(false), - fIgnoreHidden(true), - fTriggerEnabled(true), - fRedrawAfterSticky(false), - fAttachAborted(false) + menu_layout layout, bool resizeToFit) + : BView(frame, name, resizingMode, flags), + fChosenItem(NULL), + fSelected(NULL), + fCachedMenuWindow(NULL), + fSuper(NULL), + fSuperitem(NULL), + fAscent(-1.0f), + fDescent(-1.0f), + fFontHeight(-1.0f), + fState(0), + fLayout(layout), + fExtraRect(NULL), + fMaxContentWidth(0.0f), + fInitMatrixSize(NULL), + fExtraMenuData(NULL), + fSubmenus(0), + fTrigger(0), + fResizeToFit(resizeToFit), + fUseCachedMenuLayout(false), + fEnabled(true), + fDynamicName(false), + fRadioMode(false), + fTrackNewBounds(false), + fStickyMode(false), + fIgnoreHidden(true), + fTriggerEnabled(true), + fRedrawAfterSticky(false), + fAttachAborted(false) { - InitData(NULL); + _InitData(NULL); } @@ -1114,16 +1145,16 @@ BMenu::Show() void BMenu::Show(bool selectFirst) { - Install(NULL); - _show(selectFirst); + _Install(NULL); + _Show(selectFirst); } void BMenu::Hide() { - _hide(); - Uninstall(); + _Hide(); + _Uninstall(); } @@ -1131,7 +1162,8 @@ BMenuItem * BMenu::Track(bool sticky, BRect *clickToOpenRect) { if (sticky && LockLooper()) { - RedrawAfterSticky(Bounds()); + //RedrawAfterSticky(Bounds()); + // the call above didn't do anything, so I've removed it for now UnlockLooper(); } @@ -1142,9 +1174,9 @@ BMenu::Track(bool sticky, BRect *clickToOpenRect) } int action; - BMenuItem *menuItem = _track(&action); + BMenuItem *menuItem = _Track(&action); - SetStickyMode(false); + _SetStickyMode(false); fExtraRect = NULL; return menuItem; @@ -1152,7 +1184,7 @@ BMenu::Track(bool sticky, BRect *clickToOpenRect) bool -BMenu::AddDynamicItem(add_state s) +BMenu::AddDynamicItem(add_state state) { // Implemented in subclasses return false; @@ -1173,7 +1205,7 @@ void BMenu::SetTrackingHook(menu_tracking_hook func, void *state) { delete fExtraMenuData; - fExtraMenuData = new (nothrow) _ExtraMenuData_(func, state); + fExtraMenuData = new (nothrow) BPrivate::ExtraMenuData(func, state); } @@ -1191,7 +1223,7 @@ BMenu::operator=(const BMenu &) void -BMenu::InitData(BMessage *data) +BMenu::_InitData(BMessage* archive) { // TODO: Get _color, _fname, _fflt from the message, if present BFont font; @@ -1206,29 +1238,29 @@ BMenu::InitData(BMessage *data) fTriggerEnabled = sMenuInfo.triggers_always_shown; - if (data != NULL) { - data->FindInt32("_layout", (int32 *)&fLayout); - data->FindBool("_rsize_to_fit", &fResizeToFit); + if (archive != NULL) { + archive->FindInt32("_layout", (int32 *)&fLayout); + archive->FindBool("_rsize_to_fit", &fResizeToFit); bool disabled; - if (data->FindBool("_disable", &disabled) == B_OK) + if (archive->FindBool("_disable", &disabled) == B_OK) fEnabled = !disabled; - data->FindBool("_radio", &fRadioMode); - + archive->FindBool("_radio", &fRadioMode); + bool disableTrigger = false; - data->FindBool("_trig_disabled", &disableTrigger); + archive->FindBool("_trig_disabled", &disableTrigger); fTriggerEnabled = !disableTrigger; - - data->FindBool("_dyn_label", &fDynamicName); - data->FindFloat("_maxwidth", &fMaxContentWidth); + + archive->FindBool("_dyn_label", &fDynamicName); + archive->FindFloat("_maxwidth", &fMaxContentWidth); BMessage msg; - for (int32 i = 0; data->FindMessage("_items", i, &msg) == B_OK; i++) { + for (int32 i = 0; archive->FindMessage("_items", i, &msg) == B_OK; i++) { BArchivable *object = instantiate_object(&msg); if (BMenuItem *item = dynamic_cast(object)) { BRect bounds; - if ((fLayout == B_ITEMS_IN_MATRIX) - && (data->FindRect("_i_frames", i, &bounds) == B_OK)) - AddItem(item, bounds); + if (fLayout == B_ITEMS_IN_MATRIX + && archive->FindRect("_i_frames", i, &bounds) == B_OK) + AddItem(item, bounds); else AddItem(item); } @@ -1238,7 +1270,7 @@ BMenu::InitData(BMessage *data) bool -BMenu::_show(bool selectFirstItem) +BMenu::_Show(bool selectFirstItem) { // See if the supermenu has a cached menuwindow, // and use that one if possible. @@ -1246,7 +1278,7 @@ BMenu::_show(bool selectFirstItem) bool ourWindow = false; if (fSuper != NULL) { fSuperbounds = fSuper->ConvertToScreen(fSuper->Bounds()); - window = fSuper->MenuWindow(); + window = fSuper->_MenuWindow(); } // Otherwise, create a new one @@ -1260,11 +1292,11 @@ BMenu::_show(bool selectFirstItem) if (window == NULL) return false; - + if (window->Lock()) { fAttachAborted = false; window->AttachMenu(this); - + // Menu didn't have the time to add its items: aborting... if (fAttachAborted) { window->DetachMenu(); @@ -1275,28 +1307,28 @@ BMenu::_show(bool selectFirstItem) window->Unlock(); return false; } - + // Move the BMenu to 1, 1, if it's attached to a BMenuWindow, // (that means it's a BMenu, BMenuBars are attached to regular BWindows). // This is needed to be able to draw the frame around the BMenu. if (dynamic_cast(window) != NULL) MoveTo(1, 1); - - UpdateWindowViewSize(true); + + _UpdateWindowViewSize(true); window->Show(); - + if (selectFirstItem) _SelectItem(ItemAt(0)); - + window->Unlock(); } - + return true; } void -BMenu::_hide() +BMenu::_Hide() { BMenuWindow *window = static_cast(Window()); if (window == NULL || !window->Lock()) @@ -1310,7 +1342,7 @@ BMenu::_hide() // we don't want to be deleted when the window is removed // Delete the menu window used by our submenus - DeleteMenuWindow(); + _DeleteMenuWindow(); if (fSuper != NULL) window->Unlock(); @@ -1325,7 +1357,7 @@ const bigtime_t kHysteresis = 200000; // TODO: Test and reduce if needed. BMenuItem * -BMenu::_track(int *action, long start) +BMenu::_Track(int *action, long start) { // TODO: cleanup BMenuItem *item = NULL; @@ -1337,7 +1369,7 @@ BMenu::_track(int *action, long start) fSuper->fState = MENU_STATE_TRACKING_SUBMENU; while (true) { - if (CustomTrackingWantsToQuit()) + if (_CustomTrackingWantsToQuit()) break; bool locked = LockLooper(); @@ -1346,7 +1378,7 @@ BMenu::_track(int *action, long start) bigtime_t snoozeAmount = 50000; BPoint location; - ulong buttons; + uint32 buttons; GetMouse(&location, &buttons, true); BMenuWindow *window = static_cast(Window()); @@ -1355,46 +1387,45 @@ BMenu::_track(int *action, long start) if (window->CheckForScrolling(screenLocation)) { item = NULL; } else { - item = HitTestItems(location, B_ORIGIN); + item = _HitTestItems(location, B_ORIGIN); if (item != NULL) _UpdateStateOpenSelect(item, openTime, closeTime); } // Track the submenu - if (OverSubmenu(fSelected, screenLocation)) { + if (_OverSubmenu(fSelected, screenLocation)) { UnlockLooper(); locked = false; int submenuAction = MENU_STATE_TRACKING; BMenu *submenu = fSelected->Submenu(); - bool wasSticky = IsStickyMode(); + bool wasSticky = _IsStickyMode(); if (wasSticky) - submenu->SetStickyMode(true); - BMenuItem *submenuItem = submenu->_track(&submenuAction); - + submenu->_SetStickyMode(true); + BMenuItem *submenuItem = submenu->_Track(&submenuAction); + // check if the user started holding down a mouse button in a submenu - if (wasSticky && !IsStickyMode()) { + if (wasSticky && !_IsStickyMode()) { buttons = 1; // buttons must have been pressed in the meantime } - + if (submenuAction == MENU_STATE_CLOSED) { item = submenuItem; fState = submenuAction; break; } - + locked = LockLooper(); if (!locked) break; - } else if (item == NULL) { - if (OverSuper(screenLocation)) { + if (_OverSuper(screenLocation)) { fState = MENU_STATE_TRACKING; UnlockLooper(); break; } - if (!OverSubmenu(fSelected, screenLocation) + if (!_OverSubmenu(fSelected, screenLocation) && system_time() > closeTime + kHysteresis && fState != MENU_STATE_TRACKING_SUBMENU) { _SelectItem(NULL); @@ -1406,14 +1437,14 @@ BMenu::_track(int *action, long start) *action = fState; if (locked) UnlockLooper(); - + return NULL; } } - + if (locked) UnlockLooper(); - + _UpdateStateClose(item, location, buttons); if (fState == MENU_STATE_CLOSED) @@ -1430,18 +1461,19 @@ BMenu::_track(int *action, long start) UnlockLooper(); } - if (IsStickyMode()) - SetStickyMode(false); - + if (_IsStickyMode()) + _SetStickyMode(false); + // delete the menu window recycled for all the child menus - DeleteMenuWindow(); - + _DeleteMenuWindow(); + return item; } void -BMenu::_UpdateStateOpenSelect(BMenuItem *item, bigtime_t &openTime, bigtime_t &closeTime) +BMenu::_UpdateStateOpenSelect(BMenuItem* item, bigtime_t& openTime, + bigtime_t& closeTime) { if (fState == MENU_STATE_CLOSED) return; @@ -1463,23 +1495,24 @@ BMenu::_UpdateStateOpenSelect(BMenuItem *item, bigtime_t &openTime, bigtime_t &c void -BMenu::_UpdateStateClose(BMenuItem *item, const BPoint &where, const uint32 &buttons) +BMenu::_UpdateStateClose(BMenuItem* item, const BPoint& where, + const uint32& buttons) { if (fState == MENU_STATE_CLOSED) return; - if (buttons != 0 && IsStickyMode()) { + if (buttons != 0 && _IsStickyMode()) { if (item == NULL) fState = MENU_STATE_CLOSED; else { BMenu *supermenu = Supermenu(); for(; supermenu; supermenu = supermenu->Supermenu()) - supermenu->SetStickyMode(false); - SetStickyMode(false); + supermenu->_SetStickyMode(false); + _SetStickyMode(false); } - } else if (buttons == 0 && !IsStickyMode()) { + } else if (buttons == 0 && !_IsStickyMode()) { if (fExtraRect != NULL && fExtraRect->Contains(where)) { - SetStickyMode(true); + _SetStickyMode(true); fExtraRect = NULL; // This code should be executed only once } else @@ -1494,10 +1527,10 @@ BMenu::_AddItem(BMenuItem *item, int32 index) ASSERT(item != NULL); if (index < 0 || index > fItems.CountItems()) return false; - + if (!fItems.AddItem(item, index)) return false; - + // install the item on the supermenu's window // or onto our window, if we are a root menu BWindow* window = NULL; @@ -1509,13 +1542,12 @@ BMenu::_AddItem(BMenuItem *item, int32 index) item->Install(window); item->SetSuper(this); - return true; } 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; @@ -1566,8 +1598,8 @@ BMenu::RemoveItems(int32 index, int32 count, BMenuItem *item, bool deleteItems) if (invalidateLayout) { InvalidateLayout(); if (locked && window != NULL) { - LayoutItems(0); - UpdateWindowViewSize(false); + _LayoutItems(0); + _UpdateWindowViewSize(false); Invalidate(); } } @@ -1580,12 +1612,12 @@ BMenu::RemoveItems(int32 index, int32 count, BMenuItem *item, bool deleteItems) bool -BMenu::RelayoutIfNeeded() +BMenu::_RelayoutIfNeeded() { if (!fUseCachedMenuLayout) { fUseCachedMenuLayout = true; - CacheFontInfo(); - LayoutItems(0); + _CacheFontInfo(); + _LayoutItems(0); return true; } return false; @@ -1593,12 +1625,12 @@ BMenu::RelayoutIfNeeded() void -BMenu::LayoutItems(int32 index) +BMenu::_LayoutItems(int32 index) { - CalcTriggers(); + _CalcTriggers(); float width, height; - ComputeLayout(index, fResizeToFit, true, &width, &height); + _ComputeLayout(index, fResizeToFit, true, &width, &height); if (fResizeToFit) ResizeTo(width, height); @@ -1609,14 +1641,14 @@ BSize BMenu::_ValidatePreferredSize() { if (!fLayoutData->preferred.IsWidthSet()) - ComputeLayout(0, true, false, NULL, NULL); + _ComputeLayout(0, true, false, NULL, NULL); return fLayoutData->preferred; } void -BMenu::ComputeLayout(int32 index, bool bestFit, bool moveItems, +BMenu::_ComputeLayout(int32 index, bool bestFit, bool moveItems, float* _width, float* _height) { // TODO: Take "bestFit", "moveItems", "index" into account, @@ -1670,7 +1702,8 @@ BMenu::ComputeLayout(int32 index, bool bestFit, bool moveItems, void -BMenu::_ComputeColumnLayout(int32 index, bool bestFit, bool moveItems, BRect &frame) +BMenu::_ComputeColumnLayout(int32 index, bool bestFit, bool moveItems, + BRect& frame) { BFont font; GetFont(&font); @@ -1695,7 +1728,8 @@ BMenu::_ComputeColumnLayout(int32 index, bool bestFit, bool moveItems, BRect &fr item->fBounds.left = 0.0f; item->fBounds.top = frame.bottom; - item->fBounds.bottom = item->fBounds.top + iHeight + fPad.top + fPad.bottom; + item->fBounds.bottom = item->fBounds.top + iHeight + fPad.top + + fPad.bottom; if (fSubmenus) iWidth += item->Frame().Height(); @@ -1725,11 +1759,13 @@ BMenu::_ComputeColumnLayout(int32 index, bool bestFit, bool moveItems, BRect &fr void -BMenu::_ComputeRowLayout(int32 index, bool bestFit, bool moveItems, BRect &frame) +BMenu::_ComputeRowLayout(int32 index, bool bestFit, bool moveItems, + BRect& frame) { font_height fh; GetFontHeight(&fh); - frame = BRect(0.0f, 0.0f, 0.0f, ceilf(fh.ascent + fh.descent + fPad.top + fPad.bottom)); + frame = BRect(0.0f, 0.0f, 0.0f, ceilf(fh.ascent + fh.descent + fPad.top + + fPad.bottom)); for (int32 i = 0; i < fItems.CountItems(); i++) { BMenuItem *item = ItemAt(i); @@ -1739,18 +1775,19 @@ BMenu::_ComputeRowLayout(int32 index, bool bestFit, bool moveItems, BRect &frame item->fBounds.left = frame.right; item->fBounds.top = 0.0f; - item->fBounds.right = item->fBounds.left + iWidth + fPad.left + fPad.right; + item->fBounds.right = item->fBounds.left + iWidth + fPad.left + + fPad.right; frame.right = item->Frame().right + 1.0f; frame.bottom = max_c(frame.bottom, iHeight + fPad.top + fPad.bottom); } } - + if (moveItems) { for (int32 i = 0; i < fItems.CountItems(); i++) ItemAt(i)->fBounds.bottom = frame.bottom; } - + if (bestFit) frame.right = ceilf(frame.right); else @@ -1773,22 +1810,6 @@ BMenu::_ComputeMatrixLayout(BRect &frame) } -BRect -BMenu::Bump(BRect current, BPoint extent, int32 index) const -{ - // ToDo: what's this? - return BRect(); -} - - -BPoint -BMenu::ItemLocInRect(BRect frame) const -{ - // ToDo: what's this? - return BPoint(); -} - - // Assumes the SuperMenu to be locked (due to calling ConvertToScreen()) BPoint BMenu::ScreenLocation() @@ -1814,7 +1835,7 @@ BMenu::ScreenLocation() BRect -BMenu::CalcFrame(BPoint where, bool *scrollOn) +BMenu::_CalcFrame(BPoint where, bool *scrollOn) { // TODO: Improve me BRect bounds = Bounds(); @@ -1880,21 +1901,8 @@ BMenu::CalcFrame(BPoint where, bool *scrollOn) } -bool -BMenu::ScrollMenu(BRect bounds, BPoint loc, bool *fast) -{ - return false; -} - - void -BMenu::ScrollIntoView(BMenuItem *item) -{ -} - - -void -BMenu::DrawItems(BRect updateRect) +BMenu::_DrawItems(BRect updateRect) { int32 itemCount = fItems.CountItems(); for (int32 i = 0; i < itemCount; i++) { @@ -1923,7 +1931,7 @@ BMenu::InvokeItem(BMenuItem *item, bool now) { if (!item->IsEnabled()) return; - + // Do the "selected" animation if (!item->Submenu() && LockLooper()) { snooze(50000); @@ -1940,13 +1948,13 @@ BMenu::InvokeItem(BMenuItem *item, bool now) Sync(); UnlockLooper(); } - + item->Invoke(); } bool -BMenu::OverSuper(BPoint location) +BMenu::_OverSuper(BPoint location) { if (!Supermenu()) return false; @@ -1956,7 +1964,7 @@ BMenu::OverSuper(BPoint location) bool -BMenu::OverSubmenu(BMenuItem *item, BPoint loc) +BMenu::_OverSubmenu(BMenuItem *item, BPoint loc) { if (item == NULL) return false; @@ -1964,17 +1972,17 @@ BMenu::OverSubmenu(BMenuItem *item, BPoint loc) BMenu *subMenu = item->Submenu(); if (subMenu == NULL || subMenu->Window() == NULL) return false; - + // we assume that loc is in screen coords if (subMenu->Window()->Frame().Contains(loc)) return true; - return subMenu->OverSubmenu(subMenu->fSelected, loc); + return subMenu->_OverSubmenu(subMenu->fSelected, loc); } BMenuWindow * -BMenu::MenuWindow() +BMenu::_MenuWindow() { if (fCachedMenuWindow == NULL) { char windowName[64]; @@ -1987,7 +1995,7 @@ BMenu::MenuWindow() void -BMenu::DeleteMenuWindow() +BMenu::_DeleteMenuWindow() { if (fCachedMenuWindow != NULL) { fCachedMenuWindow->Lock(); @@ -1998,15 +2006,15 @@ BMenu::DeleteMenuWindow() BMenuItem * -BMenu::HitTestItems(BPoint where, BPoint slop) const +BMenu::_HitTestItems(BPoint where, BPoint slop) const { // TODO: Take "slop" into account ? - + // if the point doesn't lie within the menu's // bounds, bail out immediately if (!Bounds().Contains(where)) return NULL; - + int32 itemCount = CountItems(); for (int32 i = 0; i < itemCount; i++) { BMenuItem *item = ItemAt(i); @@ -2019,14 +2027,14 @@ BMenu::HitTestItems(BPoint where, BPoint slop) const BRect -BMenu::Superbounds() const +BMenu::_Superbounds() const { return fSuperbounds; } void -BMenu::CacheFontInfo() +BMenu::_CacheFontInfo() { font_height fh; GetFontHeight(&fh); @@ -2037,22 +2045,23 @@ BMenu::CacheFontInfo() void -BMenu::ItemMarked(BMenuItem *item) +BMenu::_ItemMarked(BMenuItem *item) { if (IsRadioMode()) { - for (int32 i = 0; i < CountItems(); i++) - if (ItemAt(i) != item) + for (int32 i = 0; i < CountItems(); i++) { + if (ItemAt(i) != item) ItemAt(i)->SetMarked(false); + } InvalidateLayout(); } - + if (IsLabelFromMarked() && Superitem()) Superitem()->SetLabel(item->Label()); } void -BMenu::Install(BWindow *target) +BMenu::_Install(BWindow *target) { for (int32 i = 0; i < CountItems(); i++) ItemAt(i)->Install(target); @@ -2060,7 +2069,7 @@ BMenu::Install(BWindow *target) void -BMenu::Uninstall() +BMenu::_Uninstall() { for (int32 i = 0; i < CountItems(); i++) ItemAt(i)->Uninstall(); @@ -2077,18 +2086,18 @@ BMenu::_SelectItem(BMenuItem* menuItem, bool showSubmenu, bool selectFirstItem) fSelected->Select(false); BMenu *subMenu = fSelected->Submenu(); if (subMenu != NULL && subMenu->Window() != NULL) - subMenu->_hide(); + subMenu->_Hide(); } - + fSelected = menuItem; if (fSelected != NULL) fSelected->Select(true); } - + if (fSelected != NULL && showSubmenu) { BMenu *subMenu = fSelected->Submenu(); if (subMenu != NULL && subMenu->Window() == NULL) { - if (!subMenu->_show(selectFirstItem)) { + if (!subMenu->_Show(selectFirstItem)) { // something went wrong, deselect the item fSelected->Select(false); fSelected = NULL; @@ -2098,33 +2107,26 @@ BMenu::_SelectItem(BMenuItem* menuItem, bool showSubmenu, bool selectFirstItem) } -BMenuItem * -BMenu::CurrentSelection() const -{ - return fSelected; -} - - bool -BMenu::SelectNextItem(BMenuItem *item, bool forward) +BMenu::_SelectNextItem(BMenuItem *item, bool forward) { - BMenuItem *nextItem = NextItem(item, forward); + BMenuItem *nextItem = _NextItem(item, forward); if (nextItem == NULL) return false; - + _SelectItem(nextItem); return true; } BMenuItem * -BMenu::NextItem(BMenuItem *item, bool forward) const +BMenu::_NextItem(BMenuItem *item, bool forward) const { if (item == NULL) { if (forward) return ItemAt(CountItems() - 1); - else - return ItemAt(0); + + return ItemAt(0); } int32 index = fItems.IndexOf(item); @@ -2132,35 +2134,23 @@ BMenu::NextItem(BMenuItem *item, bool forward) const index++; else index--; - + if (index < 0 || index >= fItems.CountItems()) return NULL; - return ItemAt(index); -} - - -bool -BMenu::IsItemVisible(BMenuItem *item) const -{ - BRect itemFrame = item->Frame(); - ConvertToScreen(&itemFrame); - - BRect visibilityFrame = Window()->Frame() & BScreen(Window()).Frame(); - - return visibilityFrame.Intersects(itemFrame); + return ItemAt(index); } void -BMenu::SetIgnoreHidden(bool on) +BMenu::_SetIgnoreHidden(bool on) { fIgnoreHidden = on; } void -BMenu::SetStickyMode(bool on) +BMenu::_SetStickyMode(bool on) { if (fStickyMode != on) { // TODO: Ugly hack, but it needs to be done right here in this method @@ -2178,70 +2168,82 @@ BMenu::SetStickyMode(bool on) // If we are switching to sticky mode, propagate the status // back to the super menu if (on && fSuper != NULL) - fSuper->SetStickyMode(on); + fSuper->_SetStickyMode(on); } bool -BMenu::IsStickyMode() const +BMenu::_IsStickyMode() const { return fStickyMode; } void -BMenu::CalcTriggers() +BMenu::_CalcTriggers() { - BList triggersList; - - // Gathers the existing triggers - // TODO: Oh great, reinterpret_cast. + BPrivate::TriggerList triggerList; + + // Gathers the existing triggers set by the user for (int32 i = 0; i < CountItems(); i++) { char trigger = ItemAt(i)->Trigger(); if (trigger != 0) - triggersList.AddItem(reinterpret_cast((uint32)trigger)); + triggerList.AddTrigger(trigger); } // Set triggers for items which don't have one yet for (int32 i = 0; i < CountItems(); i++) { BMenuItem *item = ItemAt(i); if (item->Trigger() == 0) { - const char *newTrigger = ChooseTrigger(item->Label(), &triggersList); - if (newTrigger != NULL) - item->SetAutomaticTrigger(*newTrigger); + uint32 trigger; + int32 index; + if (_ChooseTrigger(item->Label(), index, trigger, triggerList)) + item->SetAutomaticTrigger(index, trigger); } } } -const char * -BMenu::ChooseTrigger(const char *title, BList *chars) +bool +BMenu::_ChooseTrigger(const char *title, int32& index, uint32& trigger, + BPrivate::TriggerList& triggers) { - ASSERT(chars != NULL); - if (title == NULL) - return NULL; + return false; - char trigger; - // TODO: Oh great, reinterpret_cast all around - while ((trigger = title[0]) != '\0') { - if (isalpha(trigger) - && !chars->HasItem(reinterpret_cast((uint32)trigger))) { - chars->AddItem(reinterpret_cast((uint32)trigger)); - return title; + uint32 c; + + // two runs: first we look out for uppercase letters + // TODO: support Unicode characters correctly! + + for (uint32 i = 0; (c = title[i]) != '\0'; i++) { + if (!IsInsideGlyph(c) && isupper(c) && !triggers.HasTrigger(c)) { + index = i; + trigger = tolower(c); + return triggers.AddTrigger(c);; } - - title++; } - return NULL; + // then, if we still haven't found anything, we accept them all + + index = 0; + while ((c = UTF8ToCharCode(&title)) != 0) { + if (!isspace(c) && !triggers.HasTrigger(c)) { + trigger = tolower(c); + return triggers.AddTrigger(c);; + } + + index++; + } + + return false; } void -BMenu::UpdateWindowViewSize(bool upWind) +BMenu::_UpdateWindowViewSize(bool updatePosition) { - BWindow *window = Window(); + BMenuWindow *window = static_cast(Window()); if (window == NULL) return; @@ -2252,8 +2254,9 @@ BMenu::UpdateWindowViewSize(bool upWind) return; bool scroll; - const BPoint screenLocation = upWind ? ScreenLocation() : window->Frame().LeftTop(); - BRect frame = CalcFrame(screenLocation, &scroll); + const BPoint screenLocation = updatePosition ? ScreenLocation() + : window->Frame().LeftTop(); + BRect frame = _CalcFrame(screenLocation, &scroll); ResizeTo(frame.Width(), frame.Height()); if (fItems.CountItems() > 0) { @@ -2263,67 +2266,53 @@ BMenu::UpdateWindowViewSize(bool upWind) BScreen screen(window); // If we need scrolling, resize the window to fit the screen and - // attach scrollers to our cached MenuWindow. + // attach scrollers to our cached BMenuWindow. if (dynamic_cast(Supermenu()) == NULL) { window->ResizeTo(Bounds().Width() + 2, screen.Frame().bottom); frame.top = 0; } else { // Or, in case our parent was a BMenuBar enable scrolling with // normal size. - window->ResizeTo(Bounds().Width() + 2, screen.Frame().bottom - frame.top); + window->ResizeTo(Bounds().Width() + 2, screen.Frame().bottom + - frame.top); } - - static_cast(window)->AttachScrollers(); + + window->AttachScrollers(); } } else { - CacheFontInfo(); + _CacheFontInfo(); window->ResizeTo(StringWidth(kEmptyMenuLabel) + fPad.left + fPad.right, - fFontHeight + fPad.top + fPad.bottom); + fFontHeight + fPad.top + fPad.bottom); } - - if (upWind) + + if (updatePosition) window->MoveTo(frame.LeftTop()); } bool -BMenu::IsStickyPrefOn() +BMenu::_OkToProceed(BMenuItem* item) { - return true; -} - - -void -BMenu::RedrawAfterSticky(BRect bounds) -{ -} - - -bool -BMenu::OkToProceed(BMenuItem* item) -{ - bool proceed = true; BPoint where; ulong buttons; GetMouse(&where, &buttons, false); - bool stickyMode = IsStickyMode(); + bool stickyMode = _IsStickyMode(); // Quit if user clicks the mouse button in sticky mode // 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)) - proceed = false; - + || (dynamic_cast(this) == NULL + && (buttons == 0 && !stickyMode) || _HitTestItems(where) != item)) + return false; - return proceed; + return true; } bool -BMenu::CustomTrackingWantsToQuit() +BMenu::_CustomTrackingWantsToQuit() { if (fExtraMenuData != NULL && fExtraMenuData->trackingHook != NULL && fExtraMenuData->trackingState != NULL) { @@ -2346,70 +2335,7 @@ BMenu::QuitTracking() } -status_t -BMenu::ParseMsg(BMessage *msg, int32 *sindex, BMessage *spec, - int32 *form, const char **prop, BMenu **tmenu, - BMenuItem **titem, int32 *user_data, - BMessage *reply) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoMenuMsg(BMenuItem **next, BMenu *menu, BMessage *message, - BMessage *r, BMessage *spec, int32 f) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoMenuItemMsg(BMenuItem **next, BMenu *menu, BMessage *message, - BMessage *r, BMessage *spec, int32 f) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoEnabledMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoLabelMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoMarkMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoDeleteMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r) const -{ - return B_ERROR; -} - - -status_t -BMenu::DoCreateMsg(BMenuItem *ti, BMenu *tm, BMessage *m, - BMessage *r, bool menu) const -{ - return B_ERROR; -} +// #pragma mark - // TODO: Maybe the following two methods would fit better into InterfaceDefs.cpp diff --git a/src/kits/interface/MenuBar.cpp b/src/kits/interface/MenuBar.cpp index 033a0c1046..bc1d6a804e 100644 --- a/src/kits/interface/MenuBar.cpp +++ b/src/kits/interface/MenuBar.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2001-2006, Haiku, Inc. + * Copyright 2001-2007, Haiku, Inc. * Distributed under the terms of the MIT License. * * Authors: @@ -140,7 +140,7 @@ BMenuBar::Border() const void BMenuBar::Draw(BRect updateRect) { - if (RelayoutIfNeeded()) { + if (_RelayoutIfNeeded()) { Invalidate(); return; } @@ -169,14 +169,14 @@ BMenuBar::Draw(BRect updateRect) SetHighColor(color); // revert to previous used color (cheap PushState()/PopState()) - DrawItems(updateRect); + _DrawItems(updateRect); } void BMenuBar::AttachedToWindow() { - Install(Window()); + _Install(Window()); Window()->SetKeyMenuBar(this); BMenu::AttachedToWindow(); @@ -423,7 +423,7 @@ BMenuBar::TrackTask(void *arg) BMenuBar *menuBar = data.menuBar; if (data.useRect) menuBar->fExtraRect = &data.rect; - menuBar->SetStickyMode(data.sticky); + menuBar->_SetStickyMode(data.sticky); int32 action; menuBar->Track(&action, data.menuIndex, data.showMenu); @@ -481,24 +481,24 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) break; BPoint where; - ulong buttons; + uint32 buttons; GetMouse(&where, &buttons, true); - BMenuItem *menuItem = HitTestItems(where, B_ORIGIN); + BMenuItem *menuItem = _HitTestItems(where, B_ORIGIN); if (menuItem != NULL) { // Select item if: // - no previous selection // - nonsticky mode and different selection, // - clicked in sticky mode if (fSelected == NULL - || (!IsStickyMode() && menuItem != fSelected) - || (buttons != 0 && IsStickyMode())) { + || (!_IsStickyMode() && menuItem != fSelected) + || (buttons != 0 && _IsStickyMode())) { if (menuItem->Submenu() != NULL) { if (menuItem->Submenu()->Window() == NULL) { // open the menu if it's not opened yet _SelectItem(menuItem); - if (IsStickyMode()) - SetStickyMode(false); + if (_IsStickyMode()) + _SetStickyMode(false); } else { // Menu was already opened, close it and bail _SelectItem(NULL); @@ -512,25 +512,27 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) } } - if (OverSubmenu(fSelected, ConvertToScreen(where))) { - // call _track() from the selected sub-menu when the mouse cursor + if (_OverSubmenu(fSelected, ConvertToScreen(where))) { + // call _Track() from the selected sub-menu when the mouse cursor // is over its window BMenu *menu = fSelected->Submenu(); window->Unlock(); locked = false; snoozeAmount = 30000; - bool wasSticky = IsStickyMode(); + bool wasSticky = _IsStickyMode(); if (wasSticky) - menu->SetStickyMode(true); + menu->_SetStickyMode(true); int localAction; - fChosenItem = menu->_track(&localAction); - if (menu->State(NULL) == MENU_STATE_TRACKING && menu->IsStickyMode()) - menu->SetStickyMode(false); + fChosenItem = menu->_Track(&localAction); + if (menu->State(NULL) == MENU_STATE_TRACKING + && menu->_IsStickyMode()) + menu->_SetStickyMode(false); // check if the user started holding down a mouse button in a submenu - if (wasSticky && !IsStickyMode()) + if (wasSticky && !_IsStickyMode()) { buttons = 1; // buttons must have been pressed in the meantime + } // This code is needed to make menus // that are children of BMenuFields "sticky" (see ticket #953) @@ -541,7 +543,7 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) // TODO: Maybe have a shared struct between all menus // where to store the current mouse position ? BPoint newWhere; - ulong newButtons; + uint32 newButtons; if (window->Lock()) { GetMouse(&newWhere, &newButtons); window->Unlock(); @@ -550,50 +552,50 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) if (fExtraRect != NULL && fExtraRect->Contains(where) // 9 = 3 pixels ^ 2 (since point_distance() returns the square of the distance) && point_distance(newWhere, where) < 9) { - SetStickyMode(true); + _SetStickyMode(true); fExtraRect = NULL; } else fState = MENU_STATE_CLOSED; } - } else if (menuItem == NULL && fSelected != NULL - && !IsStickyMode() && fState != MENU_STATE_TRACKING_SUBMENU) { + && !_IsStickyMode() && fState != MENU_STATE_TRACKING_SUBMENU) { _SelectItem(NULL); fState = MENU_STATE_TRACKING; } - + if (locked) window->Unlock(); if (fState == MENU_STATE_CLOSED - || (buttons != 0 && IsStickyMode() && menuItem == NULL)) + || (buttons != 0 && _IsStickyMode() && menuItem == NULL)) break; - else if (buttons == 0 && !IsStickyMode()) { - if ((fSelected != NULL && fSelected->Submenu() == NULL) || menuItem == NULL) { + else if (buttons == 0 && !_IsStickyMode()) { + if ((fSelected != NULL && fSelected->Submenu() == NULL) + || menuItem == NULL) { fChosenItem = fSelected; break; } else - SetStickyMode(true); + _SetStickyMode(true); } if (snoozeAmount > 0) snooze(snoozeAmount); } - + if (window->Lock()) { if (fSelected != NULL) _SelectItem(NULL); - + if (fChosenItem != NULL) fChosenItem->Invoke(); RestoreFocus(); window->Unlock(); } - if (IsStickyMode()) - SetStickyMode(false); + if (_IsStickyMode()) + _SetStickyMode(false); - DeleteMenuWindow(); + _DeleteMenuWindow(); if (action != NULL) *action = fState; @@ -602,13 +604,13 @@ BMenuBar::Track(int32 *action, int32 startIndex, bool showMenu) } -void +void BMenuBar::StealFocus() { // We already stole the focus, don't do anything if (fPrevFocusToken != -1) return; - + BWindow *window = Window(); if (window != NULL && window->Lock()) { BView *focus = window->CurrentFocus(); @@ -646,5 +648,5 @@ BMenuBar::InitData(menu_layout layout) { fLastBounds = new BRect(Bounds()); SetItemMargins(8, 2, 8, 2); - SetIgnoreHidden(true); + _SetIgnoreHidden(true); } diff --git a/src/kits/interface/MenuItem.cpp b/src/kits/interface/MenuItem.cpp index 83dc321110..6c286b5d93 100644 --- a/src/kits/interface/MenuItem.cpp +++ b/src/kits/interface/MenuItem.cpp @@ -11,14 +11,17 @@ //! Display item for BMenu class +#include +#include +#include + #include #include #include #include #include -#include -#include +#include "utf8_functions.h" const unsigned char kCtrlBits[] = { 0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x1d,0x14, @@ -112,13 +115,9 @@ BMenuItem::BMenuItem(BMessage *data) if (data->FindBool("_marked", &marked) == B_OK) SetMarked(marked); - if (data->HasInt32("_user_trig")) { - int32 user_trig; - - data->FindInt32("_user_trig", &user_trig); - - SetTrigger(user_trig); - } + int32 userTrigger; + if (data->FindInt32("_user_trig", &userTrigger) == B_OK) + SetTrigger(userTrigger); if (data->HasInt32("_shortcut")) { int32 shortcut, mods; @@ -139,10 +138,8 @@ BMenuItem::BMenuItem(BMessage *data) BMessage subMessage; if (data->FindMessage("_submenu", &subMessage) == B_OK) { BArchivable *object = instantiate_object(&subMessage); - if (object != NULL) { BMenu *menu = dynamic_cast(object); - if (menu != NULL) _InitMenuData(menu); } @@ -251,7 +248,7 @@ BMenuItem::SetMarked(bool state) fMark = state; if (state && Menu() != NULL) - Menu()->ItemMarked(this); + Menu()->_ItemMarked(this); } @@ -260,12 +257,18 @@ BMenuItem::SetTrigger(char trigger) { fUserTrigger = trigger; - const char* pos = strchr(Label(), trigger); + // try uppercase letters first + + const char* pos = strchr(Label(), toupper(trigger)); + if (pos == NULL) { + // take lowercase, too + pos = strchr(Label(), trigger); + } if (pos != NULL) { - fAutomaticTrigger = trigger; fTriggerIndex = pos - Label(); + fTrigger = tolower(UTF8ToCharCode(&pos)); } else { - fAutomaticTrigger = 0; + fTrigger = 0; fTriggerIndex = -1; } @@ -369,10 +372,10 @@ BMenuItem::Frame() const void BMenuItem::GetContentSize(float *width, float *height) { - fSuper->CacheFontInfo(); - + fSuper->_CacheFontInfo(); + fCachedWidth = fSuper->StringWidth(fLabel); - + if (width) *width = (float)ceil(fCachedWidth); if (height) @@ -385,9 +388,9 @@ BMenuItem::TruncateLabel(float maxWidth, char *newLabel) { BFont font; BString string(fLabel); - + font.TruncateString(&string, B_TRUNCATE_MIDDLE, maxWidth); - + string.CopyInto(newLabel, 0, string.Length()); newLabel[string.Length()] = '\0'; } @@ -396,14 +399,14 @@ BMenuItem::TruncateLabel(float maxWidth, char *newLabel) void BMenuItem::DrawContent() { - fSuper->CacheFontInfo(); + fSuper->_CacheFontInfo(); fSuper->MovePenBy(0, fSuper->fAscent); BPoint lineStart = fSuper->PenLocation(); float labelWidth, labelHeight; GetContentSize(&labelWidth, &labelHeight); - + // truncate if needed // TODO: Actually, this is still never triggered if (fBounds.Width() > labelWidth) @@ -414,12 +417,12 @@ BMenuItem::DrawContent() fSuper->DrawString(truncatedLabel); delete[] truncatedLabel; } - + if (fSuper->AreTriggersEnabled() && fTriggerIndex != -1) { float escapements[fTriggerIndex + 1]; BFont font; fSuper->GetFont(&font); - + font.GetEscapements(fLabel, fTriggerIndex + 1, escapements); for (int32 i = 0; i < fTriggerIndex; i++) @@ -427,10 +430,10 @@ BMenuItem::DrawContent() lineStart.x--; lineStart.y++; - + BPoint lineEnd(lineStart); lineEnd.x += escapements[fTriggerIndex] * font.Size(); - + fSuper->StrokeLine(lineStart, lineEnd); } } @@ -462,8 +465,7 @@ BMenuItem::Draw() if (enabled) fSuper->SetHighColor(ui_color(B_MENU_ITEM_TEXT_COLOR)); else - fSuper->SetHighColor(tint_color(bgColor, - B_DISABLED_LABEL_TINT)); + fSuper->SetHighColor(tint_color(bgColor, B_DISABLED_LABEL_TINT)); // draw content fSuper->MovePenTo(ContentLocation()); @@ -536,7 +538,7 @@ BMenuItem::_InitData() fCachedWidth = 0; fTriggerIndex = -1; fUserTrigger = 0; - fAutomaticTrigger = 0; + fTrigger = 0; fShortcutChar = 0; fMark = false; fEnabled = true; @@ -563,7 +565,7 @@ void BMenuItem::Install(BWindow *window) { if (fSubmenu) - fSubmenu->Install(window); + fSubmenu->_Install(window); fWindow = window; @@ -592,7 +594,7 @@ BMenuItem::Invoke(BMessage *message) if (!message && !notify) message = Message(); - + if (!message) { if (!fSuper->IsWatched()) return err; @@ -603,7 +605,7 @@ BMenuItem::Invoke(BMessage *message) clone.AddInt64("when", (int64)system_time()); clone.AddPointer("source", this); clone.AddMessenger("be:sender", BMessenger(fSuper)); - + if (message) err = BInvoker::Invoke(&clone); @@ -618,12 +620,13 @@ void BMenuItem::Uninstall() { if (fSubmenu != NULL) - fSubmenu->Uninstall(); + fSubmenu->_Uninstall(); if (Target() == fWindow) SetTarget(BMessenger()); - if (fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) && fWindow != NULL) + if (fShortcutChar != 0 && (fModifiers & B_COMMAND_KEY) != 0 + && fWindow != NULL) fWindow->RemoveShortcut(fShortcutChar, fModifiers); fWindow = NULL; @@ -643,7 +646,7 @@ BMenuItem::SetSuper(BMenu *super) fSuper->fSubmenus--; fSubmenu->fSuper = super; } - + fSuper = super; } @@ -841,13 +844,8 @@ BMenuItem::_DrawControlChar(char shortcut, BPoint where) void -BMenuItem::SetAutomaticTrigger(char trigger) +BMenuItem::SetAutomaticTrigger(int32 index, uint32 trigger) { - fAutomaticTrigger = trigger; - - const char* pos = strchr(Label(), trigger); - if (pos != NULL) - fTriggerIndex = pos - Label(); - else - fTriggerIndex = -1; + fTriggerIndex = index; + fTrigger = trigger; }