iPlug2 - C++ Audio Plug-in Framework
IGraphicsLiveEdit.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 
18 #ifndef NDEBUG
19 
20 #include "IControl.h"
21 #include <fstream>
22 
23 BEGIN_IPLUG_NAMESPACE
24 BEGIN_IGRAPHICS_NAMESPACE
25 
32 {
33 public:
34  IGraphicsLiveEdit(bool mouseOversEnabled)
35  : IControl(IRECT())
36  , mMouseOversEnabled(mouseOversEnabled)
37  , mGridSize(10)
38  {
39  mTargetRECT = mRECT;
40  }
41 
43  {
44  GetUI()->EnableMouseOver(mMouseOversEnabled); // Set it back to what it was
45  }
46 
47  void OnInit() override
48  {
49  GetUI()->EnableMouseOver(true);
50  }
51 
52  void OnMouseDown(float x, float y, const IMouseMod& mod) override
53  {
54  int c = GetUI()->GetMouseControlIdx(x, y, true);
55 
56  if (c > 0)
57  {
58  IControl* pControl = GetUI()->GetControl(c);
59  mMouseDownRECT = pControl->GetRECT();
60  mMouseDownTargetRECT = pControl->GetTargetRECT();
61 
62  if(!mod.S)
63  mSelectedControls.Empty();
64 
65  mSelectedControls.Add(pControl);
66 
67  if(mod.A)
68  {
69  GetUI()->AttachControl(new PlaceHolder(mMouseDownRECT));
70  mClickedOnControl = GetUI()->NControls() - 1;
71  mMouseClickedOnResizeHandle = false;
72  }
73  else if (mod.R)
74  {
75  mClickedOnControl = c;
76  GetUI()->CreatePopupMenu(*this, mRightClickOnControlMenu, x, y);
77  }
78  else
79  {
80  mClickedOnControl = c;
81 
82  if(GetHandleRect(mMouseDownRECT).Contains(x, y))
83  {
84  mMouseClickedOnResizeHandle = true;
85  }
86  }
87  }
88  else if(mod.R)
89  {
90  GetUI()->CreatePopupMenu(*this, mRightClickOutsideControlMenu, x, y);
91  }
92  else
93  {
94  mSelectedControls.Empty();
95  mDragRegion.L = mDragRegion.R = x;
96  mDragRegion.T = mDragRegion.B = y;
97  }
98  }
99 
100  void OnMouseUp(float x, float y, const IMouseMod& mod) override
101  {
102  if(mMouseClickedOnResizeHandle)
103  {
104  IControl* pControl = GetUI()->GetControl(mClickedOnControl);
105  IRECT r = pControl->GetRECT();
106  float w = r.R - r.L;
107  float h = r.B - r.T;
108 
109  if(w < 0.f || h < 0.f)
110  {
111  pControl->SetRECT(mMouseDownRECT);
112  pControl->SetTargetRECT(mMouseDownTargetRECT);
113  }
114  }
115  mClickedOnControl = -1;
116  mMouseClickedOnResizeHandle = false;
118 
119  mDragRegion = IRECT();
120  }
121 
122  void OnMouseDblClick(float x, float y, const IMouseMod& mod) override
123  {
124  }
125 
126  void OnMouseOver(float x, float y, const IMouseMod& mod) override
127  {
128  int c = GetUI()->GetMouseControlIdx(x, y, true);
129  if (c > 0)
130  {
131  IRECT cr = GetUI()->GetControl(c)->GetRECT();
132  IRECT h = GetHandleRect(cr);
133 
134  if(h.Contains(x, y))
135  {
136  GetUI()->SetMouseCursor(ECursor::SIZENWSE);
137  return;
138  }
139  else
140  GetUI()->SetMouseCursor(ECursor::HAND);
141  }
142  else
143  GetUI()->SetMouseCursor(ECursor::ARROW);
144  }
145 
146  void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) override
147  {
148  float mouseDownX, mouseDownY;
149  GetUI()->GetMouseDownPoint(mouseDownX, mouseDownY);
150 
151  if(mClickedOnControl > 0)
152  {
153  IControl* pControl = GetUI()->GetControl(mClickedOnControl);
154 
155  if(mMouseClickedOnResizeHandle)
156  {
157  IRECT r = pControl->GetRECT();
158  r.R = SnapToGrid(mMouseDownRECT.R + (x - mouseDownX));
159  r.B = SnapToGrid(mMouseDownRECT.B + (y - mouseDownY));
160 
161  if(r.R < mMouseDownRECT.L +mGridSize) r.R = mMouseDownRECT.L+mGridSize;
162  if(r.B < mMouseDownRECT.T +mGridSize) r.B = mMouseDownRECT.T+mGridSize;
163 
164  GetUI()->SetControlSize(mClickedOnControl, r.W(), r.H());
165  }
166  else
167  {
168  const float x1 = SnapToGrid(mMouseDownRECT.L + (x - mouseDownX));
169  const float y1 = SnapToGrid(mMouseDownRECT.T + (y - mouseDownY));
170 
171  GetUI()->SetControlPosition(mClickedOnControl, x1, y1);
172  }
173  }
174  else
175  {
176  float mouseDownX, mouseDownY;
177  GetUI()->GetMouseDownPoint(mouseDownX, mouseDownY);
178  mDragRegion.L = x < mouseDownX ? x : mouseDownX;
179  mDragRegion.R = x < mouseDownX ? mouseDownX : x;
180  mDragRegion.T = y < mouseDownY ? y : mouseDownY;
181  mDragRegion.B = y < mouseDownY ? mouseDownY : y;
182 
183  GetUI()->ForStandardControlsFunc([&](IControl* pControl) {
184  if(mDragRegion.Contains(pControl->GetRECT())) {
185  if(mSelectedControls.FindR(pControl) == -1)
186  mSelectedControls.Add(pControl);
187  }
188  else {
189  int idx = mSelectedControls.FindR(pControl);
190  if(idx > -1)
191  mSelectedControls.Delete(idx);
192  }
193  });
194  }
195  }
196 
197  bool OnKeyDown(float x, float y, const IKeyPress& key) override
198  {
200 
201  if(key.VK == kVK_BACK || key.VK == kVK_DELETE)
202  {
203  if(mSelectedControls.GetSize())
204  {
205  for(int i = 0; i < mSelectedControls.GetSize(); i++)
206  {
207  IControl* pControl = mSelectedControls.Get(i);
208  GetUI()->RemoveControl(pControl);
209  }
210 
211  mSelectedControls.Empty();
213 
214  return true;
215  }
216  }
217 
218  return false;
219  }
220 
221  void OnPopupMenuSelection(IPopupMenu* pSelectedMenu, int valIdx) override
222  {
223  if(pSelectedMenu && pSelectedMenu == &mRightClickOutsideControlMenu)
224  {
225  auto idx = pSelectedMenu->GetChosenItemIdx();
226  float x, y;
227  GetUI()->GetMouseDownPoint(x, y);
228  IRECT b = IRECT(x, y, x + 100.f, y + 100.f);
229 
230  switch(idx)
231  {
232  case 0:
233  GetUI()->AttachControl(new PlaceHolder(b));
234  break;
235  default:
236  break;
237  }
238  }
239 
240  if (pSelectedMenu && pSelectedMenu == &mRightClickOnControlMenu)
241  {
242  auto idx = pSelectedMenu->GetChosenItemIdx();
243 
244  switch (idx)
245  {
246  case 0:
247  mSelectedControls.Empty();
248  GetUI()->RemoveControl(mClickedOnControl);
249  mClickedOnControl = -1;
250  break;
251  default:
252  break;
253  }
254 
255  }
256  }
257 
258  void Draw(IGraphics& g) override
259  {
260  IBlend b {EBlend::Add, 0.25f};
261  g.DrawGrid(mGridColor, g.GetBounds(), mGridSize, mGridSize, &b);
262 
263  for(int i = 1; i < g.NControls(); i++)
264  {
265  IControl* pControl = g.GetControl(i);
266  IRECT cr = pControl->GetRECT();
267 
268  if(pControl->IsHidden())
269  g.DrawDottedRect(COLOR_RED, cr);
270  else if(pControl->IsDisabled())
271  g.DrawDottedRect(COLOR_GREEN, cr);
272  else
273  g.DrawDottedRect(COLOR_BLUE, cr);
274 
275  IRECT h = GetHandleRect(cr);
276  g.FillTriangle(mRectColor, h.L, h.B, h.R, h.B, h.R, h.T);
277  g.DrawTriangle(COLOR_BLACK, h.L, h.B, h.R, h.B, h.R, h.T);
278  }
279 
280  for(int i = 0; i< mSelectedControls.GetSize(); i++)
281  {
282  g.DrawDottedRect(COLOR_WHITE, mSelectedControls.Get(i)->GetRECT());
283  }
284 
285  if(!mDragRegion.Empty())
286  {
287  g.DrawDottedRect(COLOR_RED, mDragRegion);
288  }
289  }
290 
291  void OnResize() override
292  {
293  mSelectedControls.Empty();
294  mRECT = GetUI()->GetBounds();
295  SetTargetRECT(mRECT);
296  }
297 
298  bool IsDirty() override { return true; }
299 
300  inline IRECT GetHandleRect(const IRECT& r)
301  {
302  return IRECT(r.R - RESIZE_HANDLE_SIZE, r.B - RESIZE_HANDLE_SIZE, r.R, r.B);
303  }
304 
305  inline float SnapToGrid(float input)
306  {
307  if (mGridSize > 1)
308  return (float) std::round(input / (float) mGridSize) * mGridSize;
309  else
310  return input;
311  }
312 
313 private:
314  IPopupMenu mRightClickOutsideControlMenu {"Outside Control", {"Add Place Holder"}};
315  IPopupMenu mRightClickOnControlMenu{ "On Control", {"Delete Control"} };
316 
317  bool mMouseOversEnabled = false;
318  bool mMouseClickedOnResizeHandle = false;
319  bool mMouseIsDragging = false;
320  WDL_String mErrorMessage;
321  WDL_PtrList<IControl> mSelectedControls;
322 
323  IColor mGridColor = COLOR_WHITE;
324  IColor mRectColor = COLOR_WHITE;
325  static const int RESIZE_HANDLE_SIZE = 10;
326 
327  IRECT mMouseDownRECT;
328  IRECT mMouseDownTargetRECT;
329  IRECT mDragRegion;
330 
331  float mGridSize = 10;
332  int mClickedOnControl = -1;
333 };
334 
335 END_IGRAPHICS_NAMESPACE
336 END_IPLUG_NAMESPACE
337 
338 #endif // !NDEBUG
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.
bool Contains(const IRECT &rhs) const
Returns true if this IRECT completely contains rhs.
The lowest level base class of an IGraphics control.
Definition: IControl.h:42
Used to manage a rectangular area, independent of draw class/platform.
virtual void DrawGrid(const IColor &color, const IRECT &bounds, float gridSizeH, float gridSizeV, const IBlend *pBlend=0, float thickness=1.f)
Draw a grid to the graphics context.
Definition: IGraphics.cpp:2410
void SetControlSize(int idx, float w, float h)
Resize a control, redrawing the interface correctly.
Definition: IGraphics.cpp:216
Used to manage composite/blend operations, independent of draw class/platform.
virtual ECursor SetMouseCursor(ECursor cursorType=ECursor::ARROW)
Sets the mouse cursor to one of ECursor (implementations should return the result of the base impleme...
Definition: IGraphics.h:805
void ReleaseMouseCapture()
Used to tell the graphics context to stop tracking mouse interaction with a control.
Definition: IGraphics.cpp:1285
const IRECT & GetTargetRECT() const
Get the rectangular mouse tracking target area, within the graphics context for this control...
Definition: IControl.h:313
virtual void DrawDottedRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f, float dashLen=2.f)
Draw a dotted rectangle to the graphics context.
Definition: IGraphics.cpp:2517
Used to manage mouse modifiers i.e.
void OnMouseDblClick(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse double click event on this control.
A control to use as a placeholder during development.
Definition: IControl.h:2060
IControl * GetControl(int idx)
Definition: IGraphics.h:1311
void SetControlPosition(int idx, float x, float y)
Reposition a control, redrawing the interface correctly.
Definition: IGraphics.cpp:208
Used to manage color data, independent of draw class/platform.
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
This file contains the base IControl implementation, along with some base classes for specific types ...
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
void SetAllControlsDirty()
Calls SetDirty() on every control.
Definition: IGraphics.cpp:543
float R
Right side of the rectangle (X + W)
bool IsHidden() const
Definition: IControl.h:349
bool IsDisabled() const
Definition: IControl.h:356
void OnPopupMenuSelection(IPopupMenu *pSelectedMenu, int valIdx) override
Implement this method to handle popup menu selection after IGraphics::CreatePopupMenu/IControl::Promp...
void RemoveControl(int idx)
Remove a control at a particular index, (frees memory).
Definition: IGraphics.cpp:161
void SetRECT(const IRECT &bounds)
Set the rectangular draw area for this control, within the graphics context.
Definition: IControl.h:309
float H() const
const IRECT & GetRECT() const
Get the rectangular draw area for this control, within the graphics context.
Definition: IControl.h:305
void CreatePopupMenu(IControl &control, IPopupMenu &menu, const IRECT &bounds, int valIdx=0)
Shows a pop up/contextual menu in relation to a rectangular region of the graphics context...
Definition: IGraphics.cpp:1937
float W() const
void ForStandardControlsFunc(std::function< void(IControl *pControl)> func)
For all standard controls in the main control stack perform a function.
Definition: IGraphics.cpp:495
A class for setting the contents of a pop up menu.
IControl(const IRECT &bounds, int paramIdx=kNoParameter, IActionFunction actionFunc=nullptr)
Constructor.
Definition: IControl.cpp:81
bool Empty() const
void GetMouseDownPoint(float &x, float &y) const
Get the x, y position of the last mouse down message.
Definition: IGraphics.h:1530
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
void OnResize() override
Called when IControl is constructed or resized using SetRect().
IRECT GetBounds() const
Returns an IRECT that represents the entire UI bounds This is useful for programatically arranging UI...
Definition: IGraphics.h:1154
bool IsDirty() override
Called at each display refresh by the IGraphics draw loop, after IControl::Animate(), to determine if the control is marked as dirty.
void Draw(IGraphics &g) override
Draw the control to the graphics context.
A control to enable live modification of control layout in an IGraphics context in debug builds This ...
virtual void DrawTriangle(const IColor &color, float x1, float y1, float x2, float y2, float x3, float y3, const IBlend *pBlend=0, float thickness=1.f)
Draw a triangle to the graphics context.
Definition: IGraphics.cpp:2468
int NControls() const
Definition: IGraphics.h:1387
void SetTargetRECT(const IRECT &bounds)
Set the rectangular mouse tracking target area, within the graphics context for this control...
Definition: IControl.h:317
IGraphics * GetUI()
Definition: IControl.h:452
bool OnKeyDown(float x, float y, const IKeyPress &key) override
Implement this method to respond to a key down event on this control.
float L
Left side of the rectangle (X)
void EnableMouseOver(bool enable)
Definition: IGraphics.h:1516
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
IControl * AttachControl(IControl *pControl, int ctrlTag=kNoTag, const char *group="")
Attach an IControl to the graphics context and add it to the top of the control stack.
Definition: IGraphics.cpp:298
Used for key press info, such as ASCII representation, virtual key (mapped to win32 codes) and modifi...
Definition: IPlugStructs.h:612
float T
Top of the rectangle (Y)
virtual void FillTriangle(const IColor &color, float x1, float y1, float x2, float y2, float x3, float y3, const IBlend *pBlend=0)
Fill a triangle with a color.
Definition: IGraphics.cpp:2540
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
float B
Bottom of the rectangle (Y + H)