xref: /haiku/headers/os/interface/Menu.h (revision c237c4ce593ee823d9867fd997e51e4c447f5623)
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;
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