1 /*	Public domain	*/
2 
3 #ifndef _AGAR_GUI_MENU_H_
4 #define _AGAR_GUI_MENU_H_
5 
6 #include <agar/gui/widget.h>
7 #include <agar/gui/window.h>
8 #include <agar/gui/toolbar.h>
9 
10 #include <agar/gui/begin.h>
11 
12 struct ag_menu;
13 struct ag_menu_view;
14 struct ag_button;
15 
16 typedef AG_TAILQ_HEAD(ag_menu_itemq, ag_menu_item) AG_MenuItemQ;
17 
18 typedef struct ag_menu_item {
19 	char *text;			/* Label text */
20 	int lblMenu[2];			/* Cached surfaces (for AG_Menu) */
21 	int lblView[2];			/* Cached surfaces (for AG_MenuView) */
22 	int icon;			/* Icon surface mapping */
23 	AG_Surface *iconSrc;		/* Icon surface source */
24 	int value;			/* Default bool value binding */
25 
26 	int          state;		/* State flag */
27 	AG_Function *stateFn;		/* State function (overrides flag) */
28 
29 	AG_KeySym key_equiv;		/* Key shortcut */
30 	AG_KeyMod key_mod;
31 	int x, y;			/* Position in parent view */
32 	AG_Event *clickFn;		/* Raised on click */
33 	AG_Event *poll;			/* Raised before the item is drawn */
34 	Uint flags;
35 #define AG_MENU_ITEM_ICONS	  0x01	/* At least one subitems has an icon
36 					   (optimization) */
37 #define AG_MENU_ITEM_NOSELECT	  0x02	/* Non-selectable regardless of state */
38 #define AG_MENU_ITEM_SEPARATOR	  0x04	/* Item is a cosmetic separator */
39 
40 	enum ag_menu_binding {		/* Boolean binding */
41 		AG_MENU_NO_BINDING,
42 		AG_MENU_INT_BOOL,
43 		AG_MENU_INT8_BOOL,
44 		AG_MENU_INT_FLAGS,
45 		AG_MENU_INT8_FLAGS,
46 		AG_MENU_INT16_FLAGS,
47 		AG_MENU_INT32_FLAGS
48 	} bind_type;
49 	void *bind_p;			/* Pointer to bound variable */
50 	Uint32 bind_flags;		/* Bitmask to control (for FLAGS) */
51 	int bind_invert;		/* Invert the value */
52 	AG_Mutex *bind_lock;		/* Lock when accessing binding */
53 
54 	struct ag_menu_view *view;	/* Back pointer to view (subitems) */
55 	struct ag_menu *pmenu;		/* Parent menu */
56 	struct ag_menu_item *sel_subitem; /* Selected subitem */
57 	struct ag_button *tbButton;	/* Associated toolbar button */
58 	struct ag_menu_item *parent;	/* Parent MenuItem or NULL */
59 
60 	AG_TAILQ_ENTRY(ag_menu_item) items;	/* In parent */
61 	AG_TAILQ_HEAD_(ag_menu_item) subItems;	/* Child items */
62 	Uint                        nSubItems;
63 } AG_MenuItem;
64 
65 enum ag_menu_style {
66 	AG_MENU_DROPDOWN,	/* Drop-down menu */
67 	AG_MENU_POPUP,		/* Contextual popup */
68 	AG_MENU_GLOBAL		/* Global application menu */
69 };
70 
71 typedef struct ag_menu {
72 	struct ag_widget wid;
73 	Uint flags;
74 #define AG_MENU_HFILL	 	0x01
75 #define AG_MENU_VFILL	 	0x02
76 #define AG_MENU_EXPAND	 	(AG_MENU_HFILL|AG_MENU_VFILL)
77 	enum ag_menu_style style;	/* Menu style */
78 	AG_MenuItem *root;		/* Root menu item */
79 	int selecting;			/* Selection in progress */
80 	AG_MenuItem *itemSel;		/* Selected top-level item */
81 	int spHoriz;			/* Horiz spacing between items */
82 	int spVert;			/* Vertical spacing between items */
83 	int lPad, rPad, tPad, bPad;	/* Global padding in pixels */
84 	int lPadLbl, rPadLbl;		/* Item label padding in pixels */
85 	int tPadLbl, bPadLbl;
86 	int itemh;			/* Item height (optimization) */
87 	int curState;			/* For MenuState() */
88 	AG_Toolbar *curToolbar;		/* For MenuToolbar() */
89 	AG_Rect r;			/* View area */
90 } AG_Menu;
91 
92 typedef struct ag_popup_menu {
93 	AG_Widget *widget;		/* Parent widget */
94 	AG_Menu *menu;			/* Menu (allocated) */
95 	AG_MenuItem *root;		/* Alias for menu->root */
96 	AG_Window *win;			/* Expanded window */
97 #ifdef AG_LEGACY
98 	AG_MenuItem *item;
99 #endif
100 } AG_PopupMenu;
101 
102 typedef struct ag_menu_view {
103 	struct ag_widget wid;
104 	AG_Menu *pmenu;
105 	AG_MenuItem *pitem;
106 	int spIconLbl;			/* Icon and label spacing */
107 	int spLblArrow;			/* Label and submenu arrow spacing */
108 	int lPad, rPad, tPad, bPad;	/* Padding in pixels */
109 	AG_Timer submenuTo;		/* For sub-menu popup delay */
110 	int arrowRight;			/* Right arrow surface handle */
111 } AG_MenuView;
112 
113 __BEGIN_DECLS
114 extern AG_WidgetClass agMenuClass;
115 extern AG_WidgetClass agMenuViewClass;
116 extern AG_Menu *agAppMenu;
117 extern AG_Window *agAppMenuWin;
118 extern AG_Mutex agAppMenuLock;
119 
120 void       AG_InitAppMenu(void);
121 void       AG_DestroyAppMenu(void);
122 AG_Menu	  *AG_MenuNew(void *, Uint);
123 AG_Menu	  *AG_MenuNewGlobal(Uint);
124 void 	   AG_MenuScale(void *, int, int);
125 void	   AG_MenuDraw(void *);
126 
127 AG_PopupMenu	*AG_PopupNew(void *);
128 void		 AG_PopupShow(AG_PopupMenu *);
129 void		 AG_PopupShowAt(AG_PopupMenu *, int, int);
130 void		 AG_PopupHide(AG_PopupMenu *);
131 void		 AG_PopupDestroy(AG_PopupMenu *);
132 
133 void	     AG_MenuDel(AG_MenuItem *);
134 void	     AG_MenuItemFree(AG_MenuItem *);
135 AG_Window   *AG_MenuExpand(void *, AG_MenuItem *, int, int);
136 void   	     AG_MenuCollapse(AG_MenuItem *);
137 void   	     AG_MenuCollapseAll(AG_Menu *);
138 
139 void	 AG_MenuSetPadding(AG_Menu *, int, int, int, int);
140 void	 AG_MenuSetLabelPadding(AG_Menu *, int, int, int, int);
141 #define	 AG_MenuSetPaddingLeft(m,v)   AG_MenuSetPadding((m),(v),-1,-1,-1)
142 #define	 AG_MenuSetPaddingRight(m,v)  AG_MenuSetPadding((m),-1,(v),-1,-1)
143 #define	 AG_MenuSetPaddingTop(m,v)    AG_MenuSetPadding((m),-1,-1,(v),-1)
144 #define	 AG_MenuSetPaddingBottom(m,v) AG_MenuSetPadding((m),-1,-1,-1,(v))
145 #define	 AG_MenuSetLabelPaddingLeft(m,v) \
146 	 AG_MenuSetLabelPadding((m),(v),-1,-1,-1)
147 #define	 AG_MenuSetLabelPaddingRight(m,v) \
148 	 AG_MenuSetLabelPadding((m),-1,(v),-1,-1)
149 #define	 AG_MenuSetLabelPaddingTop(m,v) \
150 	 AG_MenuSetLabelPadding((m),-1,-1,(v),-1)
151 #define	 AG_MenuSetLabelPaddingBottom(m,v) \
152 	 AG_MenuSetLabelPadding((m),-1,-1,-1,(v))
153 
154 void AG_MenuSetIcon(AG_MenuItem *, const AG_Surface *);
155 void AG_MenuSetLabel(AG_MenuItem *, const char *, ...)
156                      FORMAT_ATTRIBUTE(printf,2,3)
157 		     NONNULL_ATTRIBUTE(2);
158 void AG_MenuSetLabelS(AG_MenuItem *, const char *);
159 void AG_MenuSetPollFn(AG_MenuItem *, AG_EventFn, const char *, ...);
160 void AG_MenuUpdateItem(AG_MenuItem *);
161 
162 void	     AG_MenuState(AG_MenuItem *, int);
163 #define      AG_MenuDisable(m) AG_MenuState((m),0)
164 #define      AG_MenuEnable(m) AG_MenuState((m),1)
165 
166 void	     AG_MenuToolbar(AG_MenuItem *, AG_Toolbar *);
167 
168 AG_MenuItem *AG_MenuNode(AG_MenuItem *, const char *, const AG_Surface *);
169 AG_MenuItem *AG_MenuSeparator(AG_MenuItem *);
170 AG_MenuItem *AG_MenuSection(AG_MenuItem *, const char *, ...)
171                             FORMAT_ATTRIBUTE(printf,2,3)
172 			    NONNULL_ATTRIBUTE(2);
173 AG_MenuItem *AG_MenuSectionS(AG_MenuItem *, const char *);
174 AG_MenuItem *AG_MenuAction(AG_MenuItem *, const char *, const AG_Surface *,
175 			   AG_EventFn, const char *, ...);
176 AG_MenuItem *AG_MenuActionKb(AG_MenuItem *, const char *, const AG_Surface *,
177                              AG_KeySym, AG_KeyMod, AG_EventFn, const char *, ...);
178 AG_MenuItem *AG_MenuTool(AG_MenuItem *, AG_Toolbar *, const char *,
179                          const AG_Surface *, AG_KeySym, AG_KeyMod, AG_EventFn,
180 			 const char *, ...);
181 AG_MenuItem *AG_MenuDynamicItem(AG_MenuItem *, const char *, const AG_Surface *,
182                                 AG_EventFn, const char *, ...);
183 AG_MenuItem *AG_MenuDynamicItemKb(AG_MenuItem *, const char *, const AG_Surface *,
184                                   AG_KeySym, AG_KeyMod, AG_EventFn, const char *,
185 				  ...);
186 AG_MenuItem *AG_MenuIntBoolMp(AG_MenuItem *, const char *, const AG_Surface *,
187                               int *, int, AG_Mutex *);
188 AG_MenuItem *AG_MenuInt8BoolMp(AG_MenuItem *, const char *, const AG_Surface *,
189                                Uint8 *, int, AG_Mutex *);
190 AG_MenuItem *AG_MenuIntFlagsMp(AG_MenuItem *, const char *, const AG_Surface *,
191                                int *, int, int, AG_Mutex *);
192 AG_MenuItem *AG_MenuInt8FlagsMp(AG_MenuItem *, const char *, const AG_Surface *,
193                                 Uint8 *, Uint8, int, AG_Mutex *);
194 AG_MenuItem *AG_MenuInt16FlagsMp(AG_MenuItem *, const char *, const AG_Surface *,
195                                  Uint16 *, Uint16, int, AG_Mutex *);
196 AG_MenuItem *AG_MenuInt32FlagsMp(AG_MenuItem *, const char *, const AG_Surface *,
197                                  Uint32 *, Uint32, int, AG_Mutex *);
198 
199 #define	AG_MenuIntBool(mi,t,i,p,inv) \
200 	AG_MenuIntBoolMp((mi),(t),(i),(p),(inv),NULL)
201 #define AG_MenuInt8Bool(mi,t,i,p,inv) \
202 	AG_MenuInt8BoolMp((mi),(t),(i),(p),(inv),NULL)
203 
204 #define	AG_MenuBool(mi,t,i,p,inv) \
205 	AG_MenuIntBoolMp((mi),(t),(i),(p),(inv),NULL)
206 #define	AG_MenuBoolMp(mi,t,i,p,inv,mu) \
207 	AG_MenuIntBoolMp((mi),(t),(i),(p),(inv),(mu))
208 
209 #define AG_MenuIntFlags(mi,t,i,fp,fl,inv) \
210 	AG_MenuIntFlagsMp((mi),(t),(i),(fp),(fl),(inv),NULL)
211 #define AG_MenuInt8Flags(mi,t,i,fp,fl,inv) \
212 	AG_MenuInt8FlagsMp((mi),(t),(i),(fp),(fl),(inv),NULL)
213 #define AG_MenuInt16Flags(mi,t,i,fp,fl,inv) \
214 	AG_MenuInt16FlagsMp((mi),(t),(i),(fp),(fl),(inv),NULL)
215 #define AG_MenuInt32Flags(mi,t,i,fp,fl,inv) \
216 	AG_MenuInt32FlagsMp((mi),(t),(i),(fp),(fl),(inv),NULL)
217 
218 #define AG_MenuUintFlagsMp(mi,t,i,fp,fl,inv,mtx) \
219 	AG_MenuIntFlagsMp((mi),(t),(i),(int *)(fp),(int)(fl),(inv),(mtx))
220 #define AG_MenuUintFlags(mi,t,i,fp,fl,inv) \
221 	AG_MenuIntFlagsMp((mi),(t),(i),(int *)(fp),(int)(fl),(inv),NULL)
222 
223 #define AG_MenuFlagsMp(mi,t,i,fp,fl,inv,mtx) \
224 	AG_MenuIntFlagsMp((mi),(t),(i),(int *)(fp),(int)(fl),(inv),(mtx))
225 #define AG_MenuFlags(mi,t,i,fp,fl,inv) \
226 	AG_MenuIntFlagsMp((mi),(t),(i),(int *)(fp),(int)(fl),(inv),NULL)
227 
228 void    AG_MenuSetIntBoolMp(AG_MenuItem *, int *, int, AG_Mutex *);
229 #define AG_MenuSetIntBool(mi,p,fl,inv,mtx) \
230         AG_MenuSetIntBoolMp((mi),(p),(fl),(inv),(mtx))
231 
232 void AG_MenuSetIntFlagsMp(AG_MenuItem *, int *, int, int, AG_Mutex *);
233 #ifdef AG_LEGACY
234 # define AG_MenuAddItem(m,lbl) AG_MenuNode((m)->root,(lbl),NULL)
235 #endif /* AG_LEGACY */
236 __END_DECLS
237 
238 #include <agar/gui/close.h>
239 #endif /* _AGAR_GUI_MENU_H_ */
240