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