diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /public/vgui_controls/Menu.h | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'public/vgui_controls/Menu.h')
| -rw-r--r-- | public/vgui_controls/Menu.h | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/public/vgui_controls/Menu.h b/public/vgui_controls/Menu.h new file mode 100644 index 0000000..fbe44b2 --- /dev/null +++ b/public/vgui_controls/Menu.h @@ -0,0 +1,380 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef MENU_H +#define MENU_H + +#ifdef _WIN32 +#pragma once +#endif + +#include <vgui_controls/Panel.h> +#include <vgui_controls/Label.h> +#include <utllinkedlist.h> +#include <utlvector.h> + +namespace vgui +{ + +class MenuItem; +class ScrollBar; +class MenuSeparator; + +//----------------------------------------------------------------------------- +// Purpose: A menu is a list of items that can be selected with one click, navigated +// with arrow keys and/or hot keys, and have a lit behavior when mouse over. +// It is NOT the button which opens the menu, but only the menu itself. +// +// Behaviour spec: +// Menu navigation can be done in 2 modes, via keyboard keys and via mouse. +// Clicking on menu button opens menu. +// Only one item in a menu is highlighted at a time. +// Only one submenu in a menu is open at a time. +// Disabled menuitems get highlighted via mouse and keys but will not activate. +// +// Mouse: +// Moving mouse into a menuitem highlights it. +// If the menuitem has a cascading menu, the menu opens when the mouse enters +// the menuitem. The cascading menuitem stays highlighted while its menu is open. +// No submenu items are highlighted by default. +// Moving the mouse into another menuitem closes any previously open submenus in the list. +// Clicking once in the menu item activates the menu item and closes all menus. +// Moving the mouse off a menuitem unhighlights it. +// The scroll bar arrows can be used to move up/down the menu one item at a time. +// The clicking and dragging on the scroll bar nob also scrolls the menu items. +// If a highlighed menuitem scrolls off, and the user then begins navigating via keys, +// the menu will snap the scroll bar so the highlighted item is visible. +// If user has been navigating via keys, moving the mouse over a menu item +// highlights it. +// Mousewheel: +// You must have the mouse inside the menu/scroll bar to use the wheel. +// The mouse wheel moves the highlighted menuitem up or down the list. +// If the list has no scroll bar the wheel will cycle from the bottom of the list +// to the top of the list and vice versa. +// If the list has a scrollbar the mouse wheel will stop at the top or bottom +// of the list. +// If the mouse is over the scroll bar no items are highlighted. +// Keyboard: +// When a menu is opened, no items are highlighted. +// If a menuitem has a cascading menu it does not open when the item is highlighted. +// The down arrow selects the next item in the list. +// (first item if none are highlighted and there is a scrollbar). +// The up arrow selects the previous item in the list +// (first item if none are highlighted and there is a scrollbar, last item if none are +// highlighted and there is no scrollbar). +// Selecting a new menuitem closes any previously open submenus in the list. +// The enter key activates the selected item and closes all menus. +// If the selected item has a cascading menu, activating it opens its submenu. +// These may also be activated by pressing the right arrow. +// Pressing the left arrow closes the submenu. +// When the submenu is opened the cascading menuitem stays highlighted. +// No items in the submenu are highlighted when it is opened. +// +// Note: Cascading menuitems in menus with a scrollbar is not supported. +// Its a clunky UI and if we want this we should design a better solution, +// perhaps along the lines of how explorer's bookmarks does it. +// It currently functions, but there are some arm/disarm bugs. +// +// +//----------------------------------------------------------------------------- +class Menu : public Panel +{ + DECLARE_CLASS_SIMPLE( Menu, Panel ); + friend class MenuItem; +public: + enum MenuDirection_e + { + LEFT, + RIGHT, + UP, + DOWN, + CURSOR, // make the menu appear under the mouse cursor + ALIGN_WITH_PARENT, // make the menu appear under the parent + }; + + Menu(Panel *parent, const char *panelName); + ~Menu(); + + static void PlaceContextMenu( Panel *parent, Menu *menu ); + static void OnInternalMousePressed( Panel *other, MouseCode code ); + + virtual void PositionRelativeToPanel( Panel *reference, MenuDirection_e direction, int nAdditionalYOffset = 0, bool showMenu = false ); + + // the menu. For combo boxes, it's the edit/field, etc. etc. + + // Add a simple text item to the menu + virtual int AddMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + virtual int AddMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + + virtual int AddMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target , const KeyValues *userData = NULL); + virtual int AddMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target , const KeyValues *userData = NULL); + + virtual int AddMenuItem( const char *itemText, const char *command, Panel *target , const KeyValues *userData = NULL); + virtual int AddMenuItem( const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + virtual int AddMenuItem( const char *itemText, Panel *target, const KeyValues *userData = NULL ); + + // Add a checkable item to the menu + virtual int AddCheckableMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + virtual int AddCheckableMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + + virtual int AddCheckableMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + virtual int AddCheckableMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + + virtual int AddCheckableMenuItem( const char *itemText, const char *command, Panel *target , const KeyValues *userData = NULL); + virtual int AddCheckableMenuItem( const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + virtual int AddCheckableMenuItem( const char *itemText, Panel *target, const KeyValues *userData = NULL ); + + // Add a cascading menu item to the menu + virtual int AddCascadingMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + + virtual int AddCascadingMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + + virtual int AddCascadingMenuItem( const char *itemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemText, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + + // Add a custom panel to the menu + virtual int AddMenuItem( MenuItem *panel ); + + virtual void AddSeparator(); + virtual void AddSeparatorAfterItem( int itemID ); + + // Sets the values of a menu item at the specified index + virtual void UpdateMenuItem(int itemID, const char *itemText,KeyValues *message, const KeyValues *userData = NULL); + virtual void UpdateMenuItem(int itemID, const wchar_t *wszItemText,KeyValues *message, const KeyValues *userData = NULL); + + virtual void MoveMenuItem( int itemID, int moveBeforeThisItemID ); + + virtual bool IsValidMenuID(int itemID); + virtual int GetInvalidMenuID(); + + KeyValues *GetItemUserData(int itemID); + void GetItemText(int itemID, wchar_t *text, int bufLenInBytes); + void GetItemText(int itemID, char *text, int bufLenInBytes); + + virtual void SetItemEnabled(const char *itemName, bool state); + virtual void SetItemEnabled(int itemID, bool state); + virtual void SetItemVisible(const char *itemName, bool visible); + virtual void SetItemVisible(int itemID, bool visible); + + // Remove a single item + void DeleteItem( int itemID ); + + // Clear the menu, deleting all the menu items within + void DeleteAllItems(); + + // Override the auto-width setting with a single fixed width + virtual void SetFixedWidth( int width ); + + // Sets the content alignment of all items in the menu + void SetContentAlignment( Label::Alignment alignment ); + + // sets the height of each menu item + virtual void SetMenuItemHeight(int itemHeight); + virtual int GetMenuItemHeight() const; + + // Set the max number of items visible (scrollbar appears with more) + virtual void SetNumberOfVisibleItems( int numItems ); + + // Add the menu to the menu manager (see Menu::SetVisible())? + void EnableUseMenuManager( bool bUseMenuManager ); + + // Set up the menu items layout + virtual void PerformLayout( void ); + + virtual void SetBorder(class IBorder *border); + virtual void ApplySchemeSettings(IScheme *pScheme); + + // Set type ahead behaviour + enum MenuTypeAheadMode + { + COMPAT_MODE = 0, + HOT_KEY_MODE, + TYPE_AHEAD_MODE, + }; + virtual void SetTypeAheadMode(MenuTypeAheadMode mode); + virtual int GetTypeAheadMode(); + + // Hotkey handling + virtual void OnKeyTyped(wchar_t unichar); + // Menu nagivation etc. + virtual void OnKeyCodeTyped( KeyCode code ); + + // Visibility + virtual void SetVisible(bool state); + + // Activates item in the menu list, as if that menu item had been selected by the user + virtual void ActivateItem(int itemID); + virtual void SilentActivateItem(int itemID); // activate item, but don't fire the action signal + virtual void ActivateItemByRow(int row); + virtual int GetActiveItem(); // returns the itemID (not the row) of the active item + + // Return the number of items currently in the menu list + virtual int GetItemCount() const; + + // return the menuID of the n'th item in the menu list, valid from [0, GetItemCount) + virtual int GetMenuID(int index); + + // Return the number of items currently visible in the menu list + int GetCurrentlyVisibleItemsCount(); + + MenuItem *GetMenuItem(int itemID); + void CloseOtherMenus(MenuItem *item); + virtual void OnKillFocus(); + + int GetMenuMode(); + enum MenuMode + { + MOUSE = 0, + KEYBOARD, + }; + + void SetCurrentlyHighlightedItem(int itemID); + int GetCurrentlyHighlightedItem(); + void ClearCurrentlyHighlightedItem(); + + // Set the checked state of a checkable menuItem + void SetMenuItemChecked(int itemID, bool state); + bool IsChecked(int index); // check if item is checked. + + + void SetMinimumWidth(int width); + int GetMinimumWidth(); + + // baseclass overrides to chain colors through to cascade menus + virtual void SetFgColor( Color newColor ); + virtual void SetBgColor( Color newColor ); + + virtual void SetFont( HFont font ); + + // Pass in NULL hotkey to remove hotkey + void SetCurrentKeyBinding( int itemID, char const *hotkey ); + + void ForceCalculateWidth(); + + void SetUseFallbackFont( bool bState, HFont hFallback ); + +protected: + // helper functions + int AddMenuItemCharCommand(MenuItem *item, const char *command, Panel *target, const KeyValues *userData); + int AddMenuItemKeyValuesCommand(MenuItem *item, KeyValues *message, Panel *target, const KeyValues *userData); + + // vgui result reporting + virtual void OnCommand( const char *command ); + MESSAGE_FUNC_PTR( OnMenuItemSelected, "MenuItemSelected", panel ); + virtual void AddScrollBar(); + virtual void RemoveScrollBar(); + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); + virtual void Paint(); + virtual void LayoutMenuBorder(); + virtual void MakeItemsVisibleInScrollRange( int maxVisibleItems, int nNumPixelsAvailable ); + virtual void OnMouseWheeled(int delta); + // Alternate OnKeyTyped behaviors + virtual void OnHotKey(wchar_t unichar); + virtual void OnTypeAhead(wchar_t unichar); + + int CountVisibleItems(); + void ComputeWorkspaceSize( int& workWide, int& workTall ); + int ComputeFullMenuHeightWithInsets(); + + void CalculateWidth(); + + void LayoutScrollBar(); + void PositionCascadingMenu(); + void SizeMenuItems(); + void OnCursorMoved(int x, int y); + void OnKeyCodePressed(KeyCode code); + void OnMenuClose(); + MESSAGE_FUNC( OnKeyModeSet, "KeyModeSet" ); + + void SetCurrentlySelectedItem(MenuItem *item); + void SetCurrentlySelectedItem(int itemID); + MESSAGE_FUNC_INT( OnCursorEnteredMenuItem, "CursorEnteredMenuItem", VPanel); + MESSAGE_FUNC_INT( OnCursorExitedMenuItem, "CursorExitedMenuItem", VPanel); + + void MoveAlongMenuItemList(int direction, int loopCount); + + enum + { + DEFAULT_MENU_ITEM_HEIGHT = 22, // height of items in the menu + MENU_UP = -1, // used for moving up/down list of menu items in the menu + MENU_DOWN = 1 + }; + +#ifdef DBGFLAG_VALIDATE + virtual void Validate( CValidator &validator, char *pchName ); +#endif // DBGFLAG_VALIDATE + +private: + MenuItem *GetParentMenuItem(); + + int m_iMenuItemHeight; + int m_iFixedWidth; + int m_iMinimumWidth; // a minimum width the menu has to be if it is not fixed width + int m_iNumVisibleLines; // number of items in menu before scroll bar adds on + ScrollBar *m_pScroller; + + CUtlLinkedList<MenuItem*, int> m_MenuItems; + + CUtlVector<int> m_VisibleSortedItems; + CUtlVector<int> m_SortedItems; // used for visual + CUtlVector<int> m_Separators; // menu item ids after which separators should be shown + CUtlVector<MenuSeparator *> m_SeparatorPanels; + + bool _sizedForScrollBar: 1 ; // whether menu has been sized for a scrollbar + bool m_bUseFallbackFont : 1; + bool _recalculateWidth : 1; + bool m_bUseMenuManager : 1; + + int _menuWide; + int m_iCurrentlySelectedItemID; + int m_iInputMode; + int m_iCheckImageWidth; // the size of the check box spot on a checkable menu. + int m_iProportionalScrollBarSize; + Label::Alignment m_Alignment; + Color _borderDark; + int m_iActivatedItem; + HFont m_hItemFont; + HFont m_hFallbackItemFont; + + // for managing type ahead + #define TYPEAHEAD_BUFSIZE 256 + MenuTypeAheadMode m_eTypeAheadMode; + wchar_t m_szTypeAheadBuf[TYPEAHEAD_BUFSIZE]; + int m_iNumTypeAheadChars; + double m_fLastTypeAheadTime; +}; + + +//----------------------------------------------------------------------------- +// Helper class to create menu +//----------------------------------------------------------------------------- +class MenuBuilder +{ +public: + + MenuBuilder( Menu *pMenu, Panel *pActionTarget ); + + MenuItem* AddMenuItem( const char *pszButtonText, const char *pszCommand, const char *pszCategoryName ); + MenuItem* AddMenuItem( const char *pszButtonText, KeyValues *kvUserData, const char *pszCategoryName ); + + MenuItem* AddCascadingMenuItem( const char *pszButtonText, Menu *pSubMenu, const char *pszCategoryName ); + +private: + + void AddSepratorIfNeeded( const char *pszCategoryName ); + + Menu *m_pMenu; + Panel *m_pActionTarget; + const char *m_pszLastCategory; +}; + +} // namespace vgui + +#endif // MENU_H |