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