1 /* 2 * Copyright 2007-2013 Haiku, Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef _MENU_H 6 #define _MENU_H 7 8 9 #include <InterfaceDefs.h> 10 #include <List.h> 11 #include <View.h> 12 13 14 class BMenu; 15 class BMenuBar; 16 class BMenuItem; 17 18 19 namespace BPrivate { 20 class BMenuWindow; 21 class ExtraMenuData; 22 class TriggerList; 23 class MenuPrivate; 24 } 25 26 enum menu_layout { 27 B_ITEMS_IN_ROW = 0, 28 B_ITEMS_IN_COLUMN, 29 B_ITEMS_IN_MATRIX 30 }; 31 32 struct menu_info { 33 float font_size; 34 font_family f_family; 35 font_style f_style; 36 rgb_color background_color; 37 int32 separator; 38 bool click_to_open; 39 bool triggers_always_shown; 40 }; 41 42 status_t get_menu_info(menu_info* info); 43 status_t set_menu_info(menu_info* info); 44 45 typedef bool (*menu_tracking_hook)(BMenu* menu, void* state); 46 47 48 class BMenu : public BView { 49 public: 50 BMenu(const char* name, 51 menu_layout layout = B_ITEMS_IN_COLUMN); 52 BMenu(const char* name, float width, 53 float height); 54 BMenu(BMessage* archive); 55 56 virtual ~BMenu(); 57 58 static BArchivable* Instantiate(BMessage* archive); 59 virtual status_t Archive(BMessage* archive, 60 bool deep = true) const; 61 62 virtual void AttachedToWindow(); 63 virtual void DetachedFromWindow(); 64 virtual void AllAttached(); 65 virtual void AllDetached(); 66 67 virtual void Draw(BRect updateRect); 68 69 virtual void MessageReceived(BMessage* message); 70 virtual void KeyDown(const char* bytes, int32 numBytes); 71 72 virtual BSize MinSize(); 73 virtual BSize MaxSize(); 74 virtual BSize PreferredSize(); 75 virtual void GetPreferredSize(float* _width, 76 float* _height); 77 virtual void ResizeToPreferred(); 78 virtual void DoLayout(); 79 virtual void FrameMoved(BPoint where); 80 virtual void FrameResized(float width, float height); 81 82 void InvalidateLayout(); 83 84 virtual void MakeFocus(bool focus = true); 85 86 bool AddItem(BMenuItem* item); 87 bool AddItem(BMenuItem* item, int32 index); 88 bool AddItem(BMenuItem* item, BRect frame); 89 bool AddItem(BMenu* menu); 90 bool AddItem(BMenu* menu, int32 index); 91 bool AddItem(BMenu* menu, BRect frame); 92 bool AddList(BList* list, int32 index); 93 94 bool AddSeparatorItem(); 95 96 bool RemoveItem(BMenuItem* item); 97 BMenuItem* RemoveItem(int32 index); 98 bool RemoveItems(int32 index, int32 count, 99 bool deleteItems = false); 100 bool RemoveItem(BMenu* menu); 101 102 BMenuItem* ItemAt(int32 index) const; 103 BMenu* SubmenuAt(int32 index) const; 104 int32 CountItems() const; 105 int32 IndexOf(BMenuItem* item) const; 106 int32 IndexOf(BMenu* menu) const; 107 BMenuItem* FindItem(uint32 command) const; 108 BMenuItem* FindItem(const char* name) const; 109 110 virtual status_t SetTargetForItems(BHandler* target); 111 virtual status_t SetTargetForItems(BMessenger messenger); 112 virtual void SetEnabled(bool enable); 113 virtual void SetRadioMode(bool on); 114 virtual void SetTriggersEnabled(bool enable); 115 virtual void SetMaxContentWidth(float maxWidth); 116 117 void SetLabelFromMarked(bool on); 118 bool IsLabelFromMarked(); 119 bool IsEnabled() const; 120 bool IsRadioMode() const; 121 bool AreTriggersEnabled() const; 122 bool IsRedrawAfterSticky() const; 123 float MaxContentWidth() const; 124 125 BMenuItem* FindMarked(); 126 int32 FindMarkedIndex(); 127 128 BMenu* Supermenu() const; 129 BMenuItem* Superitem() const; 130 131 132 virtual BHandler* ResolveSpecifier(BMessage* message, 133 int32 index, BMessage* specifier, 134 int32 form, const char* property); 135 virtual status_t GetSupportedSuites(BMessage* data); 136 137 virtual status_t Perform(perform_code d, void* arg); 138 139 protected: 140 BMenu(BRect frame, const char* name, 141 uint32 resizeMask, uint32 flags, 142 menu_layout layout, bool resizeToFit); 143 144 virtual void LayoutInvalidated(bool descendants); 145 146 virtual BPoint ScreenLocation(); 147 148 void SetItemMargins(float left, float top, 149 float right, float bottom); 150 void GetItemMargins(float* _left, float* _top, 151 float* _right, float* _bottom) const; 152 153 menu_layout Layout() const; 154 155 virtual void Show(); 156 void Show(bool selectFirstItem); 157 void Hide(); 158 BMenuItem* Track(bool startOpened = false, 159 BRect* specialRect = NULL); 160 161 public: 162 enum add_state { 163 B_INITIAL_ADD, 164 B_PROCESSING, 165 B_ABORT 166 }; 167 virtual bool AddDynamicItem(add_state state); 168 virtual void DrawBackground(BRect updateRect); 169 170 void SetTrackingHook(menu_tracking_hook hook, 171 void* state); 172 173 // Reorder items 174 void SortItems(int (*compare)(const BMenuItem*, 175 const BMenuItem*)); 176 bool SwapItems(int32 indexA, int32 indexB); 177 bool MoveItem(int32 indexFrom, int32 indexTo); 178 179 private: 180 friend class BMenuBar; 181 friend class BSeparatorItem; 182 friend class BPrivate::MenuPrivate; 183 friend status_t _init_interface_kit_(); 184 friend status_t set_menu_info(menu_info* info); 185 friend status_t get_menu_info(menu_info* info); 186 187 struct LayoutData; 188 189 virtual void _ReservedMenu3(); 190 virtual void _ReservedMenu4(); 191 virtual void _ReservedMenu5(); 192 virtual void _ReservedMenu6(); 193 194 BMenu& operator=(const BMenu& other); 195 196 void _InitData(BMessage* archive); 197 bool _Show(bool selectFirstItem = false, 198 bool keyDown = false); 199 void _Hide(); 200 BMenuItem* _Track(int* action, long start = -1); 201 void _ScriptReceived(BMessage* message); 202 void _ItemScriptReceived(BMessage* message, 203 BMenuItem* item); 204 status_t _ResolveItemSpecifier(const BMessage& specifier, 205 int32 what, BMenuItem*& item, 206 int32 *index = NULL); 207 status_t _InsertItemAtSpecifier( 208 const BMessage& specifier, int32 what, 209 BMenuItem* item); 210 211 void _UpdateNavigationArea(BPoint position, 212 BRect& navAreaRectAbove, 213 BRect& navAreaBelow); 214 215 void _UpdateStateOpenSelect(BMenuItem* item, 216 BPoint position, BRect& navAreaRectAbove, 217 BRect& navAreaBelow, 218 bigtime_t& selectedTime, 219 bigtime_t& navigationAreaTime); 220 void _UpdateStateClose(BMenuItem* item, 221 const BPoint& where, 222 const uint32& buttons); 223 224 bool _AddItem(BMenuItem* item, int32 index); 225 bool _RemoveItems(int32 index, int32 count, 226 BMenuItem* item, bool deleteItems = false); 227 bool _RelayoutIfNeeded(); 228 void _LayoutItems(int32 index); 229 BSize _ValidatePreferredSize(); 230 void _ComputeLayout(int32 index, bool bestFit, 231 bool moveItems, float* width, 232 float* height); 233 void _ComputeColumnLayout(int32 index, bool bestFit, 234 bool moveItems, BRect* override, BRect& outRect); 235 void _ComputeRowLayout(int32 index, bool bestFit, 236 bool moveItems, BRect& outRect); 237 void _ComputeMatrixLayout(BRect& outRect); 238 239 BRect _CalcFrame(BPoint where, bool* scrollOn); 240 241 protected: 242 void DrawItems(BRect updateRect); 243 244 private: 245 bool _OverSuper(BPoint loc); 246 bool _OverSubmenu(BMenuItem* item, BPoint loc); 247 BPrivate::BMenuWindow* _MenuWindow(); 248 void _DeleteMenuWindow(); 249 BMenuItem* _HitTestItems(BPoint where, 250 BPoint slop = B_ORIGIN) const; 251 BRect _Superbounds() const; 252 void _CacheFontInfo(); 253 254 void _ItemMarked(BMenuItem* item); 255 void _Install(BWindow* target); 256 void _Uninstall(); 257 void _SelectItem(BMenuItem* item, 258 bool showSubmenu = true, 259 bool selectFirstItem = false, 260 bool keyDown = false); 261 bool _SelectNextItem(BMenuItem* item, bool forward); 262 BMenuItem* _NextItem(BMenuItem* item, bool forward) const; _SetIgnoreHidden(bool ignoreHidden)263 void _SetIgnoreHidden(bool ignoreHidden) 264 { fIgnoreHidden = ignoreHidden; } 265 void _SetStickyMode(bool on); 266 bool _IsStickyMode() const; 267 268 // Methods to get the current modifier keycode 269 void _GetShiftKey(uint32 &value) const; 270 void _GetControlKey(uint32 &value) const; 271 void _GetCommandKey(uint32 &value) const; 272 void _GetOptionKey(uint32 &value) const; 273 void _GetMenuKey(uint32 &value) const; 274 275 void _CalcTriggers(); 276 bool _ChooseTrigger(const char* title, int32& index, 277 uint32& trigger, 278 BPrivate::TriggerList& triggers); 279 void _UpdateWindowViewSize(const bool &updatePosition); 280 bool _AddDynamicItems(bool keyDown = false); 281 bool _OkToProceed(BMenuItem* item, 282 bool keyDown = false); 283 284 bool _CustomTrackingWantsToQuit(); 285 286 int _State(BMenuItem** _item = NULL) const; 287 void _InvokeItem(BMenuItem* item, bool now = false); 288 void _QuitTracking(bool onlyThis = true); 289 290 static menu_info sMenuInfo; 291 292 // Variables to keep track of what code is currently assigned to 293 // each modifier key 294 static uint32 sShiftKey; 295 static uint32 sControlKey; 296 static uint32 sOptionKey; 297 static uint32 sCommandKey; 298 static uint32 sMenuKey; 299 300 BMenuItem* fChosenItem; 301 BList fItems; 302 BRect fPad; 303 BMenuItem* fSelected; 304 BPrivate::BMenuWindow* fCachedMenuWindow; 305 BMenu* fSuper; 306 BMenuItem* fSuperitem; 307 BRect fSuperbounds; 308 float fAscent; 309 float fDescent; 310 float fFontHeight; 311 uint32 fState; 312 menu_layout fLayout; 313 BRect* fExtraRect; 314 float fMaxContentWidth; 315 BPoint* fInitMatrixSize; 316 BPrivate::ExtraMenuData* fExtraMenuData; 317 318 LayoutData* fLayoutData; 319 320 int32 _reserved; 321 322 char fTrigger; 323 bool fResizeToFit; 324 bool fUseCachedMenuLayout; 325 bool fEnabled; 326 bool fDynamicName; 327 bool fRadioMode; 328 bool fTrackNewBounds; 329 bool fStickyMode; 330 bool fIgnoreHidden; 331 bool fTriggerEnabled; 332 bool fHasSubmenus; 333 bool fAttachAborted; 334 }; 335 336 #endif // _MENU_H 337