/* * Copyright 2007-2013 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. */ #ifndef _MENU_H #define _MENU_H #include #include #include class BMenu; class BMenuBar; class BMenuItem; namespace BPrivate { class BMenuWindow; class ExtraMenuData; class TriggerList; class MenuPrivate; } enum menu_layout { B_ITEMS_IN_ROW = 0, B_ITEMS_IN_COLUMN, B_ITEMS_IN_MATRIX }; struct menu_info { float font_size; font_family f_family; font_style f_style; rgb_color background_color; int32 separator; bool click_to_open; bool triggers_always_shown; }; status_t get_menu_info(menu_info* info); status_t set_menu_info(menu_info* info); typedef bool (*menu_tracking_hook)(BMenu* menu, void* state); class BMenu : public BView { public: BMenu(const char* name, menu_layout layout = B_ITEMS_IN_COLUMN); BMenu(const char* name, float width, float height); BMenu(BMessage* archive); virtual ~BMenu(); static BArchivable* Instantiate(BMessage* archive); virtual status_t Archive(BMessage* archive, bool deep = true) const; virtual void AttachedToWindow(); virtual void DetachedFromWindow(); virtual void AllAttached(); virtual void AllDetached(); virtual void Draw(BRect updateRect); virtual void MessageReceived(BMessage* message); virtual void KeyDown(const char* bytes, int32 numBytes); 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 where); virtual void FrameResized(float width, float height); void InvalidateLayout(); virtual void MakeFocus(bool focus = true); 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 deleteItems = false); bool RemoveItem(BMenu* menu); 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 status_t SetTargetForItems(BHandler* target); virtual status_t SetTargetForItems(BMessenger messenger); virtual void SetEnabled(bool enable); virtual void SetRadioMode(bool on); virtual void SetTriggersEnabled(bool enable); virtual void SetMaxContentWidth(float maxWidth); void SetLabelFromMarked(bool on); bool IsLabelFromMarked(); bool IsEnabled() const; bool IsRadioMode() const; bool AreTriggersEnabled() const; bool IsRedrawAfterSticky() const; float MaxContentWidth() const; BMenuItem* FindMarked(); int32 FindMarkedIndex(); 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); virtual void LayoutInvalidated(bool descendants); virtual BPoint ScreenLocation(); 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; virtual void Show(); void Show(bool selectFirstItem); void Hide(); BMenuItem* Track(bool startOpened = false, BRect* specialRect = NULL); public: enum add_state { B_INITIAL_ADD, B_PROCESSING, B_ABORT }; virtual bool AddDynamicItem(add_state state); virtual void DrawBackground(BRect updateRect); void SetTrackingHook(menu_tracking_hook hook, void* state); // Reorder items void SortItems(int (*compare)(const BMenuItem*, const BMenuItem*)); bool SwapItems(int32 indexA, int32 indexB); bool MoveItem(int32 indexFrom, int32 indexTo); private: friend class BMenuBar; friend class BSeparatorItem; friend class BPrivate::MenuPrivate; 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; virtual void _ReservedMenu3(); virtual void _ReservedMenu4(); virtual void _ReservedMenu5(); virtual void _ReservedMenu6(); BMenu& operator=(const BMenu& other); void _InitData(BMessage* archive); bool _Show(bool selectFirstItem = false, bool keyDown = false); void _Hide(); BMenuItem* _Track(int* action, long start = -1); void _ScriptReceived(BMessage* message); void _ItemScriptReceived(BMessage* message, BMenuItem* item); status_t _ResolveItemSpecifier(const BMessage& specifier, int32 what, BMenuItem*& item, int32 *index = NULL); status_t _InsertItemAtSpecifier( const BMessage& specifier, int32 what, BMenuItem* item); 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); 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* override, BRect& outRect); void _ComputeRowLayout(int32 index, bool bestFit, bool moveItems, BRect& outRect); void _ComputeMatrixLayout(BRect& outRect); BRect _CalcFrame(BPoint where, bool* scrollOn); protected: void DrawItems(BRect updateRect); private: 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 _ItemMarked(BMenuItem* item); void _Install(BWindow* target); void _Uninstall(); void _SelectItem(BMenuItem* item, bool showSubmenu = true, bool selectFirstItem = false, bool keyDown = false); bool _SelectNextItem(BMenuItem* item, bool forward); BMenuItem* _NextItem(BMenuItem* item, bool forward) const; void _SetIgnoreHidden(bool ignoreHidden) { fIgnoreHidden = ignoreHidden; } void _SetStickyMode(bool on); bool _IsStickyMode() const; // Methods to get the current modifier keycode void _GetShiftKey(uint32 &value) const; void _GetControlKey(uint32 &value) const; void _GetCommandKey(uint32 &value) const; void _GetOptionKey(uint32 &value) const; void _GetMenuKey(uint32 &value) const; void _CalcTriggers(); bool _ChooseTrigger(const char* title, int32& index, uint32& trigger, BPrivate::TriggerList& triggers); void _UpdateWindowViewSize(const bool &updatePosition); bool _AddDynamicItems(bool keyDown = false); bool _OkToProceed(BMenuItem* item, bool keyDown = false); bool _CustomTrackingWantsToQuit(); int _State(BMenuItem** _item = NULL) const; void _InvokeItem(BMenuItem* item, bool now = false); void _QuitTracking(bool onlyThis = true); static menu_info sMenuInfo; // Variables to keep track of what code is currently assigned to // each modifier key static uint32 sShiftKey; static uint32 sControlKey; static uint32 sOptionKey; static uint32 sCommandKey; static uint32 sMenuKey; 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; LayoutData* fLayoutData; int32 _reserved; char fTrigger; bool fResizeToFit; bool fUseCachedMenuLayout; bool fEnabled; bool fDynamicName; bool fRadioMode; bool fTrackNewBounds; bool fStickyMode; bool fIgnoreHidden; bool fTriggerEnabled; bool fHasSubmenus; bool fAttachAborted; }; #endif // _MENU_H