iPlug2 - C++ Audio Plug-in Framework
IControl.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 #include <cstring>
19 #include <cstdlib>
20 #include <vector>
21 #include <unordered_map>
22 
23 #if defined VST3_API || defined VST3C_API
24 #undef stricmp
25 #undef strnicmp
26 #include "pluginterfaces/vst/ivstcontextmenu.h"
27 #include "base/source/fobject.h"
28 #endif
29 
30 #include "IPlugPlatform.h"
31 
32 #include "wdlstring.h"
33 #include "ptrlist.h"
34 
35 #include "IGraphics.h"
36 
37 BEGIN_IPLUG_NAMESPACE
38 BEGIN_IGRAPHICS_NAMESPACE
39 
42 class IControl
43 #if defined VST3_API || defined VST3C_API
44 : public Steinberg::Vst::IContextMenuTarget
45 , public Steinberg::FObject
46 #endif
47 {
48 public:
56  IControl(const IRECT& bounds, int paramIdx = kNoParameter, IActionFunction actionFunc = nullptr);
57 
65  IControl(const IRECT& bounds, const std::initializer_list<int>& params, IActionFunction actionFunc = nullptr);
66 
73  IControl(const IRECT& bounds, IActionFunction actionFunc);
74 
75  IControl(const IControl&) = delete;
76  void operator=(const IControl&) = delete;
77 
79  virtual ~IControl() {}
80 
85  virtual void OnMouseDown(float x, float y, const IMouseMod& mod);
86 
91  virtual void OnMouseUp(float x, float y, const IMouseMod& mod) {}
92 
99  virtual void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) {}
100 
105  virtual void OnMouseDblClick(float x, float y, const IMouseMod& mod);
106 
112  virtual void OnMouseWheel(float x, float y, const IMouseMod& mod, float d) {};
113 
118  virtual bool OnKeyDown(float x, float y, const IKeyPress& key) { return false; }
119 
124  virtual bool OnKeyUp(float x, float y, const IKeyPress& key) { return false; }
125 
130  virtual void OnMouseOver(float x, float y, const IMouseMod& mod);
131 
133  virtual void OnMouseOut();
134 
139  virtual void OnTouchCancelled(float x, float y, const IMouseMod& mod) {}
140 
142  virtual void OnDrop(const char* str) {};
143 
145  virtual void OnRescale() {}
146 
148  virtual void OnResize() {}
149 
151  virtual void OnInit() {}
152 
154  virtual void OnAttached() {}
155 
157  virtual void OnMsgFromDelegate(int msgTag, int dataSize, const void* pData) {};
158 
160  virtual void OnMidi(const IMidiMsg& msg) {};
161 
163  virtual bool OnGesture(const IGestureInfo& info);
164 
166  virtual void CreateContextMenu(IPopupMenu& contextMenu) {}
167 
171  virtual void OnPopupMenuSelection(IPopupMenu* pSelectedMenu, int valIdx);
172 
176  virtual void OnTextEntryCompletion(const char* str, int valIdx) {}
177 
179  virtual void OnContextSelection(int itemSelected) {}
180 
183  virtual void Draw(IGraphics& g) = 0;
184 
187  virtual void DrawPTHighlight(IGraphics& g);
188 
191  void PromptUserInput(int valIdx = 0);
192 
196  void PromptUserInput(const IRECT& bounds, int valIdx = 0);
197 
201  inline IControl* SetActionFunction(IActionFunction actionFunc) { mActionFunc = actionFunc; return this; }
202 
206  inline IControl* SetAnimationEndActionFunction(IActionFunction actionFunc) { mAnimationEndActionFunc = actionFunc; return this; }
207 
210  inline void SetTooltip(const char* str) { mTooltip.Set(str); }
211 
213  inline const char* GetTooltip() const { return mTooltip.Get(); }
214 
219  int GetParamIdx(int valIdx = 0) const;
220 
225  virtual void SetParamIdx(int paramIdx, int valIdx = 0);
226 
230  int LinkedToParam(int paramIdx) const;
231 
233  int NVals() const { return (int) mVals.size(); }
234 
239  virtual int GetValIdxForPos(float x, float y) const { return mVals.size() == 1 ? 0 : kNoValIdx; }
240 
243  const IParam* GetParam(int valIdx = 0) const;
244 
249  virtual void SetValueFromDelegate(double value, int valIdx = 0);
250 
255  virtual void SetValueFromUserInput(double value, int valIdx = 0);
256 
260  virtual void SetValueToDefault(int valIdx = kNoValIdx);
261 
265  virtual void SetValue(double value, int valIdx = 0);
266 
270  double GetValue(int valIdx = 0) const;
271 
274  void SetGroup(const char* groupName) { mGroup.Set(groupName); }
275 
278  const char* GetGroup() const { return mGroup.Get(); }
279 
282  const IText& GetText() const { return mText; }
283 
286  virtual void SetText(const IText& txt) { mText = txt; }
287 
290  void SetBlend(const IBlend& blend) { mBlend = blend; }
291 
293  IBlend GetBlend() const { return mBlend; }
294 
297  int GetTextEntryLength() const { return mTextEntryLength; }
298 
301  void SetTextEntryLength(int len) { mTextEntryLength = len; }
302 
305  const IRECT& GetRECT() const { return mRECT; }
306 
309  void SetRECT(const IRECT& bounds) { mRECT = bounds; mMouseIsOver = false; OnResize(); }
310 
313  const IRECT& GetTargetRECT() const { return mTargetRECT; } // The mouse target area (default = draw area).
314 
317  void SetTargetRECT(const IRECT& bounds) { mTargetRECT = bounds; mMouseIsOver = false; }
318 
321  void SetTargetAndDrawRECTs(const IRECT& bounds) { mRECT = mTargetRECT = bounds; mMouseIsOver = false; OnResize(); }
322 
326  virtual void SetPosition(float x, float y);
327 
331  virtual void SetSize(float w, float h);
332 
336  void SetPTParameterHighlight(bool isHighlighted, int color);
337 
342  bool GetMouseDblAsSingleClick() const { return mDblAsSingleClick; }
343 
346  virtual void Hide(bool hide);
347 
349  bool IsHidden() const { return mHide; }
350 
353  virtual void SetDisabled(bool disable);
354 
356  bool IsDisabled() const { return mDisabled; }
357 
360  void SetMouseOverWhenDisabled(bool allow) { mMouseOverWhenDisabled = allow; }
361 
364  void SetMouseEventsWhenDisabled(bool allow) { mMouseEventsWhenDisabled = allow; }
365 
367  bool GetMouseOverWhenDisabled() const { return mMouseOverWhenDisabled; }
368 
370  bool GetMouseEventsWhenDisabled() const { return mMouseEventsWhenDisabled; }
371 
373  bool GetIgnoreMouse() const { return mIgnoreMouse; }
374 
376  bool GetPromptShowsParamLabel() const { return mPromptShowsParamLabel; }
377 
379  void SetPromptShowsParamLabel(bool enable) { mPromptShowsParamLabel = enable; }
380 
385  virtual bool IsHit(float x, float y) const { return mTargetRECT.Contains(x, y); }
386 
391  virtual void SetDirty(bool triggerAction = true, int valIdx = kNoValIdx);
392 
393  /* Set the control clean, i.e. Called by IGraphics draw loop after control has been drawn */
394  virtual void SetClean() { mDirty = false; }
395 
396  /* Called at each display refresh by the IGraphics draw loop, triggers the control's AnimationFunc if it is set */
397  void Animate();
398 
401  virtual bool IsDirty();
402 
405  void DisablePrompt(bool disable) { mDisablePrompt = disable; }
406 
408  virtual void OnGUIIdle() {}
409 
411  int GetTag() const { return GetUI()->GetControlTag(this); }
412 
414  void SetWantsMidi(bool enable = true) { mWantsMidi = enable; }
415 
417  bool GetWantsMidi() const { return mWantsMidi; }
418 
420  void SetWantsMultiTouch(bool enable = true) { mWantsMultiTouch = enable; }
421 
423  bool GetWantsMultiTouch() const { return mWantsMultiTouch; }
424 
428  IControl* AttachGestureRecognizer(EGestureType type, IGestureFunc func);
429 
431  bool GetWantsGestures() const { return mGestureFuncs.size() > 0 && !mAnimationFunc; }
432 
434  EGestureType GetLastGesture() const { return mLastGesture; }
435 
439  IGEditorDelegate* GetDelegate() { return mDelegate; }
440 
443  {
444  mDelegate = &dlg;
445  mGraphics = dlg.GetUI();
446  OnInit();
447  OnResize();
448  OnRescale();
449  }
450 
452  IGraphics* GetUI() { return mGraphics; }
453 
455  const IGraphics* GetUI() const { return mGraphics; }
456 
459  bool GetMouseIsOver() const { return mMouseIsOver; }
460 
467  virtual void SnapToMouse(float x, float y, EDirection direction, const IRECT& bounds, int valIdx = -1, double minClip = 0., double maxClip = 1.);
468 
469  /* if you override this you must call the base implementation, to free mAnimationFunc */
470  virtual void OnEndAnimation();
471 
473  void StartAnimation(int duration);
474 
477  void SetAnimation(IAnimationFunction func) { mAnimationFunc = func;}
478 
482  void SetAnimation(IAnimationFunction func, int duration) { mAnimationFunc = func; StartAnimation(duration); }
483 
485  IAnimationFunction GetAnimationFunction() { return mAnimationFunc; }
486 
488  IActionFunction GetActionFunction() { return mActionFunc; }
489 
491  double GetAnimationProgress() const;
492 
494  Milliseconds GetAnimationDuration() const { return mAnimationDuration; }
495 
497  template <class T>
498  T* As() { return dynamic_cast<T*>(this); }
499 
500 #if defined VST3_API || defined VST3C_API
501  Steinberg::tresult PLUGIN_API executeMenuItem (Steinberg::int32 tag) override { OnContextSelection(tag); return Steinberg::kResultOk; }
502 #endif
503 
504 #pragma mark - IControl Member variables
505 protected:
506 
511  template<typename T, typename... Args>
512  void ForValIdx(int valIdx, T func, Args... args)
513  {
514  if (valIdx > kNoValIdx)
515  func(valIdx, args...);
516  else
517  {
518  const int nVals = NVals();
519  for (int v = 0; v < nVals; v++)
520  func(v, args...);
521  }
522  }
523 
524  IRECT mRECT;
525  IRECT mTargetRECT;
526 
528  WDL_String mGroup;
529 
530  IText mText;
531  IBlend mBlend;
532  int mTextEntryLength = DEFAULT_TEXT_ENTRY_LEN;
533  bool mDirty = true;
534  bool mHide = false;
535  bool mDisabled = false;
536  bool mDisablePrompt = true;
537  bool mDblAsSingleClick = false;
538  bool mMouseOverWhenDisabled = false;
539  bool mMouseEventsWhenDisabled = false;
540  bool mIgnoreMouse = false;
541  bool mWantsMidi = false;
542  bool mWantsMultiTouch = false;
543  bool mPromptShowsParamLabel = false;
545  bool mMouseIsOver = false;
546  WDL_String mTooltip;
547 
548  IColor mPTHighlightColor = COLOR_RED;
549  bool mPTisHighlighted = false;
550 
551  void SetNVals(int nVals)
552  {
553  assert(nVals > 0);
554  mVals.resize(nVals);
555  }
556 
557 #if defined VST3_API || defined VST3C_API
558  OBJ_METHODS(IControl, FObject)
559  DEFINE_INTERFACES
560  DEF_INTERFACE (IContextMenuTarget)
561  END_DEFINE_INTERFACES (FObject)
562  REFCOUNT_METHODS(FObject)
563 #endif
564 
565 private:
566  IGEditorDelegate* mDelegate = nullptr;
567  IGraphics* mGraphics = nullptr;
568  IActionFunction mActionFunc = nullptr;
569  IActionFunction mAnimationEndActionFunc = nullptr;
570  IAnimationFunction mAnimationFunc = nullptr;
571  TimePoint mAnimationStartTime;
572  Milliseconds mAnimationDuration;
573  std::vector<ParamTuple> mVals { {kNoParameter, 0.} };
574  std::unordered_map<EGestureType, IGestureFunc> mGestureFuncs;
575  EGestureType mLastGesture = EGestureType::Unknown;
576 };
577 
578 #pragma mark - Base Controls
579 
587 {
588 public:
591  IBitmapBase(const IBitmap& bitmap)
592  : mBitmap(bitmap)
593  {
594  }
595 
596  virtual ~IBitmapBase() {}
597 
600  void AttachIControl(IControl* pControl) { mControl = pControl; }
601 
605  {
606  int i = 1;
607 
608  if (mBitmap.N() > 1)
609  {
610  i = 1 + int(0.5 + mControl->GetValue() * (double) (mBitmap.N() - 1));
611  i = Clip(i, 1, mBitmap.N());
612  }
613  IBlend blend = mControl->GetBlend();
614  g.DrawBitmap(mBitmap, mControl->GetRECT().GetCentredInside(IRECT(0, 0, mBitmap)), i, &blend);
615  }
616 
617 protected:
618  IBitmap mBitmap;
619  IControl* mControl = nullptr;
620 };
621 
625 {
626 public:
631  IVectorBase(const IVStyle& style, bool labelInWidget = false, bool valueInWidget = false)
632  : mLabelInWidget(labelInWidget)
633  , mValueInWidget(valueInWidget)
634  {
635  SetStyle(style);
636  }
637 
641  void AttachIControl(IControl* pControl, const char* label)
642  {
643  mControl = pControl;
644  mLabelStr.Set(label);
645  }
646 
650  void SetColor(EVColor colorIdx, const IColor& color)
651  {
652  mStyle.colorSpec.mColors[static_cast<int>(colorIdx)] = color;
653  mControl->SetDirty(false);
654  }
655 
658  void SetColors(const IVColorSpec& spec)
659  {
660  mStyle.colorSpec = spec;
661  }
662 
664  const IColor& GetColor(EVColor color) const
665  {
666  return mStyle.colorSpec.GetColor(color);
667  }
668 
669  void SetLabelStr(const char* label) { mLabelStr.Set(label); mControl->SetDirty(false); }
670  void SetValueStr(const char* value) { mValueStr.Set(value); mControl->SetDirty(false); }
671  void SetWidgetFrac(float frac) { mStyle.widgetFrac = Clip(frac, 0.f, 1.f); mControl->OnResize(); mControl->SetDirty(false); }
672  void SetAngle(float angle) { mStyle.angle = Clip(angle, 0.f, 360.f); mControl->SetDirty(false); }
673  void SetShowLabel(bool show) { mStyle.showLabel = show; mControl->OnResize(); mControl->SetDirty(false); }
674  void SetShowValue(bool show) { mStyle.showValue = show; mControl->OnResize(); mControl->SetDirty(false); }
675  void SetRoundness(float roundness) { mStyle.roundness = Clip(roundness, 0.f, 1.f); mControl->SetDirty(false); }
676  void SetDrawFrame(bool draw) { mStyle.drawFrame = draw; mControl->SetDirty(false); }
677  void SetDrawShadows(bool draw) { mStyle.drawShadows = draw; mControl->SetDirty(false); }
678  void SetEmboss(bool draw) { mStyle.emboss = draw; mControl->SetDirty(false); }
679  void SetShadowOffset(float offset) { mStyle.shadowOffset = offset; mControl->SetDirty(false); }
680  void SetFrameThickness(float thickness) { mStyle.frameThickness = thickness; mControl->SetDirty(false); }
681  void SetSplashRadius(float radius) { mSplashRadius = radius * mMaxSplashRadius; }
682  void SetSplashPoint(float x, float y) { mSplashPoint.x = x; mSplashPoint.y = y; }
683  void SetShape(EVShape shape) { mShape = shape; mControl->SetDirty(false); }
684 
687  virtual void SetStyle(const IVStyle& style)
688  {
689  mStyle = style;
690  SetColors(style.colorSpec);
691  }
692 
695  IVStyle GetStyle() const { return mStyle; }
696 
700  IRECT GetAdjustedHandleBounds(IRECT handleBounds) const
701  {
702  if(mStyle.drawFrame)
703  handleBounds.Pad(- 0.5f * mStyle.frameThickness);
704 
705  if (mStyle.drawShadows)
706  handleBounds.Offset(mStyle.shadowOffset, 0, -mStyle.shadowOffset, -mStyle.shadowOffset);
707 
708  return handleBounds;
709  }
710 
714  float GetRoundedCornerRadius(const IRECT& bounds) const
715  {
716  if(bounds.W() < bounds.H())
717  return mStyle.roundness * (bounds.W() / 2.f);
718  else
719  return mStyle.roundness * (bounds.H() / 2.f);
720  }
721 
725  void DrawSplash(IGraphics& g, const IRECT& clipRegion = IRECT())
726  {
727  g.PathClipRegion(clipRegion);
728  g.FillCircle(GetColor(kHL), mSplashPoint.x, mSplashPoint.y, mSplashRadius);
729  g.PathClipRegion(IRECT());
730  }
731 
733  virtual void DrawBackground(IGraphics& g, const IRECT& rect)
734  {
735  IBlend blend = mControl->GetBlend();
736  g.FillRect(GetColor(kBG), rect, &blend);
737  }
738 
740  virtual void DrawWidget(IGraphics& g)
741  {
742  // NO-OP
743  }
744 
746  virtual void DrawLabel(IGraphics& g)
747  {
748  if (mLabelBounds.H() && mStyle.showLabel)
749  {
750  IBlend blend = mControl->GetBlend();
751  g.DrawText(mStyle.labelText, mLabelStr.Get(), mLabelBounds, &blend);
752  }
753  }
754 
756  virtual void DrawValue(IGraphics& g, bool mouseOver)
757  {
758  if(mouseOver)
759  g.FillRect(COLOR_TRANSLUCENT, mValueBounds);
760 
761  if (mStyle.showValue)
762  {
763  IBlend blend = mControl->GetBlend();
764  g.DrawText(mStyle.valueText, mValueStr.Get(), mValueBounds, &blend);
765  }
766  }
767 
775  virtual void DrawPressableShape(IGraphics& g, EVShape shape, const IRECT& bounds, bool pressed, bool mouseOver, bool disabled)
776  {
777  switch (shape)
778  {
779  case EVShape::Ellipse:
780  DrawPressableEllipse(g, bounds, pressed, mouseOver, disabled);
781  break;
782  case EVShape::Rectangle:
783  DrawPressableRectangle(g, bounds, pressed, mouseOver, disabled);
784  break;
785  case EVShape::Triangle:
786  DrawPressableTriangle(g, bounds, pressed, mouseOver, mStyle.angle, disabled);
787  break;
788  case EVShape::EndsRounded:
789  DrawPressableRectangle(g, bounds, pressed, mouseOver, disabled, true, true, false, false);
790  break;
791  case EVShape::AllRounded:
792  DrawPressableRectangle(g, bounds, pressed, mouseOver, disabled, true, true, true, true);
793  default:
794  break;
795  }
796  }
797 
804  void DrawPressableEllipse(IGraphics& g, const IRECT& bounds, bool pressed, bool mouseOver, bool disabled)
805  {
806  IRECT handleBounds = bounds;
807  IRECT centreBounds = bounds.GetPadded(-mStyle.shadowOffset);
808  IRECT shadowBounds = bounds.GetTranslated(mStyle.shadowOffset, mStyle.shadowOffset);
809  const IBlend blend = mControl->GetBlend();
810  const float contrast = disabled ? -GRAYED_ALPHA : 0.f;
811 
812  if(!pressed && !disabled && mStyle.drawShadows)
813  g.FillEllipse(GetColor(kSH), shadowBounds);
814 
815  if (pressed)
816  {
817  if (mStyle.emboss)
818  {
819  shadowBounds.ReduceFromRight(mStyle.shadowOffset);
820  shadowBounds.ReduceFromBottom(mStyle.shadowOffset);
821  // Fill background with pressed color and shade it
822  g.FillEllipse(GetColor(kPR), bounds, &blend);
823  g.FillEllipse(GetColor(kSH), bounds, &blend);
824 
825  // Inverse shading for recessed look - shadowBounds = inner shadow
826  g.FillEllipse(GetColor(kFG).WithContrast(contrast), shadowBounds/*, &blend*/);
827 
828  // Fill in center with pressed color
829  g.FillEllipse(GetColor(kPR).WithContrast(contrast), centreBounds/*, &blend*/);
830  }
831  else
832  g.FillEllipse(GetColor(kPR).WithContrast(contrast), handleBounds/*, &blend*/);
833  }
834  else
835  {
836  // Embossed style unpressed
837  if (mStyle.emboss)
838  {
839  // Positive light TODO: use thes kPR color for now, maybe change the name?
840  g.FillEllipse(GetColor(kPR).WithContrast(contrast), bounds/*, &blend*/);
841 
842  // Negative light TODO: clip this?
843  g.FillEllipse(GetColor(kSH).WithContrast(contrast), shadowBounds/*, &blend*/);
844 
845  // Fill in foreground
846  g.FillEllipse(GetColor(kFG).WithContrast(contrast), centreBounds/*, &blend*/);
847 
848  // Shade when hovered
849  if (mouseOver)
850  g.FillEllipse(GetColor(kHL), centreBounds, &blend);
851  }
852  else
853  {
854  g.FillEllipse(GetColor(kFG).WithContrast(contrast), handleBounds/*, &blend*/);
855 
856  // Shade when hovered
857  if (mouseOver)
858  g.FillEllipse(GetColor(kHL), handleBounds, &blend);
859  }
860  }
861 
862  if(pressed && mControl->GetAnimationFunction())
863  DrawSplash(g, handleBounds);
864 
865  if(mStyle.drawFrame)
866  g.DrawEllipse(GetColor(kFR), handleBounds, &blend, mStyle.frameThickness);
867  }
868 
876  IRECT DrawPressableRectangle(IGraphics&g, const IRECT& bounds, bool pressed, bool mouseOver, bool disabled,
877  bool rtl = true, bool rtr = true, bool rbl = true, bool rbr = true)
878  {
879  IRECT handleBounds = GetAdjustedHandleBounds(bounds);
880  IRECT centreBounds = handleBounds.GetPadded(-mStyle.shadowOffset);
881  IRECT shadowBounds = handleBounds.GetTranslated(mStyle.shadowOffset, mStyle.shadowOffset);
882  const IBlend blend = mControl->GetBlend();
883  const float contrast = disabled ? -GRAYED_ALPHA : 0.f;
884  float cR = GetRoundedCornerRadius(handleBounds);
885 
886  const float tlr = rtl ? cR : 0.f;
887  const float trr = rtr ? cR : 0.f;
888  const float blr = rbl ? cR : 0.f;
889  const float brr = rbr ? cR : 0.f;
890 
891  if (pressed)
892  {
893  shadowBounds.ReduceFromRight(mStyle.shadowOffset);
894  shadowBounds.ReduceFromBottom(mStyle.shadowOffset);
895 
896  if (mStyle.emboss)
897  {
898  // Fill background with pressed color and shade it
899  g.FillRoundRect(GetColor(kPR), handleBounds, tlr, trr, blr, brr, &blend);
900  g.FillRoundRect(GetColor(kSH), handleBounds, tlr, trr, blr, brr, &blend);
901 
902  // Inverse shading for recessed look - shadowBounds = inner shadow
903  g.FillRoundRect(GetColor(kFG).WithContrast(contrast), shadowBounds, tlr, trr, blr, brr/*, &blend*/);
904 
905  // Fill in center with pressed color
906  g.FillRoundRect(GetColor(kPR), centreBounds, tlr, trr, blr, brr, &blend);
907  }
908  else
909  {
910  g.FillRoundRect(GetColor(kPR).WithContrast(contrast), handleBounds, tlr, trr, blr, brr/*, &blend*/);
911  }
912  }
913  else
914  {
915  //outer shadow
916  if (mStyle.drawShadows)
917  g.FillRoundRect(GetColor(kSH), shadowBounds, tlr, trr, blr, brr, &blend);
918 
919  // Embossed style unpressed
920  if (mStyle.emboss)
921  {
922  // Positive light TODO: use thes kPR color for now, maybe change the name?
923  g.FillRoundRect(GetColor(kPR).WithContrast(contrast), handleBounds, tlr, trr, blr, brr/*, &blend*/);
924 
925  // Negative light TODO: clip this?
926  g.FillRoundRect(GetColor(kSH).WithContrast(contrast), shadowBounds, tlr, trr, blr, brr/*, &blend*/);
927 
928  // Fill in foreground
929  g.FillRoundRect(GetColor(kFG).WithContrast(contrast), centreBounds, tlr, trr, blr, brr/*, &blend*/);
930 
931  // Shade when hovered
932  if (mouseOver)
933  g.FillRoundRect(GetColor(kHL), centreBounds, tlr, trr, blr, brr, &blend);
934  }
935  else
936  {
937  g.FillRoundRect(GetColor(kFG).WithContrast(contrast), handleBounds, tlr, trr, blr, brr/*, &blend*/);
938 
939  // Shade when hovered
940  if (mouseOver)
941  g.FillRoundRect(GetColor(kHL), handleBounds, tlr, trr, blr, brr, &blend);
942  }
943  }
944 
945  if(pressed && mControl->GetAnimationFunction())
946  DrawSplash(g, handleBounds);
947 
948  if(mStyle.drawFrame)
949  g.DrawRoundRect(GetColor(kFR), handleBounds, tlr, trr, blr, brr, &blend, mStyle.frameThickness);
950 
951  return handleBounds;
952  }
953 
959  IRECT DrawPressableTriangle(IGraphics&g, const IRECT& bounds, bool pressed, bool mouseOver, float angle, bool disabled)
960  {
961  float x1, x2, x3, y1, y2, y3;
962 
963  float theta = DegToRad(angle);
964 
965  IRECT handleBounds = GetAdjustedHandleBounds(bounds);
966 
967  // Center bounds around origin for rotation
968  float xT = handleBounds.L + handleBounds.W() * 0.5f;
969  float yT = handleBounds.T + handleBounds.H() * 0.5f;
970  IRECT centered = handleBounds.GetTranslated(-xT, -yT);
971 
972  // Do rotation and translate points back into view space
973  float c = cosf(theta);
974  float s = sinf(theta);
975  x1 = centered.L * c - centered.B * s + xT;
976  y1 = centered.L * s + centered.B * c + yT;
977  x2 = centered.MW() * c - centered.T * s + xT;
978  y2 = centered.MW() * s + centered.T * c + yT;
979  x3 = centered.R * c - centered.B * s + xT;
980  y3 = centered.R * s + centered.B * c + yT;
981 
982  const IBlend blend = mControl->GetBlend();
983  const float contrast = disabled ? -GRAYED_ALPHA : 0.f;
984 
985  if (pressed)
986  g.FillTriangle(GetColor(kPR).WithContrast(contrast), x1, y1, x2, y2, x3, y3/*, &blend*/);
987  else
988  {
989  //outer shadow
990  if (mStyle.drawShadows)
991  g.FillTriangle(GetColor(kSH), x1 + mStyle.shadowOffset, y1 + mStyle.shadowOffset,
992  x2 + mStyle.shadowOffset, y2 + mStyle.shadowOffset,
993  x3 + mStyle.shadowOffset, y3 + mStyle.shadowOffset, &blend);
994 
995  g.FillTriangle(GetColor(kFG).WithContrast(contrast), x1, y1, x2, y2, x3, y3/*, &blend*/);
996  }
997 
998  if (mouseOver)
999  g.FillTriangle(GetColor(kHL), x1, y1, x2, y2, x3, y3, &blend);
1000 
1001  if(pressed && mControl->GetAnimationFunction())
1002  DrawSplash(g);
1003 
1004  if (mStyle.drawFrame)
1005  g.DrawTriangle(GetColor(kFR), x1, y1, x2, y2, x3, y3, &blend, mStyle.frameThickness);
1006 
1007  return handleBounds;
1008  }
1009 
1014  IRECT MakeRects(const IRECT& parent, bool hasHandle = false)
1015  {
1016  IRECT clickableArea = parent;
1017 
1018  if(!mLabelInWidget)
1019  {
1020  if(mStyle.showLabel && CStringHasContents(mLabelStr.Get()))
1021  {
1022  IRECT textRect;
1023  mControl->GetUI()->MeasureText(mStyle.labelText, mLabelStr.Get(), textRect);
1024 
1025  mLabelBounds = parent.GetFromTop(textRect.H()).GetCentredInside(textRect.W(), textRect.H());
1026  }
1027  else
1028  mLabelBounds = IRECT();
1029 
1030  if(mLabelBounds.H())
1031  clickableArea = parent.GetReducedFromTop(mLabelBounds.H());
1032  }
1033 
1034  if (mStyle.showValue && !mValueInWidget)
1035  {
1036  IRECT textRect;
1037 
1038  if(CStringHasContents(mValueStr.Get()))
1039  mControl->GetUI()->MeasureText(mStyle.valueText, mValueStr.Get(), textRect);
1040 
1041  const float valueDisplayWidth = textRect.W() * mValueDisplayFrac;
1042 
1043  switch (mStyle.valueText.mVAlign)
1044  {
1045  case EVAlign::Middle:
1046  mValueBounds = clickableArea.GetMidVPadded(textRect.H()/2.f).GetMidHPadded(valueDisplayWidth);
1047  mWidgetBounds = clickableArea.GetScaledAboutCentre(mStyle.widgetFrac);
1048  break;
1049  case EVAlign::Bottom:
1050  {
1051  mValueBounds = clickableArea.GetFromBottom(textRect.H()).GetMidHPadded(valueDisplayWidth);
1052  mWidgetBounds = clickableArea.GetReducedFromBottom(textRect.H()).GetScaledAboutCentre(mStyle.widgetFrac);
1053  break;
1054  }
1055  case EVAlign::Top:
1056  mValueBounds = clickableArea.GetFromTop(textRect.H()).GetMidHPadded(valueDisplayWidth);
1057  mWidgetBounds = clickableArea.GetReducedFromTop(textRect.H()).GetScaledAboutCentre(mStyle.widgetFrac);
1058  break;
1059  default:
1060  break;
1061  }
1062  }
1063  else
1064  {
1065  mWidgetBounds = clickableArea.GetScaledAboutCentre(mStyle.widgetFrac);
1066  }
1067 
1068  if(hasHandle)
1069  mWidgetBounds = GetAdjustedHandleBounds(clickableArea).GetScaledAboutCentre(mStyle.widgetFrac);
1070 
1071  if(mLabelInWidget)
1072  mLabelBounds = mWidgetBounds;
1073 
1074  if(mValueInWidget)
1075  mValueBounds = mWidgetBounds;
1076 
1077  return clickableArea;
1078  }
1079 
1080 protected:
1081  IControl* mControl = nullptr;
1082  IVStyle mStyle; // IVStyle that defines certain common properties of an IVControl
1083  bool mLabelInWidget = false; // Should the Label text be displayed inside the widget
1084  bool mValueInWidget = false; // Should the Value text be displayed inside the widget
1085  float mSplashRadius = 0.f; // Modified during the default SplashClickAnimationFunc to specify the radius of the splash
1086  IVec2 mSplashPoint = {0.f, 0.f}; // Set at the start of the SplashClickActionFunc to set the position of the splash
1087  float mMaxSplashRadius = 50.f;
1088  float mTrackSize = 2.f;
1089  float mValueDisplayFrac = 0.66f; // the fraction of the control width for the text entry
1090  IRECT mWidgetBounds; // The knob/slider/button
1091  IRECT mLabelBounds; // A piece of text above the control
1092  IRECT mValueBounds; // Text below the contol, usually displaying the value of a parameter
1093  WDL_String mLabelStr;
1094  WDL_String mValueStr;
1095  EVShape mShape = EVShape::Rectangle;
1096 };
1097 
1100 {
1101 public:
1103  {
1104  int index = 0;
1105  float x = 0.f;
1106  float y = 0.f;
1107  float sx = 0.f;
1108  float sy = 0.f;
1109  float radius = 1.f;
1110  TimePoint startTime;
1111 
1112  TrackedTouch(int index, float x, float y, float radius, TimePoint time)
1113  : index(index), x(x), y(y), sx(x), sy(y), radius(radius), startTime(time)
1114  {}
1115 
1116  TrackedTouch()
1117  {}
1118  };
1119 
1120  virtual void AddTouch(ITouchID touchID, float x, float y, float radius)
1121  {
1122  int touchIndex = 0;
1123  for (int i = 0; i < MAX_TOUCHES; i++)
1124  {
1125  if (mTouchStatus[i] == false)
1126  {
1127  touchIndex = i;
1128  mTouchStatus[i] = true;
1129  break;
1130  }
1131  }
1132 
1133  if(NTrackedTouches() < MAX_TOUCHES)
1134  mTrackedTouches.insert(std::make_pair(touchID, TrackedTouch(touchIndex, x, y, radius, std::chrono::high_resolution_clock::now())));
1135  }
1136 
1137  virtual void ReleaseTouch(ITouchID touchID)
1138  {
1139  mTouchStatus[GetTouchWithIdentifier(touchID)->index] = false;
1140  mTrackedTouches.erase(touchID);
1141  }
1142 
1143  virtual void UpdateTouch(ITouchID touchID, float x, float y, float radius)
1144  {
1145  mTrackedTouches[touchID].x = x;
1146  mTrackedTouches[touchID].y = y;
1147  mTrackedTouches[touchID].radius = radius;
1148  }
1149 
1150  void ClearAllTouches()
1151  {
1152  mTrackedTouches.clear();
1153  memset(mTouchStatus, 0, MAX_TOUCHES * sizeof(bool));
1154  }
1155 
1156  int NTrackedTouches() const
1157  {
1158  return static_cast<int>(mTrackedTouches.size());
1159  }
1160 
1161  TrackedTouch* GetTouch(int index)
1162  {
1163  auto itr = std::find_if(mTrackedTouches.begin(), mTrackedTouches.end(),
1164  [index](auto element) {
1165  return(element.second.index == index);
1166  });
1167 
1168  if(itr != mTrackedTouches.end())
1169  return &itr->second;
1170  else
1171  return nullptr;
1172  }
1173 
1174  TrackedTouch* GetTouchWithIdentifier(ITouchID touchID)
1175  {
1176  auto itr = mTrackedTouches.find(touchID);
1177 
1178  if(itr != mTrackedTouches.end())
1179  return &itr->second;
1180  else
1181  return nullptr;
1182  }
1183 
1184 protected:
1185  static constexpr int MAX_TOUCHES = 10;
1186  std::unordered_map<ITouchID, TrackedTouch> mTrackedTouches;
1187  bool mTouchStatus[MAX_TOUCHES] = { 0 };
1188 };
1189 
1192 {
1193 public:
1194  IKnobControlBase(const IRECT& bounds, int paramIdx = kNoParameter, EDirection direction = EDirection::Vertical, double gearing = DEFAULT_GEARING)
1195  : IControl(bounds, paramIdx)
1196  , mDirection(direction)
1197  , mGearing(gearing)
1198  {}
1199 
1200  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
1201  void OnMouseUp(float x, float y, const IMouseMod& mod) override;
1202  void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) override;
1203  void OnMouseWheel(float x, float y, const IMouseMod& mod, float d) override;
1204 
1205  void SetGearing(double gearing) { mGearing = gearing; }
1206  bool IsFineControl(const IMouseMod& mod, bool wheel) const;
1207 
1208 protected:
1211  virtual IRECT GetKnobDragBounds() { return mTargetRECT; }
1212 
1213  bool mHideCursorOnDrag = true;
1214  EDirection mDirection;
1215  double mGearing;
1216  bool mMouseDown = false;
1217  double mMouseDragValue = 0.0;
1218 };
1219 
1222 {
1223 public:
1224  ISliderControlBase(const IRECT& bounds, int paramIdx = kNoParameter, EDirection dir = EDirection::Vertical, double gearing = DEFAULT_GEARING, float handleSize = 0.f);
1225  ISliderControlBase(const IRECT& bounds, IActionFunction aF = nullptr, EDirection dir = EDirection::Vertical, double gearing = DEFAULT_GEARING, float handleSize = 0.f);
1226 
1227  void OnResize() override;
1228  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
1229  void OnMouseUp(float x, float y, const IMouseMod& mod) override;
1230  void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) override;
1231  void OnMouseWheel(float x, float y, const IMouseMod& mod, float d) override;
1232 
1233  void SetGearing(double gearing) { mGearing = gearing; }
1234  bool IsFineControl(const IMouseMod& mod, bool wheel) const;
1235 
1236 protected:
1237  bool mHideCursorOnDrag = true;
1238  EDirection mDirection;
1239  IRECT mTrackBounds;
1240  float mHandleSize;
1241  double mGearing;
1242  bool mMouseDown = false;
1243  double mMouseDragValue;
1244 };
1245 
1249  , public IVectorBase
1250 {
1251 public:
1252  IVTrackControlBase(const IRECT& bounds, const char* label, const IVStyle& style, int maxNTracks = 1, int nSteps = 0, EDirection dir = EDirection::Horizontal, std::initializer_list<const char*> trackNames = {})
1253  : IControl(bounds)
1254  , IVectorBase(style)
1255  , mDirection(dir)
1256  , mNSteps(nSteps)
1257  {
1258  SetNVals(maxNTracks);
1259  mTrackBounds.Resize(maxNTracks);
1260 
1261  for (int i=0; i<maxNTracks; i++)
1262  {
1263  SetParamIdx(kNoParameter, i);
1264  }
1265 
1266  if(trackNames.size())
1267  {
1268  assert(trackNames.size() == maxNTracks); // check that the trackNames list size matches the number of tracks
1269 
1270  for (auto& trackName : trackNames)
1271  {
1272  mTrackNames.Add(new WDL_String(trackName));
1273  }
1274  }
1275 
1276  AttachIControl(this, label);
1277  }
1278 
1279  IVTrackControlBase(const IRECT& bounds, const char* label, const IVStyle& style, int lowParamidx, int maxNTracks = 1, int nSteps = 0, EDirection dir = EDirection::Horizontal, std::initializer_list<const char*> trackNames = {})
1280  : IControl(bounds)
1281  , IVectorBase(style)
1282  , mDirection(dir)
1283  , mNSteps(nSteps)
1284  {
1285  SetNVals(maxNTracks);
1286  mTrackBounds.Resize(maxNTracks);
1287 
1288  for (int i = 0; i < maxNTracks; i++)
1289  {
1290  SetParamIdx(lowParamidx+i, i);
1291  }
1292 
1293  if(trackNames.size())
1294  {
1295  assert(trackNames.size() == maxNTracks);
1296 
1297  for (auto& trackName : trackNames)
1298  {
1299  mTrackNames.Add(new WDL_String(trackName));
1300  }
1301  }
1302 
1303  AttachIControl(this, label);
1304  }
1305 
1306  IVTrackControlBase(const IRECT& bounds, const char* label, const IVStyle& style, const std::initializer_list<int>& params, int nSteps = 0, EDirection dir = EDirection::Horizontal, std::initializer_list<const char*> trackNames = {})
1307  : IControl(bounds)
1308  , IVectorBase(style)
1309  , mDirection(dir)
1310  , mNSteps(nSteps)
1311  {
1312  int maxNTracks = static_cast<int>(params.size());
1313  SetNVals(maxNTracks);
1314  mTrackBounds.Resize(maxNTracks);
1315 
1316  int valIdx = 0;
1317  for (auto param : params)
1318  {
1319  SetParamIdx(param, valIdx++);
1320  }
1321 
1322  if(trackNames.size())
1323  {
1324  assert(trackNames.size() == params.size());
1325 
1326  for (auto& trackName : trackNames)
1327  {
1328  mTrackNames.Add(new WDL_String(trackName));
1329  }
1330  }
1331 
1332  AttachIControl(this, label);
1333  }
1334 
1335  virtual ~IVTrackControlBase()
1336  {
1337  mTrackNames.Empty(true);
1338  }
1339 
1340  void OnMouseOver(float x, float y, const IMouseMod& mod) override
1341  {
1342  mMouseOverTrack = GetValIdxForPos(x, y);
1343  SetDirty(false);
1344  }
1345 
1346  void OnMouseOut() override
1347  {
1348  mMouseOverTrack = -1;
1349  SetDirty(false);
1350  }
1351 
1352  virtual void OnResize() override
1353  {
1354  SetTargetRECT(MakeRects(mRECT));
1355  MakeTrackRects(mWidgetBounds);
1356  MakeStepRects(mWidgetBounds, mNSteps);
1357  SetDirty(false);
1358  }
1359 
1360  int GetValIdxForPos(float x, float y) const override
1361  {
1362  int nVals = NVals();
1363 
1364  for (auto v = 0; v < nVals; v++)
1365  {
1366  if (mTrackBounds.Get()[v].Contains(x, y))
1367  {
1368  return v;
1369  }
1370  }
1371 
1372  return kNoValIdx;
1373  }
1374 
1375  void DrawWidget(IGraphics& g) override
1376  {
1377  const int nVals = NVals();
1378 
1379  for (int ch = 0; ch < nVals; ch++)
1380  {
1381  DrawTrack(g, mTrackBounds.Get()[ch], ch);
1382  }
1383  }
1384 
1387  void SetParamsByGroup(const char* paramGroup)
1388  {
1389  int nParams = GetDelegate()->NParams();
1390  std::vector<int> paramIdsForGroup;
1391 
1392  for (auto p = 0; p < nParams; p++)
1393  {
1394  IParam* pParam = GetDelegate()->GetParam(p);
1395 
1396  if(strcmp(pParam->GetGroup(), paramGroup) == 0)
1397  {
1398  paramIdsForGroup.push_back(p);
1399  }
1400  }
1401 
1402  SetParams(paramIdsForGroup);
1403  }
1404 
1407  void SetParams(const std::vector<int>& paramIds)
1408  {
1409  int nParams = static_cast<int>(paramIds.size());
1410 
1411  SetNVals(nParams);
1412  mTrackBounds.Resize(nParams);
1413 
1414  int valIdx = 0;
1415  for (auto param : paramIds)
1416  {
1417  SetParamIdx(param, valIdx++);
1418  }
1419 
1420  const IParam* pFirstParam = GetParam(0);
1421  const int range = static_cast<int>(pFirstParam->GetRange() / pFirstParam->GetStep());
1422  mZeroValueStepHasBounds = !(range == 1);
1423  SetNSteps(pFirstParam->GetStepped() ? range : 0); // calls OnResize()
1424  }
1425 
1426  void SetBaseValue(double value)
1427  {
1428  mBaseValue = value; OnResize();
1429  }
1430 
1431  void SetTrackPadding(float value)
1432  {
1433  mTrackPadding = value; OnResize();
1434  }
1435 
1436  void SetPeakSize(float value)
1437  {
1438  mPeakSize = value; OnResize();
1439  }
1440 
1441  void SetNSteps(int nSteps)
1442  {
1443  mNSteps = nSteps; OnResize();
1444  }
1445 
1446  void SetHighlightedTrack(int highlightIdx)
1447  {
1448  mHighlightedTrack = highlightIdx;
1449  SetDirty(false);
1450  }
1451 
1452  void SetZeroValueStepHasBounds(bool val)
1453  {
1454  mZeroValueStepHasBounds = val;
1455  OnResize();
1456  }
1457 
1458  bool HasTrackNames() const
1459  {
1460  return mTrackNames.GetSize() > 0;
1461  }
1462 
1463  const char* GetTrackName(int chIdx) const
1464  {
1465  WDL_String* pStr = mTrackNames.Get(chIdx);
1466  return pStr ? pStr->Get() : "";
1467  }
1468 
1469  void SetTrackName(int chIdx, const char* newName)
1470  {
1471  assert(chIdx >= 0 && chIdx < mTrackNames.GetSize());
1472 
1473  if(chIdx >= 0 && chIdx < mTrackNames.GetSize())
1474  {
1475  mTrackNames.Get(chIdx)->Set(newName);
1476  }
1477  }
1478 
1479 protected:
1480  virtual void DrawBackground(IGraphics& g, const IRECT& r) override
1481  {
1482  g.FillRect(kBG, r, &mBlend);
1483 
1484  if(mBaseValue > 0.)
1485  {
1486  if(mDirection == EDirection::Horizontal)
1487  g.DrawVerticalLine(GetColor(kSH), r, static_cast<float>(mBaseValue));
1488  else
1489  g.DrawHorizontalLine(GetColor(kSH), r, static_cast<float>(mBaseValue));
1490  }
1491  }
1492 
1493  virtual void DrawTrack(IGraphics& g, const IRECT& r, int chIdx)
1494  {
1495  DrawTrackBackground(g, r, chIdx);
1496 
1497  if(HasTrackNames())
1498  DrawTrackName(g, r, chIdx);
1499 
1500  const float trackPos = static_cast<float>(GetValue(chIdx));
1501 
1502  const bool stepped = GetStepped();
1503 
1504  IRECT fillRect;
1505  const float bv = static_cast<float>(mBaseValue);
1506 
1507  if(bv > 0.f)
1508  {
1509  if(mDirection == EDirection::Vertical)
1510  {
1511  fillRect = IRECT(r.L,
1512  trackPos < bv ? r.B - r.H() * bv : r.B - r.H() * trackPos,
1513  r.R,
1514  trackPos < bv ? r.B - r.H() * trackPos : r.B - r.H() * bv);
1515  }
1516  else
1517  {
1518  fillRect = IRECT(trackPos < bv ? r.L + r.W() * trackPos : r.L + r.W() * bv,
1519  r.T,
1520  trackPos < bv ? r.L + r.W() * bv : r.L + r.W() * trackPos,
1521  r.B);
1522  }
1523  }
1524  else
1525  {
1526  fillRect = r.FracRect(mDirection, trackPos);
1527 
1528  if(stepped && mZeroValueStepHasBounds && trackPos == 0.f)
1529  {
1530  if(mDirection == EDirection::Vertical)
1531  fillRect.T = mStepBounds.Get()[0].T;
1532  }
1533  }
1534 
1535  if(stepped)
1536  {
1537  int step = GetStepIdxForPos(fillRect.R, fillRect.T);
1538 
1539  if (step > -1)
1540  {
1541  if(mDirection == EDirection::Horizontal)
1542  {
1543  fillRect.L = mStepBounds.Get()[step].L;
1544  fillRect.R = mStepBounds.Get()[step].R;
1545  }
1546  else
1547  {
1548  fillRect.T = mStepBounds.Get()[step].T;
1549  fillRect.B = mStepBounds.Get()[step].B;
1550  }
1551  }
1552 
1553  if(mZeroValueStepHasBounds || GetValue(chIdx) > 0.)
1554  DrawTrackHandle(g, fillRect, chIdx, trackPos > mBaseValue);
1555  }
1556  else
1557  {
1558  DrawTrackHandle(g, fillRect, chIdx, trackPos > mBaseValue);
1559 
1560  IRECT peakRect;
1561 
1562  if(mDirection == EDirection::Vertical)
1563  {
1564  peakRect = IRECT(fillRect.L,
1565  trackPos < mBaseValue ? fillRect.B : fillRect.T,
1566  fillRect.R,
1567  trackPos < mBaseValue ? fillRect.B - mPeakSize: fillRect.T + mPeakSize);
1568  }
1569  else
1570  {
1571  peakRect = IRECT(trackPos < mBaseValue ? fillRect.L + mPeakSize : fillRect.R - mPeakSize,
1572  fillRect.T,
1573  trackPos < mBaseValue ? fillRect.L : fillRect.R,
1574  fillRect.B);
1575  }
1576 
1577  DrawPeak(g, peakRect, chIdx, trackPos > mBaseValue);
1578  }
1579 
1580  if(mStyle.drawFrame && mDrawTrackFrame)
1581  g.DrawRect(GetColor(kFR), r, &mBlend, mStyle.frameThickness);
1582  }
1583 
1584  virtual void DrawTrackBackground(IGraphics& g, const IRECT& r, int chIdx)
1585  {
1586  g.FillRect(chIdx == mHighlightedTrack ? this->GetColor(kHL) : COLOR_TRANSPARENT, r);
1587  }
1588 
1589  virtual void DrawTrackName(IGraphics& g, const IRECT& r, int chIdx)
1590  {
1591  g.DrawText(mText, GetTrackName(chIdx), r);
1592  }
1593 
1599  virtual void DrawTrackHandle(IGraphics& g, const IRECT& r, int chIdx, bool aboveBaseValue)
1600  {
1601  g.FillRect(chIdx == mHighlightedTrack ? GetColor(kX1) : GetColor(kFG), r, &mBlend);
1602 
1603  if(chIdx == mMouseOverTrack)
1604  g.FillRect(GetColor(kHL), r, &mBlend);
1605  }
1606 
1607  virtual void DrawPeak(IGraphics& g, const IRECT& r, int chIdx, bool aboveBaseValue)
1608  {
1609  g.FillRect(GetColor(kFR), r, &mBlend);
1610  }
1611 
1612  int GetStepIdxForPos(float x, float y) const
1613  {
1614  int nSteps = mStepBounds.GetSize();
1615 
1616  for (auto v = 0; v < nSteps; v++)
1617  {
1618  if (mStepBounds.Get()[v].ContainsEdge(x, y))
1619  {
1620  return v;
1621  }
1622  }
1623 
1624  return -1;
1625  }
1626 
1627  virtual void MakeTrackRects(const IRECT& bounds)
1628  {
1629  int nVals = NVals();
1630  int dir = static_cast<int>(mDirection); // 0 = horizontal, 1 = vertical
1631  for (int ch = 0; ch < nVals; ch++)
1632  {
1633  mTrackBounds.Get()[ch] = bounds.SubRect(EDirection(!dir), nVals, ch).
1634  GetPadded(0, -mTrackPadding * (float) dir, -mTrackPadding * (float) !dir, -mTrackPadding);
1635  }
1636  }
1637 
1638  virtual void MakeStepRects(const IRECT& bounds, int nSteps)
1639  {
1640  if(nSteps)
1641  {
1642  int dir = static_cast<int>(mDirection);
1643 
1644  nSteps += (int) mZeroValueStepHasBounds;
1645 
1646  mStepBounds.Resize(nSteps);
1647 
1648  for (int step = 0; step < nSteps; step++)
1649  {
1650  mStepBounds.Get()[step] = bounds.SubRect(EDirection(dir), nSteps, nSteps - 1 - step);
1651  }
1652  }
1653  else
1654  mStepBounds.Resize(0);
1655  }
1656 
1657  bool GetStepped() const
1658  {
1659  return mStepBounds.GetSize() > 0;
1660  }
1661 
1662 protected:
1663  EDirection mDirection = EDirection::Vertical;
1664  WDL_TypedBuf<IRECT> mTrackBounds;
1665  WDL_TypedBuf<IRECT> mStepBounds;
1666  WDL_PtrList<WDL_String> mTrackNames;
1667  int mNSteps = 0;
1668  float mTrackPadding = 0.;
1669  float mPeakSize = 1.;
1670  int mHighlightedTrack = -1; // Highlight a single track, e.g. for step sequencer
1671  int mMouseOverTrack = -1;
1672  double mBaseValue = 0.; // 0-1 value to represent the mid-point, i.e. for displaying bipolar data
1673  bool mDrawTrackFrame = true;
1674  bool mZeroValueStepHasBounds = true; // If this is true, there is a separate step for zero, when mNSteps > 0
1675 };
1676 
1680 {
1681 public:
1682  IButtonControlBase(const IRECT& bounds, IActionFunction aF);
1683 
1684  virtual ~IButtonControlBase() {}
1685  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
1686  void OnEndAnimation() override;
1687 };
1688 
1691 {
1692 public:
1693  ISwitchControlBase(const IRECT& bounds, int paramIdx = kNoParameter, IActionFunction aF = nullptr, int numStates = 2);
1694 
1695  virtual ~ISwitchControlBase() {}
1696  void OnInit() override;
1697  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
1698  void OnMouseUp(float x, float y, const IMouseMod& mod) override;
1699 
1700  int GetSelectedIdx() const { return int(0.5 + GetValue() * (double) (mNumStates - 1)); }
1701 
1702  void SetStateDisabled(int stateIdx, bool disabled);
1703  void SetAllStatesDisabled(bool disabled);
1704  bool GetStateDisabled(int stateIdx) const;
1705 protected:
1706  int mNumStates;
1707  WDL_TypedBuf<bool> mDisabledState;
1708  bool mMouseDown = false;
1709 };
1710 
1713 {
1714 public:
1719  IDirBrowseControlBase(const IRECT& bounds, const char* extension, bool showFileExtensions = true)
1720  : IControl(bounds)
1721  , mShowFileExtensions(showFileExtensions)
1722  {
1723  mExtension.Set(extension);
1724  }
1725 
1726  virtual ~IDirBrowseControlBase();
1727 
1728  int NItems();
1729 
1730  void AddPath(const char* path, const char* label);
1731 
1732  void SetupMenu();
1733 
1734 // void GetSelectedItemLabel(WDL_String& label);
1735 // void GetSelectedItemPath(WDL_String& path);
1736 
1737 private:
1738  void ScanDirectory(const char* path, IPopupMenu& menuToAddTo);
1739  void CollectSortedItems(IPopupMenu* pMenu);
1740 
1741 protected:
1742  bool mShowEmptySubmenus = false;
1743  bool mShowFileExtensions = true;
1744  int mSelectedIndex = -1;
1745  IPopupMenu* mSelectedMenu = nullptr;
1746  IPopupMenu mMainMenu;
1747  WDL_PtrList<WDL_String> mPaths;
1748  WDL_PtrList<WDL_String> mPathLabels;
1749  WDL_PtrList<WDL_String> mFiles;
1750  WDL_PtrList<IPopupMenu::Item> mItems; // ptr to item for each file
1751  WDL_String mExtension;
1752 };
1753 
1756 #pragma mark - BASIC CONTROLS
1757 
1764 class IPanelControl : public IControl
1765 {
1766 public:
1767  IPanelControl(const IRECT& bounds, const IColor& color, bool drawFrame = false)
1768  : IControl(bounds, kNoParameter)
1769  , mPattern(color)
1770  , mDrawFrame(drawFrame)
1771  {
1772  mIgnoreMouse = true;
1773  }
1774 
1775  IPanelControl(const IRECT& bounds, const IPattern& pattern, bool drawFrame = false)
1776  : IControl(bounds, kNoParameter)
1777  , mPattern(pattern)
1778  , mDrawFrame(drawFrame)
1779  {
1780  mIgnoreMouse = true;
1781  }
1782 
1783  void Draw(IGraphics& g) override
1784  {
1785  g.PathRect(mRECT);
1786  g.PathFill(mPattern);
1787 
1788  if(mDrawFrame)
1789  g.DrawRect(COLOR_LIGHT_GRAY, mRECT);
1790  }
1791 
1792  void SetPattern(const IPattern& pattern)
1793  {
1794  mPattern = pattern;
1795  SetDirty(false);
1796  }
1797 
1798  IPattern GetPattern() const { return mPattern; }
1799 
1800 private:
1801  IPattern mPattern;
1802  bool mDrawFrame;
1803 };
1804 
1806 class ILambdaControl : public IControl
1807 {
1808 public:
1809  ILambdaControl(const IRECT& bounds, ILambdaDrawFunction drawFunc, int animationDuration = DEFAULT_ANIMATION_DURATION,
1810  bool loopAnimation = false, bool startImmediately = false, int paramIdx = kNoParameter, bool ignoreMouse = false)
1811  : IControl(bounds, paramIdx, DefaultClickActionFunc)
1812  , mDrawFunc(drawFunc)
1813  , mLoopAnimation(loopAnimation)
1814  , mAnimationDuration(animationDuration)
1815  {
1816  if (startImmediately)
1817  SetAnimation(DefaultAnimationFunc, mAnimationDuration);
1818 
1819  mIgnoreMouse = ignoreMouse;
1820  mDblAsSingleClick = true;
1821  }
1822 
1823  void Draw(IGraphics& g) override
1824  {
1825  if(mDrawFunc)
1826  mDrawFunc(this, g, mRECT);
1827  }
1828 
1829  virtual void OnEndAnimation() override // if you override this you must call the base implementation, to free mAnimationFunc
1830  {
1831  if(mLoopAnimation && mAnimationDuration)
1832  StartAnimation(mAnimationDuration);
1833  else
1834  SetAnimation(nullptr);
1835 
1836  SetDirty(false);
1837  }
1838 
1839  void OnMouseDown(float x, float y, const IMouseMod& mod) override
1840  {
1841  mMouseInfo.x = x; mMouseInfo.y = y; mMouseInfo.ms = mod;
1842  SetAnimation(DefaultAnimationFunc, mAnimationDuration);
1843  }
1844 
1845  void OnMouseUp(float x, float y, const IMouseMod& mod) override
1846  {
1847  mMouseInfo.x = x;
1848  mMouseInfo.y = y;
1849  mMouseInfo.ms = IMouseMod();
1850  SetDirty(false);
1851  }
1852 
1853  void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod) override
1854  {
1855  mMouseInfo.x = x;
1856  mMouseInfo.y = y;
1857  mMouseInfo.dX = dX;
1858  mMouseInfo.dY = dY;
1859  mMouseInfo.ms = mod;
1860  SetDirty(false);
1861  }
1862 
1863 public: // public for easy access :-)
1864  ILayerPtr mLayer;
1865  IMouseInfo mMouseInfo;
1866 private:
1867  ILambdaDrawFunction mDrawFunc = nullptr;
1868  bool mLoopAnimation;
1869  int mAnimationDuration;
1870 };
1871 
1873 class IBitmapControl : public IControl
1874  , public IBitmapBase
1875 {
1876 public:
1880  IBitmapControl(float x, float y, const IBitmap& bitmap, int paramIdx = kNoParameter, EBlend blend = EBlend::Default)
1881  : IControl(IRECT(x, y, bitmap), paramIdx)
1882  , IBitmapBase(bitmap)
1883  {
1884  AttachIControl(this);
1885  mBlend = blend;
1886  }
1887 
1888  IBitmapControl(const IRECT& bounds, const IBitmap& bitmap, int paramIdx = kNoParameter, EBlend blend = EBlend::Default)
1889  : IControl(bounds, paramIdx)
1890  , IBitmapBase(bitmap)
1891  {
1892  AttachIControl(this);
1893  mBlend = blend;
1894  }
1895 
1896  virtual ~IBitmapControl() {}
1897 
1898  void Draw(IGraphics& g) override { DrawBitmap(g); }
1899 
1901  void OnRescale() override { mBitmap = GetUI()->GetScaledBitmap(mBitmap); }
1902 };
1903 
1905 class ISVGControl : public IControl
1906 {
1907 public:
1908  ISVGControl(const IRECT& bounds, const ISVG& svg, bool useLayer = false)
1909  : IControl(bounds)
1910  , mUseLayer(useLayer)
1911  , mSVG(svg)
1912  {}
1913 
1914  virtual ~ISVGControl() {}
1915 
1916  void Draw(IGraphics& g) override
1917  {
1918  if(mUseLayer)
1919  {
1920  if (!g.CheckLayer(mLayer))
1921  {
1922  g.StartLayer(this, mRECT);
1923  g.DrawSVG(mSVG, mRECT);
1924  mLayer = g.EndLayer();
1925  }
1926 
1927  g.DrawLayer(mLayer, &mBlend);
1928  }
1929  else
1930  g.DrawSVG(mSVG, mRECT, &mBlend);
1931  }
1932 
1933  void SetSVG(const ISVG& svg)
1934  {
1935  mSVG = svg;
1936  }
1937 
1938 private:
1939  bool mUseLayer;
1940  ILayerPtr mLayer;
1941  ISVG mSVG;
1942 };
1943 
1945 class ITextControl : public IControl
1946 {
1947 public:
1948  ITextControl(const IRECT& bounds, const char* str = "", const IText& text = DEFAULT_TEXT, const IColor& BGColor = DEFAULT_BGCOLOR, bool setBoundsBasedOnStr = false);
1949 
1950  void Draw(IGraphics& g) override;
1951  void OnInit() override;
1952 
1955  virtual void SetStr(const char* str);
1956 
1959  virtual void SetStrFmt(int maxlen, const char* fmt, ...);
1960 
1962  virtual void ClearStr() { SetStr(""); }
1963 
1965  const char* GetStr() const { return mStr.Get(); }
1966 
1968  void SetBoundsBasedOnStr();
1969 
1970 protected:
1971  WDL_String mStr;
1972  IColor mBGColor;
1973  bool mSetBoundsBasedOnStr = false;
1974 };
1975 
1978 {
1979 public:
1980  IEditableTextControl(const IRECT& bounds, const char* str, const IText& text = DEFAULT_TEXT, const IColor& BGColor = DEFAULT_BGCOLOR)
1981  : ITextControl(bounds, str, text, BGColor)
1982  {
1983  mIgnoreMouse = false;
1984  }
1985 
1986  void OnMouseDown(float x, float y, const IMouseMod& mod) override
1987  {
1988  GetUI()->CreateTextEntry(*this, mText, mRECT, GetStr());
1989  }
1990 
1991  void OnTextEntryCompletion(const char* str, int valIdx) override
1992  {
1993  SetStr(str);
1994  SetDirty(true);
1995  }
1996 };
1997 
2000 {
2001 public:
2002  IURLControl(const IRECT& bounds, const char* str, const char* url, const IText& text = DEFAULT_TEXT, const IColor& BGColor = DEFAULT_BGCOLOR, const IColor& MOColor = COLOR_WHITE, const IColor& CLColor = COLOR_BLUE);
2003 
2004  void Draw(IGraphics& g) override;
2005 
2006  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
2007  void OnMouseOver(float x, float y, const IMouseMod& mod) override { GetUI()->SetMouseCursor(ECursor::HAND); IControl::OnMouseOver(x, y, mod); };
2009  void SetText(const IText&) override;
2010 
2012  void SetMOColor(const IColor& color) { mMOColor = color; SetDirty(false); }
2013 
2015  void SetCLColor(const IColor& color) { mCLColor = color; SetDirty(false); }
2016 
2017 protected:
2018  WDL_String mURLStr;
2019  IColor mOriginalColor, mMOColor, mCLColor;
2020  bool mClicked = false;
2021 };
2022 
2025 {
2026 public:
2027  ITextToggleControl(const IRECT& bounds, int paramIdx = kNoParameter, const char* offText = "OFF", const char* onText = "ON", const IText& text = DEFAULT_TEXT, const IColor& BGColor = DEFAULT_BGCOLOR);
2028 
2029  ITextToggleControl(const IRECT& bounds, IActionFunction aF = nullptr, const char* offText = "OFF", const char* onText = "ON", const IText& text = DEFAULT_TEXT, const IColor& BGColor = DEFAULT_BGCOLOR);
2030 
2031  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
2032  void SetDirty(bool push, int valIdx = 0) override;
2033 protected:
2034  WDL_String mOffText;
2035  WDL_String mOnText;
2036 };
2037 
2040 {
2041 public:
2048  ICaptionControl(const IRECT& bounds, int paramIdx, const IText& text = DEFAULT_TEXT, const IColor& BGColor = DEFAULT_BGCOLOR, bool showParamLabel = true);
2049  void Draw(IGraphics& g) override;
2050  void OnMouseDown(float x, float y, const IMouseMod& mod) override;
2051  void OnResize() override;
2052 protected:
2053  bool mShowParamLabel;
2054  IColor mTriangleColor = COLOR_BLACK;
2055  IColor mTriangleMouseOverColor = COLOR_WHITE;
2056  IRECT mTri;
2057 };
2058 
2061 {
2062 public:
2063  PlaceHolder(const IRECT& bounds, const char* str = "Place Holder");
2064 
2065  void Draw(IGraphics& g) override;
2066  void OnMouseDblClick(float x, float y, const IMouseMod& mod) override { GetUI()->CreateTextEntry(*this, mText, mRECT, mStr.Get()); }
2067  void OnTextEntryCompletion(const char* str, int valIdx) override { SetStr(str); }
2068  void OnResize() override;
2069 
2070 protected:
2071  IRECT mCentreLabelBounds;
2072  WDL_String mTLHCStr;
2073  WDL_String mWidthStr;
2074  WDL_String mHeightStr;
2075  IText mTLGCText = DEFAULT_TEXT.WithAlign(EAlign::Near);
2076  IText mWidthText = DEFAULT_TEXT;
2077  IText mHeightText = DEFAULT_TEXT.WithAngle(270.f);
2078  static constexpr float mInset = 10.f;
2079 };
2080 
2081 END_IGRAPHICS_NAMESPACE
2082 END_IPLUG_NAMESPACE
2083 
Encapsulate an xy point in one struct.
IRECT DrawPressableRectangle(IGraphics &g, const IRECT &bounds, bool pressed, bool mouseOver, bool disabled, bool rtl=true, bool rtr=true, bool rbl=true, bool rbr=true)
Draw a rectangle-shaped vector button.
Definition: IControl.h:876
void PathRect(const IRECT &bounds)
Add a rectangle to the current path.
Definition: IGraphics.cpp:2613
Contains a set of 9 colors used to theme IVControls.
bool Contains(const IRECT &rhs) const
Returns true if this IRECT completely contains rhs.
void SetMouseOverWhenDisabled(bool allow)
Specify whether the control should respond to mouse overs when disabled.
Definition: IControl.h:360
void SetWantsMultiTouch(bool enable=true)
Specify whether this control supports multiple touches.
Definition: IControl.h:420
float MW() const
bool GetStepped() const
virtual void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControl.h:1352
virtual void OnAttached()
Called after the control has been attached, and its delegate and graphics member variable set...
Definition: IControl.h:154
IRECT SubRect(EDirection layoutDir, int numSlices, int sliceIdx) const
Get a new rectangle which is a "slice" of this rectangle.
void StartLayer(IControl *pOwner, const IRECT &r, bool cacheable=false)
Create an IGraphics layer.
Definition: IGraphics.cpp:1954
The lowest level base class of an IGraphics control.
Definition: IControl.h:42
void SetPTParameterHighlight(bool isHighlighted, int color)
Used internally by the AAX wrapper view interface to set the control parmeter highlight.
Definition: IControl.cpp:363
virtual void SetText(const IText &txt)
Set the Text object typically used to determine font/layout/size etc of the main text in a control...
Definition: IControl.h:286
Used to manage a rectangular area, independent of draw class/platform.
virtual void OnResize()
Called when IControl is constructed or resized using SetRect().
Definition: IControl.h:148
virtual void SetValueFromUserInput(double value, int valIdx=0)
Set the control&#39;s value after user input.
Definition: IControl.cpp:172
void SetTextEntryLength(int len)
Set the max number of characters that are allowed in text entry.
Definition: IControl.h:301
IGEditorDelegate * GetDelegate()
Gets a pointer to the class implementing the IEditorDelegate interface that handles parameter changes...
Definition: IControl.h:439
bool GetWantsMidi() const
Definition: IControl.h:417
void SetColor(EVColor colorIdx, const IColor &color)
Set one of the IVColors that style the IVControl.
Definition: IControl.h:650
virtual void OnMouseDown(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse down event on this control.
Definition: IControl.cpp:250
int LinkedToParam(int paramIdx) const
Check if the control is linked to a particular parameter.
Definition: IControl.cpp:130
virtual void DrawValue(IGraphics &g, bool mouseOver)
Draw the IVControl value text.
Definition: IControl.h:756
A basic control to draw a bitmap, or one frame of a stacked bitmap depending on the current value...
Definition: IControl.h:1873
virtual void DrawRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f)
Draw a rectangle to the graphics context.
Definition: IGraphics.cpp:2475
A basic control to display some text.
Definition: IControl.h:1945
Used to manage composite/blend operations, independent of draw class/platform.
virtual void DrawBackground(IGraphics &g, const IRECT &rect)
Draw the IVControl background (usually transparent)
Definition: IControl.h:733
int GetTag() const
Get the control&#39;s tag.
Definition: IControl.h:411
bool GetMouseEventsWhenDisabled() const
Definition: IControl.h:370
User-facing bitmap abstraction that you use to manage bitmap data, independant 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
Encapsulates a MIDI message and provides helper functions.
Definition: IPlugMidi.h:30
virtual bool OnKeyUp(float x, float y, const IKeyPress &key)
Implement this method to respond to a key up event on this control.
Definition: IControl.h:124
void CreateTextEntry(IControl &control, const IText &text, const IRECT &bounds, const char *str="", int valIdx=0)
Create a text entry box.
Definition: IGraphics.cpp:1900
void SetColors(const IVColorSpec &spec)
Set the colors of this IVControl.
Definition: IControl.h:658
const IRECT & GetTargetRECT() const
Get the rectangular mouse tracking target area, within the graphics context for this control...
Definition: IControl.h:313
void DisablePrompt(bool disable)
Disable/enable default prompt for user input.
Definition: IControl.h:405
Used to manage mouse modifiers i.e.
A base class for switch controls.
Definition: IControl.h:1690
A basic control to display some editable text.
Definition: IControl.h:1977
bool mMouseIsOver
if mGraphics::mHandleMouseOver = true, this will be true when the mouse is over control.
Definition: IControl.h:545
int GetTextEntryLength() const
Get the max number of characters that are allowed in text entry.
Definition: IControl.h:297
EGestureType GetLastGesture() const
Definition: IControl.h:434
virtual void Hide(bool hide)
Shows or hides the IControl.
Definition: IControl.cpp:237
void SetMouseEventsWhenDisabled(bool allow)
Specify whether the control should respond to other mouse events when disabled.
Definition: IControl.h:364
virtual void FillCircle(const IColor &color, float cx, float cy, float r, const IBlend *pBlend=0)
Fill a circle with a color.
Definition: IGraphics.cpp:2584
void SetPromptShowsParamLabel(bool enable)
Set if the control should show parameter labels/units e.g.
Definition: IControl.h:379
const IParam * GetParam(int valIdx=0) const
Get a const pointer to the IParam object (owned by the editor delegate class), associated with this c...
Definition: IControl.cpp:120
Include to get consistently named preprocessor macros for different platforms and logging functionali...
A control to use as a placeholder during development.
Definition: IControl.h:2060
bool GetMouseDblAsSingleClick() const
Get double click as single click By default, mouse double click has its own handler.
Definition: IControl.h:342
IPlug&#39;s parameter class.
virtual void SetValueFromDelegate(double value, int valIdx=0)
Set the control&#39;s value from the delegate This method is called from the class implementing the IEdit...
Definition: IControl.cpp:157
IRECT FracRect(EDirection layoutDir, float frac, bool fromTopOrRight=false) const
Get a new rectangle which is a fraction of this rectangle.
virtual void SetValueToDefault(int valIdx=kNoValIdx)
Set one or all of the control&#39;s values to the default value of the associated parameter.
Definition: IControl.cpp:181
float GetRoundedCornerRadius(const IRECT &bounds) const
Get the radius of rounded corners for a rectangle, based on the style roundness factor.
Definition: IControl.h:714
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControl.h:1340
IControl * SetActionFunction(IActionFunction actionFunc)
Set an Action Function for this control.
Definition: IControl.h:201
void SetMOColor(const IColor &color)
Sets the color of the text on Mouse Over.
Definition: IControl.h:2012
virtual void OnContextSelection(int itemSelected)
Implement this to respond to a menu selection from CreateContextMenu();.
Definition: IControl.h:179
void SetTooltip(const char *str)
Set a tooltip for the control.
Definition: IControl.h:210
virtual void DrawRoundRect(const IColor &color, const IRECT &bounds, float cornerRadius=5.f, const IBlend *pBlend=0, float thickness=1.f)
Draw a rounded rectangle to the graphics context.
Definition: IGraphics.cpp:2482
Used to manage color data, independent of draw class/platform.
IRECT GetTranslated(float x, float y) const
Get a translated copy of this rectangle.
const char * GetStr() const
Definition: IControl.h:1965
Used to describe a particular gesture.
void SetParams(const std::vector< int > &paramIds)
Update the parameters based on a parameter group name.
Definition: IControl.h:1407
A base interface to be combined with IControl for bitmap-based controls "IBControls", managing an IBitmap.
Definition: IControl.h:586
bool GetIgnoreMouse() const
Definition: IControl.h:373
void DefaultClickActionFunc(IControl *pCaller)
A click action function that triggers the default animation function for DEFAULT_ANIMATION_DURATION.
Definition: IControl.cpp:45
void DrawText(const IText &text, const char *str, const IRECT &bounds, const IBlend *pBlend=0)
Draw some text to the graphics context in a specific rectangle.
Definition: IGraphics.cpp:631
A base class for buttons/momentary switches - cannot be linked to parameters.
Definition: IControl.h:1679
virtual void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod)
Implement this method to respond to a mouse drag event on this control.
Definition: IControl.h:99
void OnRescale() override
If you override this make sure you call the parent method in order to rescale mBitmap.
Definition: IControl.h:1901
IRECT ReduceFromBottom(float amount)
Reduce in height from the bottom edge by &#39;amount&#39; and return the removed region.
void DrawSplash(IGraphics &g, const IRECT &clipRegion=IRECT())
Draw a splash effect when a widget handle is clicked (via SplashClickAnimationFunc) ...
Definition: IControl.h:725
IControl * SetAnimationEndActionFunction(IActionFunction actionFunc)
Set an Action Function to be called at the end of an animation.
Definition: IControl.h:206
IRECT ReduceFromRight(float amount)
Reduce in width from the right edge by &#39;amount&#39; and return the removed region.
User-facing SVG abstraction that you use to manage SVG data ISVG doesn&#39;t actually own the image data...
void AttachIControl(IControl *pControl, const char *label)
Call in the constructor of your IVControl to link the IVectorBase and IControl.
Definition: IControl.h:641
double GetRange() const
Returns the parameter&#39;s range.
virtual void Draw(IGraphics &g)=0
Draw the control to the graphics context.
int GetParamIdx(int valIdx=0) const
Get the index of a parameter that the control is linked to Normaly controls are either linked to a si...
Definition: IControl.cpp:107
virtual int GetValIdxForPos(float x, float y) const
Check to see which of the control&#39;s values relates to this x and y coordinate.
Definition: IControl.h:239
void DrawPressableEllipse(IGraphics &g, const IRECT &bounds, bool pressed, bool mouseOver, bool disabled)
Draw an ellipse-shaped vector button.
Definition: IControl.h:804
float R
Right side of the rectangle (X + W)
bool IsHidden() const
Definition: IControl.h:349
bool IsDisabled() const
Definition: IControl.h:356
virtual bool IsHit(float x, float y) const
Hit test the control.
Definition: IControl.h:385
virtual void OnMouseUp(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse up event on this control.
Definition: IControl.h:91
virtual void ClearStr()
Clear the text .
Definition: IControl.h:1962
IRECT DrawPressableTriangle(IGraphics &g, const IRECT &bounds, bool pressed, bool mouseOver, float angle, bool disabled)
Draw a triangle-shaped vector button.
Definition: IControl.h:959
A base class for mult-strip/track controls, such as multi-sliders, meters Track refers to the channel...
Definition: IControl.h:1248
IRECT MakeRects(const IRECT &parent, bool hasHandle=false)
Calculate the rectangles for the various areas, depending on the style.
Definition: IControl.h:1014
void SetRECT(const IRECT &bounds)
Set the rectangular draw area for this control, within the graphics context.
Definition: IControl.h:309
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControl.h:1823
float H() const
double GetAnimationProgress() const
Get the progress in a control&#39;s animation, in the range 0-1.
Definition: IControl.cpp:429
The lowest level base class of an IGraphics context.
A control to display the textual representation of a parameter.
Definition: IControl.h:2039
An editor delegate base class for a SOMETHING that uses IGraphics for it&#39;s UI.
virtual void OnTouchCancelled(float x, float y, const IMouseMod &mod)
Implement this method to respond to a touch cancel event on this control.
Definition: IControl.h:139
int GetControlTag(const IControl *pControl) const
Get the tag given to a control.
Definition: IGraphics.h:1333
const IRECT & GetRECT() const
Get the rectangular draw area for this control, within the graphics context.
Definition: IControl.h:305
void ForValIdx(int valIdx, T func, Args...args)
A helper template function to call a method for an individual value, or for all values.
Definition: IControl.h:512
bool GetWantsMultiTouch() const
Definition: IControl.h:423
void OnTextEntryCompletion(const char *str, int valIdx) override
Implement this method to handle text input after IGraphics::CreateTextEntry/IControl::PromptUserInput...
Definition: IControl.h:1991
const char * GetTooltip() const
Definition: IControl.h:213
void SetAnimation(IAnimationFunction func, int duration)
Set the animation function and starts it.
Definition: IControl.h:482
float W() const
IBitmapBase(const IBitmap &bitmap)
IBitmapBase Constructor.
Definition: IControl.h:591
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...
IRECT GetScaledAboutCentre(float scale) const
Get a copy of this IRECT where the width and height are multiplied by scale without changing the cent...
void Offset(float l, float t, float r, float b)
Offset each field of the rectangle.
bool CheckLayer(const ILayerPtr &layer)
Test to see if a layer needs drawing, for instance if the control&#39;s bounds were changed.
Definition: IGraphics.cpp:2009
const IColor & GetColor(EVColor color) const
Get value of a specific EVColor in the IVControl.
Definition: IControl.h:664
virtual void OnInit()
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControl.h:151
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControl.h:2007
virtual void DrawSVG(const ISVG &svg, const IRECT &bounds, const IBlend *pBlend=0)
Draw an SVG image to the graphics context.
Definition: IGraphics.cpp:2762
virtual void OnPopupMenuSelection(IPopupMenu *pSelectedMenu, int valIdx)
Implement this method to handle popup menu selection after IGraphics::CreatePopupMenu/IControl::Promp...
Definition: IControl.cpp:281
virtual bool IsDirty()
Called at each display refresh by the IGraphics draw loop, after IControl::Animate(), to determine if the control is marked as dirty.
Definition: IControl.cpp:229
virtual void DrawTrackHandle(IGraphics &g, const IRECT &r, int chIdx, bool aboveBaseValue)
Draw the main body of the track.
Definition: IControl.h:1599
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControl.h:1839
IControl(const IRECT &bounds, int paramIdx=kNoParameter, IActionFunction actionFunc=nullptr)
Constructor.
Definition: IControl.cpp:81
IRECT GetReducedFromBottom(float amount) const
Get a subrect of this IRECT reduced in height from the bottom edge by &#39;amount&#39;.
WDL_String mGroup
Controls can be grouped for hiding and showing panels.
Definition: IControl.h:528
Used to group mouse coordinates with mouse modifier information.
const char * GetGroup() const
Get the group that the control belongs to, if any.
Definition: IControl.h:278
virtual void PathFill(const IPattern &pattern, const IFillOptions &options=IFillOptions(), const IBlend *pBlend=0)=0
Fill the current current path.
IBitmap GetScaledBitmap(IBitmap &inBitmap)
Get a version of the input bitmap from the cache that corresponds to the current screen scale For exa...
Definition: IGraphics.cpp:1493
IDirBrowseControlBase(const IRECT &bounds, const char *extension, bool showFileExtensions=true)
Creates an IDirBrowseControlBase.
Definition: IControl.h:1719
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControl.h:1375
bool GetMouseIsOver() const
This can be used in IControl::Draw() to check if the mouse is over the control, without implementing ...
Definition: IControl.h:459
virtual void OnMouseWheel(float x, float y, const IMouseMod &mod, float d)
Implement this method to respond to a mouse wheel event on this control.
Definition: IControl.h:112
void PathClipRegion(const IRECT r=IRECT())
Clip the current path to a particular region.
Definition: IGraphics.cpp:2743
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
IVectorBase(const IVStyle &style, bool labelInWidget=false, bool valueInWidget=false)
IVectorBase Constructor.
Definition: IControl.h:631
void SetAnimation(IAnimationFunction func)
Set the animation function.
Definition: IControl.h:477
virtual void DrawPressableShape(IGraphics &g, EVShape shape, const IRECT &bounds, bool pressed, bool mouseOver, bool disabled)
Call one of the DrawPressableShape methods.
Definition: IControl.h:775
virtual void OnMouseOver(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouseover event on this control.
Definition: IControl.cpp:265
virtual void DrawLabel(IGraphics &g)
Draw the IVControl label text.
Definition: IControl.h:746
const char * GetGroup() const
Returns the parameter&#39;s group.
IBlend GetBlend() const
Get the Blend for this control.
Definition: IControl.h:293
void SetBlend(const IBlend &blend)
Set the Blend for this control.
Definition: IControl.h:290
virtual void OnMidi(const IMidiMsg &msg)
Implement to receive MIDI messages sent to the control if mWantsMidi == true, see IEditorDelegate:Sen...
Definition: IControl.h:160
IVStyle GetStyle() const
Get the style of this IVControl.
Definition: IControl.h:695
void OnMouseOut() override
Implement this method to respond to a mouseout event on this control.
Definition: IControl.h:2008
virtual void FillRoundRect(const IColor &color, const IRECT &bounds, float cornerRadius=5.f, const IBlend *pBlend=0)
Fill a rounded rectangle with a color.
Definition: IGraphics.cpp:2554
void PromptUserInput(int valIdx=0)
Call this method in response to a mouse event to create an edit box so the user can enter a value...
Definition: IControl.cpp:332
virtual void SnapToMouse(float x, float y, EDirection direction, const IRECT &bounds, int valIdx=-1, double minClip=0., double maxClip=1.)
Set control value based on x, y position within a rectangle.
Definition: IControl.cpp:395
virtual void FillRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0)
Fill a rectangular region of the graphics context with a color.
Definition: IGraphics.cpp:2547
virtual void OnGUIIdle()
This is an idle timer tick call on the GUI thread, only active if USE_IDLE_CALLS is defined...
Definition: IControl.h:408
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.
int NVals() const
Definition: IControl.h:233
virtual void FillEllipse(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0)
Fill an ellipse within a rectangular region of the graphics context.
Definition: IGraphics.cpp:2591
virtual void DrawEllipse(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f)
Draw an ellipse within a rectangular region of the graphics context.
Definition: IGraphics.cpp:2526
A basic control to fill a rectangle with a color or gradient.
Definition: IControl.h:1764
A control that can be specialised with a lambda function, for quick experiments without making a cust...
Definition: IControl.h:1806
BEGIN_IPLUG_NAMESPACE BEGIN_IGRAPHICS_NAMESPACE void DefaultAnimationFunc(IControl *pCaller)
An animation function that just calls the caller control&#39;s OnEndAnimation() method at the end of the ...
Definition: IControl.cpp:21
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControl.h:1783
void SetTargetAndDrawRECTs(const IRECT &bounds)
Set BOTH the draw rect and the target area, within the graphics context for this control.
Definition: IControl.h:321
virtual void OnTextEntryCompletion(const char *str, int valIdx)
Implement this method to handle text input after IGraphics::CreateTextEntry/IControl::PromptUserInput...
Definition: IControl.h:176
IAnimationFunction GetAnimationFunction()
Get the control&#39;s animation function, if it exists.
Definition: IControl.h:485
void DrawBitmap(IGraphics &g)
Draw a frame of a multi-frame bitmap based on the IControl value.
Definition: IControl.h:604
A base class for knob/dial controls, to handle mouse action and Sender.
Definition: IControl.h:1191
bool GetPromptShowsParamLabel() const
Definition: IControl.h:376
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
void DrawLayer(const ILayerPtr &layer, const IBlend *pBlend=nullptr)
Draw a layer to the main IGraphics context.
Definition: IGraphics.cpp:2022
void Pad(float padding)
Pad this IRECT N.B.
virtual void DrawPTHighlight(IGraphics &g)
Implement this to customise how a colored highlight is drawn on the control in ProTools (AAX format o...
Definition: IControl.cpp:387
An abstract IControl base class that you can inherit from in order to make a control that pops up a m...
Definition: IControl.h:1712
bool GetMouseOverWhenDisabled() const
Definition: IControl.h:367
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControl.h:1916
virtual void DrawBitmap(const IBitmap &bitmap, const IRECT &bounds, int srcX, int srcY, const IBlend *pBlend=0)=0
Draw a bitmap (raster) image to the graphics context.
T * As()
Helper function to dynamic cast an IControl to a subclass.
Definition: IControl.h:498
void DrawHorizontalLine(const IColor &color, const IRECT &bounds, float y, const IBlend *pBlend=0, float thickness=1.f)
Draw a horizontal line, within a rectangular region of the graphics context.
Definition: IGraphics.cpp:747
void Set(int a=255, int r=0, int g=0, int b=0)
Set the color parts.
A base class for slider/fader controls, to handle mouse action and Sender.
Definition: IControl.h:1221
virtual bool OnGesture(const IGestureInfo &info)
Definition: IControl.cpp:318
virtual void OnMsgFromDelegate(int msgTag, int dataSize, const void *pData)
Implement to receive messages sent to the control, see IEditorDelegate:SendControlMsgFromDelegate() ...
Definition: IControl.h:157
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControl.h:1986
double GetValue(int valIdx=0) const
Get the control&#39;s value.
Definition: IControl.cpp:151
IControl * AttachGestureRecognizer(EGestureType type, IGestureFunc func)
Add a IGestureFunc that should be triggered in response to a certain type of gesture.
Definition: IControl.cpp:309
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
A base class for controls that can do do multitouch.
Definition: IControl.h:1099
float L
Left side of the rectangle (X)
void OnMouseOut() override
Implement this method to respond to a mouseout event on this control.
Definition: IControl.h:1346
virtual void SetParamIdx(int paramIdx, int valIdx=0)
Set the index of a parameter that the control is linked to If you are calling this "manually" to reus...
Definition: IControl.cpp:113
IActionFunction GetActionFunction()
Get the control&#39;s action function, if it exists.
Definition: IControl.h:488
virtual void SetStyle(const IVStyle &style)
Set the Style of this IVControl.
Definition: IControl.h:687
ILayerPtr EndLayer()
End an IGraphics layer.
Definition: IGraphics.cpp:1977
virtual void SetPosition(float x, float y)
Set the position of the control, preserving the width and height.
Definition: IControl.cpp:289
void SetGroup(const char *groupName)
Assign the control to a control group.
Definition: IControl.h:274
virtual void DrawWidget(IGraphics &g)
Draw the IVControl main widget (override)
Definition: IControl.h:740
IBitmapControl(float x, float y, const IBitmap &bitmap, int paramIdx=kNoParameter, EBlend blend=EBlend::Default)
Creates a bitmap control.
Definition: IControl.h:1880
const IGraphics * GetUI() const
Definition: IControl.h:455
void DrawVerticalLine(const IColor &color, const IRECT &bounds, float x, const IBlend *pBlend=0, float thickness=1.f)
Draw a vertical line, within a rectangular region of the graphics context.
Definition: IGraphics.cpp:740
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
Definition: IControl.h:1845
virtual void OnRescale()
Implement to do something when graphics is scaled globally (e.g.
Definition: IControl.h:145
virtual void OnMouseDblClick(float x, float y, const IMouseMod &mod)
Implement this method to respond to a mouse double click event on this control.
Definition: IControl.cpp:256
void OnTextEntryCompletion(const char *str, int valIdx) override
Implement this method to handle text input after IGraphics::CreateTextEntry/IControl::PromptUserInput...
Definition: IControl.h:2067
void OnMouseDblClick(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse double click event on this control.
Definition: IControl.h:2066
void SetParamsByGroup(const char *paramGroup)
Update the parameters based on a parameter group name.
Definition: IControl.h:1387
virtual IRECT GetKnobDragBounds()
Get the area for which mouse deltas will be used to calculate the amount dragging changes the control...
Definition: IControl.h:1211
int GetValIdxForPos(float x, float y) const override
Check to see which of the control&#39;s values relates to this x and y coordinate.
Definition: IControl.h:1360
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.
Definition: IControl.h:1853
IRECT GetPadded(float padding) const
Get a copy of this IRECT with each value padded by padding N.B.
void SetWantsMidi(bool enable=true)
Specify whether this control wants to know about MIDI messages sent to the UI.
Definition: IControl.h:414
void SetDelegate(IGEditorDelegate &dlg)
Used internally to set the mDelegate (and mGraphics) variables.
Definition: IControl.h:442
int NParams() const
virtual bool OnKeyDown(float x, float y, const IKeyPress &key)
Implement this method to respond to a key down event on this control.
Definition: IControl.h:118
A control to show a clickable URL, that changes color after clicking.
Definition: IControl.h:1999
virtual void CreateContextMenu(IPopupMenu &contextMenu)
Called by default when the user right clicks a control.
Definition: IControl.h:166
virtual void SetValue(double value, int valIdx=0)
Set one of the control&#39;s values.
Definition: IControl.cpp:145
bool GetWantsGestures() const
Definition: IControl.h:431
void SetCLColor(const IColor &color)
Sets the color of the text when the URL has been clicked.
Definition: IControl.h:2015
A base interface to be combined with IControl for vectorial controls "IVControls", in order for them to share a common style If you need more flexibility, you&#39;re on your own!
Definition: IControl.h:624
std::unique_ptr< ILayer > ILayerPtr
ILayerPtr is a managed pointer for transferring the ownership of layers.
Milliseconds GetAnimationDuration() const
Get the duration of animations applied to the control.
Definition: IControl.h:494
IRECT GetAdjustedHandleBounds(IRECT handleBounds) const
Get the adjusted bounds for the widget handle, based on the style settings.
Definition: IControl.h:700
Used to store pattern information for gradients.
IRECT GetFromBottom(float amount) const
Get a subrect of this IRECT bounded in Y by &#39;amount&#39; and the bottom edge.
A basic control to draw an SVG image to the screen.
Definition: IControl.h:1905
void StartAnimation(int duration)
Definition: IControl.cpp:423
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControl.h:1898
IGraphics * GetUI()
Get a pointer to the IGraphics context.
double GetStep() const
Returns the parameter&#39;s step size.
IRECT GetFromTop(float amount) const
Get a subrect of this IRECT bounded in Y by the top edge and &#39;amount&#39;.
virtual void OnDrop(const char *str)
Implement to do something when something was drag &#39;n dropped onto this control.
Definition: IControl.h:142
Used for key press info, such as ASCII representation, virtual key (mapped to win32 codes) and modifi...
Definition: IPlugStructs.h:612
virtual void SetSize(float w, float h)
Set the size of the control, preserving the current position.
Definition: IControl.cpp:301
void AttachIControl(IControl *pControl)
Call in the constructor of your IBControl to link the IBitmapBase and IControl.
Definition: IControl.h:600
virtual ~IControl()
Destructor.
Definition: IControl.h:79
A control to toggle between two text strings on click.
Definition: IControl.h:2024
float T
Top of the rectangle (Y)
virtual void DrawBackground(IGraphics &g, const IRECT &r) override
Draw the IVControl background (usually transparent)
Definition: IControl.h:1480
IParam * GetParam(int paramIdx)
Get a pointer to one of the delegate&#39;s IParam objects.
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
A struct encapsulating a set of properties used to configure IVControls.
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
Definition: IControl.cpp:196
virtual void SetDisabled(bool disable)
Sets disabled mode for the control, the default implementation modifies the mBlend member...
Definition: IControl.cpp:243
const IText & GetText() const
Get the Text object for the control.
Definition: IControl.h:282
IRECT GetReducedFromTop(float amount) const
Get a subrect of this IRECT reduced in height from the top edge by &#39;amount&#39;.
float B
Bottom of the rectangle (Y + H)
virtual void OnMouseOut()
Implement this method to respond to a mouseout event on this control.
Definition: IControl.cpp:273
IRECT GetMidVPadded(float padding) const
Get a copy of this IRECT where its height = 2 * padding but the center point on the Y-axis has not ch...