iPlug2 - C++ Audio Plug-in Framework
IPopupMenuControl.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the iPlug 2 library. Copyright (C) the iPlug 2 developers.
5 
6  See LICENSE.txt for more info.
7 
8  ==============================================================================
9 */
10 
11 #pragma once
12 
19 #include "IControl.h"
20 
21 BEGIN_IPLUG_NAMESPACE
22 BEGIN_IGRAPHICS_NAMESPACE
23 
30 {
31  class MenuPanel;
32 
33 public:
36  {
37  kCollapsed = 0,
38  kExpanding,
39  kExpanded,
40  kCollapsing,
41  kFlickering, // on click
42  kSubMenuAppearing, // when a submenu appears, only that menu is faded in
43  kIdling,
44  };
45 
46  enum EArrowDir
47  {
48  kNorth,
49  kEast,
50  kSouth,
51  kWest
52  };
53 
59  IPopupMenuControl(int paramIdx = kNoParameter, IText text = IText(16), IRECT collapsedBounds = IRECT(), IRECT expandedBounds = IRECT());
60  virtual ~IPopupMenuControl();
61 
62  //IControl
63  void Draw(IGraphics& g) override;
64  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
65  void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) override;
66  void OnMouseOver(float x, float y, const IMouseMod& mod) override;
67  void OnMouseOut() override;
68  void OnMouseWheel(float x, float y, const IMouseMod& mod, float d) override;
69  void OnEndAnimation() override;
70 
71  //IPopupMenuControl
72 
76  void CalculateMenuPanels(float x, float y);
77 
79  virtual void DrawCalloutArrow(IGraphics& g, const IRECT& bounds, IBlend* pBlend);
81  virtual void DrawSubMenuCalloutArrow(IGraphics& g, const IRECT& bounds, IBlend* pBlend);
83  virtual void DrawPanelBackground(IGraphics& g, MenuPanel* panel);
85  virtual void DrawPanelShadow(IGraphics& g, MenuPanel* panel);
87  virtual void DrawCellBackground(IGraphics& g, const IRECT& bounds, const IPopupMenu::Item* pItem, bool sel, IBlend* pBlend);
89  virtual void DrawCellText(IGraphics& g, const IRECT& bounds, const IPopupMenu::Item* pItem, bool sel, IBlend* pBlend);
91  virtual void DrawTick(IGraphics& g, const IRECT& bounds, const IPopupMenu::Item* pItem, bool sel, IBlend* pBlend);
93  virtual void DrawSubMenuArrow(IGraphics& g, const IRECT& bounds, const IPopupMenu::Item* pItem, bool sel, IBlend* pBlend);
95  virtual void DrawUpArrow(IGraphics& g, const IRECT& bounds, bool sel, IBlend* pBlend);
97  virtual void DrawDownArrow(IGraphics& g, const IRECT& bounds, bool sel, IBlend* pBlend);
99  virtual void DrawSeparator(IGraphics& g, const IRECT& bounds, IBlend* pBlend);
100 
102  void SetPanelColor(IColor color) { mPanelBackgroundColor = color; }
104  void SetCellBackgroundColor(IColor color) { mCellBackGroundColor = color; }
106  void SetItemMouseoverColor(IColor color) { mItemMouseoverColor = color; }
108  void SetItemColor(IColor color) { mItemColor = color; }
110  void SetDisabledItemColor(IColor color) { mDisabledItemColor = color; }
112  void SetSeparatorColor(IColor color) { mSeparatorColor = color; }
117  void SetShiftForSubmenus(float distance) { mMenuShift = distance; }
119  void SetMenuForcedSouth(bool isForcedSouth) { mForcedSouth = isForcedSouth;}
120 
124  void CreatePopupMenu(IPopupMenu& menu, const IRECT& anchorArea);
125 
127  bool GetExpanded() const { return mState == kExpanded; }
128 
130  EPopupState GetState() const { return mState; }
131 
133  void SetExpandedBounds(const IRECT& bounds) { mSpecifiedExpandedBounds = bounds; }
134 
136  void SetCallout(bool callout) { mCallOut = callout; }
137 
139  void SetMaxBounds(const IRECT& bounds) { mMaxBounds = bounds; }
140 
141 private:
143  IRECT GetLargestCellRectForMenu(IPopupMenu& menu, float x, float y) const;
144 
149  void GetPanelDimensions(IPopupMenu&menu, float& width, float& height) const;
150 
152  void Expand(const IRECT& bounds);
153 
155  virtual void CollapseEverything();
156 
157 private:
158 
160  class MenuPanel
161  {
162  public:
163  MenuPanel(IPopupMenuControl& owner, IPopupMenu& menu, float x, float y, int parentIdx);
164  ~MenuPanel();
165 
166  MenuPanel(const MenuPanel&) = delete;
167  MenuPanel& operator=(const MenuPanel&) = delete;
168 
170  float CellWidth() const { return mSingleCellBounds.W(); }
171 
173  float CellHeight() const { return mSingleCellBounds.H(); }
174 
175  void ScrollUp() { mScrollItemOffset--; mScrollItemOffset = Clip(mScrollItemOffset, 0, mCellBounds.GetSize()-1); }
176 
177  void ScrollDown() { mScrollItemOffset++; mScrollItemOffset = Clip(mScrollItemOffset, 0, mMenu.NItems()-mCellBounds.GetSize()); }
178 
183  IRECT* HitTestCells(float x, float y) const;
184 
185  public:
186  IPopupMenu& mMenu; // The IPopupMenu that this MenuPanel is displaying
187  WDL_PtrList<IRECT> mCellBounds; // The size of this array will always correspond to the number of items in the top level of the menu
188 
189  IRECT mRECT; // The drawing bounds for this panel
190  IRECT mTargetRECT; // The mouse target bounds for this panel
191  int mScrollMaxRows = 0; // 0 when no scroll
192  bool mShouldDraw = true; // boolean determining whether this panel should be drawn
193  IBlend mBlend = { EBlend::Default, 0.f }; // blend for sub panels appearing
194 
195  IRECT mSingleCellBounds; // The dimensions of the largest cell for the menu
196  IRECT* mHighlightedCell = nullptr; // A pointer to one of the IRECTs in mCellBounds, if one should be highlighted
197  IRECT* mClickedCell = nullptr; // A pointer to one of the IRECTs in mCellBounds, if one has been clicked
198  int mParentIdx = 0; // An index into the IPopupMenuControl::mMenuPanels lists, representing the parent menu panel
199  bool mScroller = false;
200  int mScrollItemOffset = 0;
201 
202 #ifndef IGRAPHICS_NANOVG
203  ILayerPtr mShadowLayer;
204 #endif
205  };
206 
207  WDL_PtrList<MenuPanel> mMenuPanels; // An array of ptrs to MenuPanel objects for every panel, expands as sub menus are revealed, contents deleted when the menu is dismissed
208  MenuPanel* mActiveMenuPanel = nullptr; // A pointer to the active MenuPanel within the mMenuPanels array
209  MenuPanel* mAppearingMenuPanel = nullptr; // A pointer to a MenuPanel that's in the process of fading in
210  EPopupState mState = kCollapsed; // The state of the pop-up, mainly used for animation
211  IRECT* mMouseCellBounds = nullptr;
212  IPopupMenu* mMenu = nullptr; // Pointer to the main IPopupMenu, that this control is visualising. This control does not own the menu.
213 
214  int mMaxColumnItems = 0; // How long the list can get before adding a new column - 0 equals no limit
215  bool mScrollIfTooBig = true; // If the menu is higher than the graphics context, should it scroll or should it start a new column
216  bool mCallOut = false; // set true if popup should be outside of bounds (i.e. on a tablet touchscreen interface)
217  bool mMenuHasSubmenu = false; // Gets automatically set to true in CreatePopupMenu() if *mMenu contains any submenus... false if not.
218  bool mForcedSouth = true; // if set true, a menu in the lower half of the GUI will appear below it's control if there is enough room for it.
219  bool mSubmenuOnRight = true; // If set true, the submenu will be drawn on the right of the parent menu.... on the left if false.
220  bool mSubMenuOpened = false; // Is set true when a submenu panel is open and false when menu is collapsed.
221 
222  float mCellGap = 2.f; // The gap between cells in pixels
223  float mSeparatorSize = 2.; // The size in pixels of a separator. This could be width or height
224  float mRoundness = 5.f; // The roundness of the corners of the menu panel backgrounds
225  float mDropShadowSize = 10.f; // The size in pixels of the drop shadow
226  float mOpacity = 0.95f; // The opacity of the menu panel backgrounds when fully faded in
227  float mMenuShift = 0.f; // The distance in pixels the main menu is shifted to make room for submenus (only if one exist). Set by SetShiftForSubmenus()
228 
229  const float TEXT_HPAD = 5.; // The amount of horizontal padding on either side of cell text in pixels
230  const float TICK_SIZE = 10.; // The size of the area on the left of the cell where a tick mark appears on checked items - actual
231  const float ARROW_SIZE = 8; // The width of the area on the right of the cell where an arrow appears for new submenus
232  const float PAD = 5.; // How much white space between the background and the cells
233  const float CALLOUT_SPACE = 8; // The space between start bounds and callout
234  IRECT mAnchorArea; // The area where the menu was triggered; menu will be adjacent, but won't occupy it.
235  EArrowDir mCalloutArrowDir = kEast;
236  IRECT mCalloutArrowBounds; // The rectangle in which the CallOut arrow is drawn.
237  IRECT mSubMenuCalloutArrowBounds; // The rectangle in which the CallOut arrow for a submenus is drawn.
238 
239  IRECT mMaxBounds; // if view is only showing a part of the graphics context, we need to know because menus can't go there
240 
241  IColor mPanelBackgroundColor = COLOR_WHITE;
242  IColor mCellBackGroundColor = COLOR_BLUE;
243  IColor mItemMouseoverColor = COLOR_WHITE;
244  IColor mItemColor = COLOR_BLACK;
245  IColor mDisabledItemColor = COLOR_GRAY;
246  IColor mSeparatorColor = COLOR_MID_GRAY;
247 
248 protected:
249  IRECT mSpecifiedCollapsedBounds;
250  IRECT mSpecifiedExpandedBounds;
251 };
252 
253 END_IGRAPHICS_NAMESPACE
254 END_IPLUG_NAMESPACE
virtual void DrawUpArrow(IGraphics &g, const IRECT &bounds, bool sel, IBlend *pBlend)
Override this method to change the way a scroll up cell&#39;s arrow is drawn.
void SetMaxBounds(const IRECT &bounds)
Set the bounds that the menu can potentially occupy, if not the full graphics context.
The lowest level base class of an IGraphics control.
Definition: IControl.h:42
void SetPanelColor(IColor color)
Call this to set the Panel color.
Used to manage a rectangular area, independent of draw class/platform.
Used to manage composite/blend operations, independent of draw class/platform.
EPopupState
An enumerated list, that is used to determine the state of the menu, mainly for animations.
Used to manage mouse modifiers i.e.
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
void OnMouseOut() override
Implement this method to respond to a mouseout event on this control.
Used to manage color data, independent of draw class/platform.
A class to specify an item of a pop up menu.
virtual void DrawTick(IGraphics &g, const IRECT &bounds, const IPopupMenu::Item *pItem, bool sel, IBlend *pBlend)
Override this method to change the way a checked cell&#39;s "tick" is drawn.
This file contains the base IControl implementation, along with some base classes for specific types ...
void CreatePopupMenu(IPopupMenu &menu, const IRECT &anchorArea)
Call this to create a pop-up menu.
bool GetExpanded() const
void SetExpandedBounds(const IRECT &bounds)
Force the menu to open with a specific bounds - useful on small screens for making it modal...
EPopupState GetState() const
virtual void DrawPanelBackground(IGraphics &g, MenuPanel *panel)
Override this method to change the background of the pop-up menu panel.
A base control for a pop-up menu/drop-down list that stays within the bounds of the IGraphics context...
void SetCellBackgroundColor(IColor color)
Call this to set the Cell color when mouse is over it.
A class for setting the contents of a pop up menu.
IText is used to manage font and text/text entry style for a piece of text on the UI...
void OnMouseWheel(float x, float y, const IMouseMod &mod, float d) override
Implement this method to respond to a mouse wheel event on this control.
virtual void DrawSubMenuCalloutArrow(IGraphics &g, const IRECT &bounds, IBlend *pBlend)
Override this method to change the way Callout arrows for Submenus are drawn.
virtual void DrawCellText(IGraphics &g, const IRECT &bounds, const IPopupMenu::Item *pItem, bool sel, IBlend *pBlend)
Override this method to change the way a cell&#39;s text is drawn.
void SetItemColor(IColor color)
Call this to set the color of enabled text items, ticks and arrows on menu panels.
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
void SetShiftForSubmenus(float distance)
Sets the amount the main menu is shifted to make room for submenus.
void SetItemMouseoverColor(IColor color)
Call this to set the mouseover color for text, tick, and arrows on menu panels.
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.
void CalculateMenuPanels(float x, float y)
Called as the user moves the mouse around, in order to work out which menu panel should be on the scr...
virtual void DrawPanelShadow(IGraphics &g, MenuPanel *panel)
Override this method to change the shadow of the pop-up menu panel.
virtual void DrawSubMenuArrow(IGraphics &g, const IRECT &bounds, const IPopupMenu::Item *pItem, bool sel, IBlend *pBlend)
Override this method to change the way a submenu cell&#39;s arrow is drawn.
void Draw(IGraphics &g) override
Draw the control to the graphics context.
virtual void DrawCalloutArrow(IGraphics &g, const IRECT &bounds, IBlend *pBlend)
Override this method to change the way Callout arrows are drawn.
void SetCallout(bool callout)
Set if the menu is shifted away from where the control is created with a callout arrow (for fat finge...
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
void SetMenuForcedSouth(bool isForcedSouth)
If set true, the menu (kNorth) is forced to appear below it&#39;s control(kSouth) when it would normally ...
void SetDisabledItemColor(IColor color)
Call this to set the text color of disabled items on menu panels.
virtual void DrawSeparator(IGraphics &g, const IRECT &bounds, IBlend *pBlend)
Override this method to change the way a cell separator is drawn.
virtual void DrawDownArrow(IGraphics &g, const IRECT &bounds, bool sel, IBlend *pBlend)
Override this method to change the way a scroll Down cell&#39;s arrow is drawn.
void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod) override
Implement this method to respond to a mouse drag event on this control.
void SetSeparatorColor(IColor color)
Call this to set the Separator color on menu panels.
std::unique_ptr< ILayer > ILayerPtr
ILayerPtr is a managed pointer for transferring the ownership of layers.
IPopupMenuControl(int paramIdx=kNoParameter, IText text=IText(16), IRECT collapsedBounds=IRECT(), IRECT expandedBounds=IRECT())
Create a new IPopupMenuControl.
virtual void DrawCellBackground(IGraphics &g, const IRECT &bounds, const IPopupMenu::Item *pItem, bool sel, IBlend *pBlend)
Override this method to change the way a cell&#39;s background is drawn.