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
14class BMenu;
15class BMenuBar;
16class BMenuItem;
17
18
19namespace BPrivate {
20	class BMenuWindow;
21	class ExtraMenuData;
22	class TriggerList;
23	class MenuPrivate;
24}
25
26enum menu_layout {
27	B_ITEMS_IN_ROW = 0,
28	B_ITEMS_IN_COLUMN,
29	B_ITEMS_IN_MATRIX
30};
31
32struct 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
42status_t get_menu_info(menu_info* info);
43status_t set_menu_info(menu_info* info);
44
45typedef bool (*menu_tracking_hook)(BMenu* menu, void* state);
46
47
48class BMenu : public BView {
49public:
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
139protected:
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
161public:
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
179private:
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
241protected:
242			void				DrawItems(BRect updateRect);
243
244private:
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;
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