iPlug2 - C++ Audio Plug-in Framework
Loading...
Searching...
No Matches
IControls.cpp
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
17#include "IControls.h"
18
19using namespace iplug;
20using namespace igraphics;
21
22#pragma mark - VECTOR CONTROLS
23
24const IColor IVKeyboardControl::DEFAULT_BK_COLOR = IColor(255, 70, 70, 70);
25const IColor IVKeyboardControl::DEFAULT_WK_COLOR = IColor(255, 240, 240, 240);
26const IColor IVKeyboardControl::DEFAULT_PK_COLOR = IColor(60, 0, 0, 0);
27const IColor IVKeyboardControl::DEFAULT_FR_COLOR = COLOR_BLACK;
28const IColor IVKeyboardControl::DEFAULT_HK_COLOR = COLOR_ORANGE;
29
30IVLabelControl::IVLabelControl(const IRECT& bounds, const char* label, const IVStyle& style)
31: ITextControl(bounds, label)
32, IVectorBase(style)
33{
34 mText = style.valueText;
35 AttachIControl(this, label);
36}
37
39{
40 DrawBackground(g, mRECT);
41
42 if (mStr.GetLength())
43 {
44 if (mStyle.drawShadows && !IsDisabled())
45 g.DrawText(mStyle.valueText.WithFGColor(GetColor(kSH)), mStr.Get(), mRECT.GetTranslated(mStyle.shadowOffset, mStyle.shadowOffset), &mBlend);
46
47 g.DrawText(mStyle.valueText, mStr.Get(), mRECT, &mBlend);
48 }
49
50 if (mStyle.drawFrame)
51 g.DrawRect(GetColor(kFR), mRECT, &mBlend, mStyle.frameThickness);
52}
53
54IVButtonControl::IVButtonControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, bool labelInButton, bool valueInButton, EVShape shape)
55: IButtonControlBase(bounds, aF)
56, IVectorBase(style, labelInButton, valueInButton)
57{
58 mText = style.valueText;
59 mShape = shape;
60 AttachIControl(this, label);
61}
62
64{
65 DrawBackground(g, mRECT);
66 DrawWidget(g);
67 DrawLabel(g);
68 DrawValue(g, false);
69}
70
72{
73 bool pressed = (bool)GetValue();
74 DrawPressableShape(g, mShape, mWidgetBounds, pressed, mMouseIsOver, IsDisabled());
75}
76
78{
79 SetTargetRECT(MakeRects(mRECT, true));
80 SetDirty(false);
81}
82
83bool IVButtonControl::IsHit(float x, float y) const
84{
85 return mWidgetBounds.Contains(x, y);
86}
87
88IVSwitchControl::IVSwitchControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, bool valueInButton)
90, IVectorBase(style, false, valueInButton)
91{
92 AttachIControl(this, label);
93 mText = style.valueText;
94
95 if(valueInButton)
96 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;
97}
98
99IVSwitchControl::IVSwitchControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, int numStates, bool valueInButton)
100: ISwitchControlBase(bounds, kNoParameter, aF, numStates)
101, IVectorBase(style, false, valueInButton)
102{
103 AttachIControl(this, label);
104 mText = style.valueText;
105
106 if(valueInButton)
107 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;
108}
109
111{
112 DrawBackground(g, mRECT);
113 DrawLabel(g);
114 DrawWidget(g);
115 DrawValue(g, false);
116}
117
119{
120 DrawPressableShape(g, mShape, mWidgetBounds, mMouseDown, mMouseIsOver, IsDisabled());
121}
122
123void IVSwitchControl::SetDirty(bool push, int valIdx)
124{
125 IControl::SetDirty(push);
126
127 const IParam* pParam = GetParam();
128
129 if(pParam)
130 pParam->GetDisplay(mValueStr);
131}
132
134{
135 SetTargetRECT(MakeRects(mRECT, true));
136 SetDirty(false);
137}
138
139bool IVSwitchControl::IsHit(float x, float y) const
140{
141 return mWidgetBounds.Contains(x, y);
142}
143
145{
147
148 const IParam* pParam = GetParam();
149
150 if(pParam)
151 {
152 pParam->GetDisplayWithLabel(mValueStr);
153
154 if(!mLabelStr.GetLength())
155 mLabelStr.Set(pParam->GetName());
156 }
157}
158
159IVToggleControl::IVToggleControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, const char* offText, const char* onText)
160: IVSwitchControl(bounds, paramIdx, label, style, true)
161, mOffText(offText)
162, mOnText(onText)
163{
164 //TODO: assert boolean?
165}
166
167IVToggleControl::IVToggleControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, const char* offText, const char* onText, bool initialState)
168: IVSwitchControl(bounds, aF, label, style, 2, true)
169, mOffText(offText)
170, mOnText(onText)
171{
172 SetValue((double) initialState);
173}
174
176{
177 DrawPressableShape(g, mShape, mWidgetBounds, GetValue() > 0.5, mMouseIsOver, IsDisabled());
178}
179
180void IVToggleControl::DrawValue(IGraphics& g, bool mouseOver)
181{
182 if(mouseOver)
183 g.FillRect(GetColor(kHL), mValueBounds, &mBlend);
184
185 if(GetValue() > 0.5)
186 g.DrawText(mStyle.valueText, mOnText.Get(), mValueBounds, &mBlend);
187 else
188 g.DrawText(mStyle.valueText, mOffText.Get(), mValueBounds, &mBlend);
189}
190
191//TODO: Don't Repeat Yourself!
192IVSlideSwitchControl::IVSlideSwitchControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, bool valueInButton, EDirection direction)
193: IVSwitchControl(bounds, paramIdx, label, style, valueInButton)
194, mDirection(direction)
195{
196 SetActionFunction([&](IControl* pCaller) {
197 SetAnimation([&](IControl* pCaller) {
198 auto progress = pCaller->GetAnimationProgress();
199
200 mHandleBounds = IRECT::LinearInterpolateBetween(mStartRect, mEndRect, static_cast<float>(progress));
201
202 if(mValueInWidget)
203 mValueBounds = mHandleBounds;
204
205 if(progress > 1.) {
206 pCaller->OnEndAnimation();
207 return;
208 }
209 },
210 DEFAULT_ANIMATION_DURATION);
211 });
212}
213
214IVSlideSwitchControl::IVSlideSwitchControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, bool valueInButton, EDirection direction, int numStates, int initialState)
215: IVSwitchControl(bounds, nullptr, label, style, numStates, valueInButton)
216, mDirection(direction)
217{
218 SetValue((double) initialState);
219
220 SetActionFunction([&](IControl* pCaller) {
221 SetAnimation([&](IControl* pCaller) {
222 auto progress = pCaller->GetAnimationProgress();
223
224 mHandleBounds = IRECT::LinearInterpolateBetween(mStartRect, mEndRect, static_cast<float>(progress));
225
226 if(mValueInWidget)
227 mValueBounds = mHandleBounds;
228
229 if(progress > 1.) {
230 pCaller->OnEndAnimation();
231 return;
232 }
233
234 },
235 DEFAULT_ANIMATION_DURATION);
236 });
237
239}
240
241void IVSlideSwitchControl::UpdateRects()
242{
243 mHandleBounds = mStartRect = mWidgetBounds.SubRect(mDirection, mNumStates, GetSelectedIdx());
244 mEndRect = mWidgetBounds.SubRect(mDirection, mNumStates, (GetSelectedIdx() + 1) % mNumStates);
245
246 if(mValueInWidget)
247 mValueBounds = mHandleBounds;
248}
249
251{
253 UpdateRects();
254}
255
256void IVSlideSwitchControl::OnEndAnimation()
257{
258 UpdateRects();
259
260 IControl::OnEndAnimation();
261}
262
264{
265 DrawBackground(g, mRECT);
266 DrawWidget(g);
267 DrawLabel(g);
268
270 DrawValue(g, false);
271}
272
274{
275 DrawTrack(g, mWidgetBounds);
276 DrawHandle(g, mHandleBounds);
277}
278
279void IVSlideSwitchControl::DrawTrack(IGraphics& g, const IRECT& filledArea)
280{
281 float cR = GetRoundedCornerRadius(mHandleBounds);
282 g.FillRoundRect(GetColor(kSH), mWidgetBounds, cR);
283}
284
285void IVSlideSwitchControl::DrawHandle(IGraphics& g, const IRECT& filledArea)
286{
287 DrawPressableShape(g, mShape, filledArea, mMouseDown, mMouseIsOver, IsDisabled());
288}
289
290void IVSlideSwitchControl::SetDirty(bool push, int valIdx)
291{
292 IVSwitchControl::SetDirty(push, valIdx);
293
295 UpdateRects();
296}
297
298IVTabSwitchControl::IVTabSwitchControl(const IRECT& bounds, int paramIdx, const std::vector<const char*>& options, const char* label, const IVStyle& style, EVShape shape, EDirection direction)
299: ISwitchControlBase(bounds, paramIdx, SplashClickActionFunc, (int) options.size())
300, IVectorBase(style)
301, mDirection(direction)
302{
303 AttachIControl(this, label);
304 mText = style.valueText;
305 mText.mAlign = mStyle.valueText.mAlign = EAlign::Center;
306 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;
307 mShape = shape;
308
309 for (auto& option : options)
310 {
311 mTabLabels.Add(new WDL_String(option));
312 }
313}
314
315IVTabSwitchControl::IVTabSwitchControl(const IRECT& bounds, IActionFunction aF, const std::vector<const char*>& options, const char* label, const IVStyle& style, EVShape shape, EDirection direction)
316: ISwitchControlBase(bounds, kNoParameter, aF, static_cast<int>(options.size()))
317, IVectorBase(style)
318, mDirection(direction)
319{
320 AttachIControl(this, label);
321 mText = style.valueText;
322 mText.mAlign = mStyle.valueText.mAlign = EAlign::Center;
323 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;
324 mShape = shape;
325
326 for (auto& option : options)
327 {
328 mTabLabels.Add(new WDL_String(option));
329 }
330}
331
333{
335
336 const IParam* pParam = GetParam();
337
338 if(pParam && mTabLabels.GetSize() == 0) // don't add param display text based labels if allready added via ctor
339 {
340 for (int i = 0; i < mNumStates; i++)
341 {
342 mTabLabels.Add(new WDL_String(GetParam()->GetDisplayText(i)));
343 }
344
345 if(!mLabelStr.GetLength())
346 mLabelStr.Set(pParam->GetName());
347 }
348}
349
351{
352 DrawBackground(g, mRECT);
353 DrawLabel(g);
354 DrawWidget(g);
355}
356
357void IVTabSwitchControl::DrawButton(IGraphics& g, const IRECT& r, bool pressed, bool mouseOver, ETabSegment segment, bool disabled)
358{
359 switch (mShape)
360 {
361 case EVShape::EndsRounded:
362 if(mDirection == EDirection::Horizontal)
363 DrawPressableRectangle(g, r, pressed, mouseOver, disabled, segment == ETabSegment::Start, segment == ETabSegment::End, false, false);
364 else
365 DrawPressableRectangle(g, r, pressed, mouseOver, false, disabled, segment == ETabSegment::Start, false, segment == ETabSegment::End);
366 break;
367 case EVShape::AllRounded:
368 if(mDirection == EDirection::Horizontal)
369 DrawPressableRectangle(g, r, pressed, mouseOver, disabled, true, true, false, false);
370 else
371 DrawPressableRectangle(g, r, pressed, mouseOver, disabled, false, true, false, true);
372 break;
373 default:
374 DrawPressableShape(g, mShape, r, pressed, mouseOver, disabled);
375 break;
376 }
377}
378
379void IVTabSwitchControl::DrawButtonText(IGraphics& g, const IRECT& r, bool pressed, bool mouseOver, ETabSegment segment, bool disabled, const char* textStr)
380{
381 if (CStringHasContents(textStr))
382 {
383 g.DrawText(mStyle.valueText, textStr, r, &mBlend);
384 }
385}
386
388{
389 int selected = GetSelectedIdx();
390 ETabSegment segment = ETabSegment::Start;
391
392 for (int i = 0; i < mNumStates; i++)
393 {
394 IRECT r = mButtons.Get()[i];
395
396 if (i > 0)
397 segment = ETabSegment::Mid;
398
399 if (i == mNumStates-1)
400 segment = ETabSegment::End;
401
402 const bool isSelected = i == selected;
403 const bool isMouseOver = mMouseOverButton == i;
404 const bool isDisabled = IsDisabled() || GetStateDisabled(i);
405
406 DrawButton(g, r, isSelected, isMouseOver, segment, isDisabled);
407
408 if (mTabLabels.Get(i))
409 {
410 DrawButtonText(g, r, isSelected, isMouseOver, segment, isDisabled, mTabLabels.Get(i)->Get());
411 }
412 }
413}
414
415int IVTabSwitchControl::GetButtonForPoint(float x, float y) const
416{
417 for (int i = 0; i < mNumStates; i++)
418 {
419 if (mButtons.Get()[i].Contains(x, y))
420 return i;
421 }
422
423 return -1;
424}
425
426bool IVTabSwitchControl::IsHit(float x, float y) const
427{
428 return GetButtonForPoint(x, y) > -1;
429}
430
431void IVTabSwitchControl::OnMouseDown(float x, float y, const IMouseMod& mod)
432{
433 int index = GetButtonForPoint(x, y);
434 if (index > -1)
435 SetValue(((double) index * (1./(double) (mNumStates-1))));
436
437 SetDirty(true);
438}
439
440void IVTabSwitchControl::OnMouseOver(float x, float y, const IMouseMod& mod)
441{
442 mMouseOverButton = GetButtonForPoint(x, y);
443
445
446 SetDirty(false);
447}
448
450{
451 SetTargetRECT(MakeRects(mRECT));
452
453 mButtons.Resize(0);
454
455 for (int i = 0; i < mNumStates; i++)
456 {
457 mButtons.Add(mWidgetBounds.SubRect(mDirection, mNumStates, i));
458 }
459
460 SetDirty(false);
461}
462
464{
465 return mTabLabels.Get(GetSelectedIdx())->Get();
466}
467
468IVRadioButtonControl::IVRadioButtonControl(const IRECT& bounds, int paramIdx, const std::initializer_list<const char*>& options, const char* label, const IVStyle& style, EVShape shape, EDirection direction, float buttonSize)
469: IVTabSwitchControl(bounds, paramIdx, options, label, style, shape, direction)
470, mButtonSize(buttonSize)
471{
472 mButtonAreaWidth = buttonSize * 3.f;
473 mText.mAlign = mStyle.valueText.mAlign = EAlign::Near;
474 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;
475}
476
477IVRadioButtonControl::IVRadioButtonControl(const IRECT& bounds, IActionFunction aF, const std::initializer_list<const char*>& options, const char* label, const IVStyle& style, EVShape shape, EDirection direction, float buttonSize)
478: IVTabSwitchControl(bounds, aF, options, label, style, shape, direction)
479, mButtonSize(buttonSize)
480{
481 mButtonAreaWidth = buttonSize * 3.f;
482 mText.mAlign = mStyle.valueText.mAlign = EAlign::Near;
483 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;
484}
485
487{
488 int hit = GetSelectedIdx();
489
490 for (int i = 0; i < mNumStates; i++)
491 {
492 IRECT r = mButtons.Get()[i];
493
494 DrawButton(g, r.GetFromLeft(mButtonAreaWidth).GetCentredInside(mButtonSize), i == hit, mMouseOverButton == i, ETabSegment::Mid, IsDisabled() || GetStateDisabled(i));
495
496 if (mTabLabels.Get(i))
497 {
498 r = r.GetFromRight(r.W() - mButtonAreaWidth);
499 g.DrawText(mStyle.valueText.WithFGColor(i == hit ? GetColor(kON) : GetColor(kX1)), mTabLabels.Get(i)->Get(), r, &mBlend);
500 }
501 }
502}
503
505{
506 if (mOnlyButtonsRespondToMouse)
507 {
508 for (int i = 0; i < mNumStates; i++)
509 {
510 if (mButtons.Get()[i].GetFromLeft(mButtonAreaWidth).Contains(x, y))
511 return i;
512 }
513
514 return -1;
515 }
516 else
518}
519
520IVMenuButtonControl::IVMenuButtonControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, EVShape shape)
521: IContainerBase(bounds, paramIdx)
522, IVectorBase(style)
523{
524 AttachIControl(this, "");
525
526 mText = style.valueText;
527 mDisablePrompt = false;
528
529 SetAttachFunc([&, label, style, shape](IContainerBase* pContainer, const IRECT& bounds) {
530 AddChildControl(mButtonControl = new IVButtonControl(bounds, SplashClickActionFunc, label, style.WithValueText(style.valueText.WithVAlign(EVAlign::Middle)), false, true, shape), kNoTag, GetGroup());
531
532 WDL_String str;
534 mButtonControl->SetValueStr(str.Get());
535
536 mButtonControl->SetAnimationEndActionFunction([&](IControl* pCaller){
537 PromptUserInput(mButtonControl->GetWidgetBounds());
538 });
539 });
540
541 SetResizeFunc([&](IContainerBase* pContainer, const IRECT& bounds) {
542 mButtonControl->SetTargetAndDrawRECTs(bounds);
543 });
544}
545
547{
549 mButtonControl->SetStyle(style.WithValueText(style.valueText.WithVAlign(EVAlign::Middle)));
550}
551
552void IVMenuButtonControl::SetValueFromDelegate(double value, int valIdx)
553{
555 WDL_String str;
557 mButtonControl->SetValueStr(str.Get());
558}
559
561{
562 if (pSelectedMenu)
563 {
564 mButtonControl->SetValueStr(pSelectedMenu->GetChosenItem()->GetText());
565 }
566 IControl::OnPopupMenuSelection(pSelectedMenu, valIdx);
567}
568
569void IVMenuButtonControl::SetValueFromUserInput(double value, int valIdx)
570{
571 if (GetValue(valIdx) != value)
572 {
573 SetValue(value, valIdx);
574 SetDirty(true, valIdx);
575
576 WDL_String val;
578 mButtonControl->SetValueStr(val.Get());
579 }
580}
581
582IVKnobControl::IVKnobControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, bool valueIsEditable, bool valueInWidget, float a1, float a2, float aAnchor, EDirection direction, double gearing, float trackSize)
583: IKnobControlBase(bounds, paramIdx, direction, gearing)
584, IVectorBase(style, false, valueInWidget)
585, mAngle1(a1)
586, mAngle2(a2)
587, mAnchorAngle(aAnchor)
588{
589 DisablePrompt(!valueIsEditable);
590 mText = style.valueText;
591 mHideCursorOnDrag = mStyle.hideCursor;
592 mShape = EVShape::Ellipse;
593 mTrackSize = trackSize;
594 AttachIControl(this, label);
595}
596
597IVKnobControl::IVKnobControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, bool valueIsEditable, bool valueInWidget, float a1, float a2, float aAnchor, EDirection direction, double gearing, float trackSize)
598: IKnobControlBase(bounds, kNoParameter, direction, gearing)
599, IVectorBase(style, false, valueInWidget)
600, mAngle1(a1)
601, mAngle2(a2)
602, mAnchorAngle(aAnchor)
603{
604 DisablePrompt(!valueIsEditable);
605 mText = style.valueText;
606 mHideCursorOnDrag = mStyle.hideCursor;
607 mShape = EVShape::Ellipse;
608 mTrackSize = trackSize;
610 AttachIControl(this, label);
611}
612
614{
615 DrawBackground(g, mRECT);
616 DrawLabel(g);
617 DrawWidget(g);
618 DrawValue(g, mValueMouseOver);
619}
620
622{
623 IRECT r;
624
625 if (mWidgetBounds.W() > mWidgetBounds.H())
626 r = mWidgetBounds.GetCentredInside(mWidgetBounds.H()/2.f, mWidgetBounds.H());
627 else
628 r = mWidgetBounds.GetCentredInside(mWidgetBounds.W(), mWidgetBounds.W()/2.f);
629
630 return r;
631}
632
633float IVKnobControl::GetRadius() const
634{
635 float widgetRadius;
636
637 if (mWidgetBounds.W() > mWidgetBounds.H())
638 widgetRadius = (mWidgetBounds.H()/2.f);
639 else
640 widgetRadius = (mWidgetBounds.W()/2.f);
641
642 widgetRadius -= (mTrackSize/2.f);
643
644 return widgetRadius;
645}
646
647IRECT IVKnobControl::GetTrackBounds() const
648{
649 return mWidgetBounds.GetCentredInside((GetRadius() + mTrackSize) * 2.f );
650}
651
653{
654 float widgetRadius = GetRadius();// The radius out to the indicator track arc
655 const float cx = mWidgetBounds.MW(), cy = mWidgetBounds.MH();
656 IRECT knobHandleBounds = mWidgetBounds.GetCentredInside((widgetRadius - mTrackToHandleDistance) * 2.f );
657 const float angle = mAngle1 + (static_cast<float>(GetValue()) * (mAngle2 - mAngle1));
658 DrawIndicatorTrack(g, angle, cx, cy, widgetRadius);
659 DrawPressableShape(g, /*mShape*/ EVShape::Ellipse, knobHandleBounds, mMouseDown, mMouseIsOver, IsDisabled());
660 DrawPointer(g, angle, cx, cy, knobHandleBounds.W() / 2.f);
661}
662
663void IVKnobControl::DrawIndicatorTrack(IGraphics& g, float angle, float cx, float cy, float radius)
664{
665 if (mTrackSize > 0.f)
666 {
667 g.DrawArc(GetColor(kX1), cx, cy, radius, angle >= mAnchorAngle ? mAnchorAngle : mAnchorAngle - (mAnchorAngle - angle), angle >= mAnchorAngle ? angle : mAnchorAngle, &mBlend, mTrackSize);
668 }
669}
670
671void IVKnobControl::DrawPointer(IGraphics& g, float angle, float cx, float cy, float radius)
672{
673 g.DrawRadialLine(GetColor(kFR), cx, cy, angle, mInnerPointerFrac * radius, mOuterPointerFrac * radius, &mBlend, mPointerThickness);
674}
675
676void IVKnobControl::OnMouseDown(float x, float y, const IMouseMod& mod)
677{
678 if(mStyle.showValue && mValueBounds.Contains(x, y))
679 {
680 PromptUserInput(mValueBounds);
681 }
682 else
683 {
685 }
686
687 SetDirty(false);
688}
689
690void IVKnobControl::OnMouseDblClick(float x, float y, const IMouseMod& mod)
691{
692 #ifdef AAX_API
693 PromptUserInput(mValueBounds);
694 #else
696 #endif
697}
698
699void IVKnobControl::OnMouseUp(float x, float y, const IMouseMod& mod)
700{
702 SetDirty(true);
703}
704
705void IVKnobControl::OnMouseOver(float x, float y, const IMouseMod& mod)
706{
707 if(mStyle.showValue && !mDisablePrompt)
708 mValueMouseOver = mValueBounds.Contains(x,y);
709
711
712 SetDirty(false);
713}
714
716{
717 SetTargetRECT(MakeRects(mRECT));
718 SetDirty(false);
719}
720
721bool IVKnobControl::IsHit(float x, float y) const
722{
723 if(!mDisablePrompt)
724 {
725 if(mValueBounds.Contains(x,y))
726 return true;
727 }
728
729 return mWidgetBounds.Contains(x, y);
730}
731
732void IVKnobControl::SetDirty(bool push, int valIdx)
733{
735
736 const IParam* pParam = GetParam();
737
738 if(pParam)
739 pParam->GetDisplayWithLabel(mValueStr);
740}
741
743{
744 const IParam* pParam = GetParam();
745
746 if(pParam)
747 {
748 pParam->GetDisplayWithLabel(mValueStr);
749
750 if(!mLabelStr.GetLength())
751 mLabelStr.Set(pParam->GetName());
752 }
753}
754
755IVSliderControl::IVSliderControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, bool valueIsEditable, EDirection dir, double gearing, float handleSize, float trackSize, bool handleInsideTrack, float handleXOffset, float handleYOffset)
756: ISliderControlBase(bounds, paramIdx, dir, gearing, handleSize)
757, IVectorBase(style)
758, mHandleInsideTrack(handleInsideTrack)
759, mHandleXOffset(handleXOffset)
760, mHandleYOffset(handleYOffset)
761{
762 DisablePrompt(!valueIsEditable);
763 mText = style.valueText;
764 mHideCursorOnDrag = style.hideCursor;
765 mShape = EVShape::Ellipse;
766 mTrackSize = trackSize;
767 AttachIControl(this, label);
768}
769
770IVSliderControl::IVSliderControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, bool valueIsEditable, EDirection dir, double gearing, float handleSize, float trackSize, bool handleInsideTrack, float handleXOffset, float handleYOffset)
771: ISliderControlBase(bounds, aF, dir, gearing, handleSize)
772, IVectorBase(style)
773, mHandleInsideTrack(handleInsideTrack)
774, mHandleXOffset(handleXOffset)
775, mHandleYOffset(handleYOffset)
776{
777 DisablePrompt(!valueIsEditable);
778 mText = style.valueText;
779 mHideCursorOnDrag = style.hideCursor;
780 mShape = EVShape::Ellipse;
781 mTrackSize = trackSize;
782 AttachIControl(this, label);
783}
784
786{
787 DrawBackground(g, mRECT);
788 DrawLabel(g);
789 DrawWidget(g);
790 DrawValue(g, mValueMouseOver);
791}
792
793void IVSliderControl::DrawTrack(IGraphics& g, const IRECT& filledArea)
794{
795 const float extra = mHandleInsideTrack ? mHandleSize : 0.f;
796 const IRECT adjustedTrackBounds = mDirection == EDirection::Vertical ? mTrackBounds.GetVPadded(extra) : mTrackBounds.GetHPadded(extra);
797 const IRECT adjustedFillBounds = mDirection == EDirection::Vertical ? filledArea.GetVPadded(extra) : filledArea.GetHPadded(extra);
798 const float cr = GetRoundedCornerRadius(mTrackBounds);
799
800 g.FillRoundRect(GetColor(kSH), adjustedTrackBounds, cr, &mBlend);
801 g.FillRoundRect(GetColor(kX1), adjustedFillBounds, cr, &mBlend);
802
803 if(mStyle.drawFrame)
804 g.DrawRoundRect(GetColor(kFR), adjustedTrackBounds, cr, &mBlend, mStyle.frameThickness);
805}
806
808{
809 IRECT filledTrack = mTrackBounds.FracRect(mDirection, (float) GetValue());
810
811 if(mTrackSize > 0.f)
812 DrawTrack(g, filledTrack);
813
814 float cx, cy;
815
816 const float offset = (mStyle.drawShadows && mShape != EVShape::Ellipse /* TODO? */) ? mStyle.shadowOffset * 0.5f : 0.f;
817
818 if(mDirection == EDirection::Vertical)
819 {
820 cx = filledTrack.MW() + offset;
821 cy = filledTrack.T;
822 }
823 else
824 {
825 cx = filledTrack.R;
826 cy = filledTrack.MH() + offset;
827 }
828
829 if(mHandleSize > 0.f)
830 {
831 DrawHandle(g, {cx+mHandleXOffset-mHandleSize, cy+mHandleYOffset-mHandleSize, cx+mHandleXOffset+mHandleSize, cy+mHandleYOffset+mHandleSize});
832 }
833}
834
835void IVSliderControl::DrawHandle(IGraphics& g, const IRECT& bounds)
836{
837 DrawPressableShape(g, mShape, bounds, mMouseDown, mMouseIsOver, IsDisabled());
838}
839
840void IVSliderControl::OnMouseDown(float x, float y, const IMouseMod& mod)
841{
842 if(mStyle.showValue && mValueBounds.Contains(x, y))
843 {
844 PromptUserInput(mValueBounds);
845 }
846 else
847 {
849 }
850}
851
852void IVSliderControl::OnMouseDblClick(float x, float y, const IMouseMod& mod)
853{
854 #ifdef AAX_API
855 PromptUserInput(mValueBounds);
856 #else
858 #endif
859}
860
861void IVSliderControl::OnMouseUp(float x, float y, const IMouseMod& mod)
862{
864 SetDirty(true);
865}
866
867void IVSliderControl::OnMouseOver(float x, float y, const IMouseMod& mod)
868{
869 if(mStyle.showValue && !mDisablePrompt)
870 mValueMouseOver = mValueBounds.Contains(x,y);
871
873 SetDirty(false);
874}
875
877{
878 SetTargetRECT(MakeRects(mRECT));
879
880 if(mDirection == EDirection::Vertical)
881 mTrackBounds = mWidgetBounds.GetPadded(-mHandleSize).GetMidHPadded(mTrackSize);
882 else
883 mTrackBounds = mWidgetBounds.GetPadded(-mHandleSize).GetMidVPadded(mTrackSize);
884
885 SetDirty(false);
886}
887
888bool IVSliderControl::IsHit(float x, float y) const
889{
890 if(!mDisablePrompt)
891 {
892 if(mValueBounds.Contains(x,y))
893 {
894 return true;
895 }
896 }
897
898 return mWidgetBounds.Contains(x, y);
899}
900
901void IVSliderControl::SetDirty(bool push, int valIdx)
902{
904
905 const IParam* pParam = GetParam();
906
907 if(pParam)
908 pParam->GetDisplayWithLabel(mValueStr);
909}
910
912{
913 const IParam* pParam = GetParam();
914
915 if(pParam)
916 {
917 if(!mLabelStr.GetLength())
918 mLabelStr.Set(pParam->GetName());
919
920 pParam->GetDisplayWithLabel(mValueStr);
921 }
922}
923
924IVRangeSliderControl::IVRangeSliderControl(const IRECT& bounds, const std::initializer_list<int>& params, const char* label, const IVStyle& style, EDirection dir, bool onlyHandle, float handleSize, float trackSize)
925: IVTrackControlBase(bounds, label, style, params, 0, dir)
926, mHandleSize(handleSize)
927{
928 mTrackSize = trackSize;
929}
930
932{
933 DrawBackground(g, mRECT);
934 DrawLabel(g);
935 DrawWidget(g);
936// DrawValue(g, mValueMouseOver);
937}
938
939void IVRangeSliderControl::MakeTrackRects(const IRECT& bounds)
940{
941 for (int ch = 0; ch < NVals(); ch++)
942 {
943 if(mDirection == EDirection::Vertical)
944 mTrackBounds.Get()[ch] = bounds.GetPadded(-mHandleSize).GetMidHPadded(mTrackSize);
945 else
946 mTrackBounds.Get()[ch] = bounds.GetPadded(-mHandleSize).GetMidVPadded(mTrackSize);
947 }
948}
949
950void IVRangeSliderControl::DrawTrack(IGraphics& g, const IRECT& r, int chIdx)
951{
952 bool thisTrack = mMouseOverHandle == chIdx;
953 float angle = 0.f;
954
955 if(mDirection == EDirection::Horizontal)
956 angle = chIdx % 2 ? 180.f : 0.f;
957 else
958 angle = chIdx % 2 ? 270.f : 90.f;
959
960 DrawPressableTriangle(g, GetHandleBounds(chIdx), thisTrack && mMouseIsDown, thisTrack, angle, IsDisabled());
961}
962
963IRECT IVRangeSliderControl::GetHandleBounds(int trackIdx)
964{
965 IRECT filledTrack = mTrackBounds.Get()[trackIdx].FracRect(mDirection, (float) GetValue(trackIdx));
966 float cx, cy;
967 const float offset = (mStyle.drawShadows && mShape != EVShape::Ellipse /* TODO? */) ? mStyle.shadowOffset * 0.5f : 0.f;
968 if(mDirection == EDirection::Vertical)
969 {
970 cx = filledTrack.MW() + offset;
971 cy = filledTrack.T;
972
973 if(trackIdx % 2)
974 return IRECT(cx+mTrackSize, cy-mHandleSize, cx+(2.f*mHandleSize)+mTrackSize, cy+mHandleSize);
975 else
976 return IRECT(cx-(2.f*mHandleSize), cy-mHandleSize, cx, cy+mHandleSize);
977 }
978 else
979 {
980 cx = filledTrack.R;
981 cy = filledTrack.MH() + offset;
982
983 if(trackIdx % 2)
984 return IRECT(cx-mHandleSize, cy-(2.f*mHandleSize), cx+mHandleSize, cy);
985 else
986 return IRECT(cx-mHandleSize, cy+mTrackSize, cx+mHandleSize, cy+(2.f*mHandleSize)+mTrackSize);
987 }
988}
989
991{
992 IRECT r = mTrackBounds.Get()[0];
993
994 DrawTrackBackground(g, r, 0);
995
996 for(int i=0;i<NVals()-1;i++)
997 {
998 IRECT filled1 = mTrackBounds.Get()[i].FracRect(mDirection, (float) GetValue(i));
999 IRECT filled2 = mTrackBounds.Get()[i+1].FracRect(mDirection, (float) GetValue(i+1));
1000
1001 if(mDirection == EDirection::Vertical)
1002 g.FillRect(GetColor(kX1), IRECT(filled1.L, filled1.T < filled2.T ? filled1.T : filled2.T, filled1.R, filled1.T > filled2.T ? filled1.T : filled2.T), &mBlend);
1003 else
1004 g.FillRect(GetColor(kX1), IRECT(filled1.R < filled2.R ? filled1.R : filled2.R, filled1.T, filled1.R > filled2.R ? filled1.R : filled2.R, filled1.B), &mBlend);
1005 }
1006
1007 if(mStyle.drawFrame && mDrawTrackFrame)
1008 g.DrawRect(GetColor(kFR), r, &mBlend, mStyle.frameThickness);
1009
1011}
1012
1013void IVRangeSliderControl::OnMouseOver(float x, float y, const IMouseMod& mod)
1014{
1015 IRECT bounds;
1016 int hitHandle = -1;
1017
1018 for(int i=0;i<NVals();i++)
1019 {
1020 bounds = GetHandleBounds(i);
1021 if(bounds.Contains(x, y))
1022 {
1023 hitHandle = i;
1024 break;
1025 }
1026 }
1027
1028 mMouseOverHandle = hitHandle;
1029
1031 SetDirty(false);
1032}
1033
1034void IVRangeSliderControl::OnMouseDown(float x, float y, const IMouseMod& mod)
1035{
1036 mMouseIsDown = true;
1037 OnMouseDrag(x, y, 0., 0., mod);
1038}
1039
1040void IVRangeSliderControl::OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod)
1041{
1042 if(mMouseOverHandle == -1)
1043 return;
1044
1045 auto minClip = mMouseOverHandle == 0 ? 0. : GetValue(mMouseOverHandle-1);
1046 auto maxClip = mMouseOverHandle == NVals()-1 ? 1. : GetValue(mMouseOverHandle+1);
1047 SnapToMouse(x, y, mDirection, mWidgetBounds, mMouseOverHandle, minClip, maxClip);
1048}
1049
1050
1051IVXYPadControl::IVXYPadControl(const IRECT& bounds, const std::initializer_list<int>& params, const char* label, const IVStyle& style, float handleRadius, bool trackClipsHandle, bool drawCross)
1052: IControl(bounds, params)
1053, IVectorBase(style)
1054, mHandleRadius(handleRadius)
1055, mTrackClipsHandle(trackClipsHandle)
1056, mDrawCross(drawCross)
1057{
1058 mShape = EVShape::Ellipse;
1059 AttachIControl(this, label);
1060}
1061
1063{
1064 DrawBackground(g, mRECT);
1065 DrawLabel(g);
1066
1067 if(mStyle.drawFrame)
1068 g.DrawRect(GetColor(kFR), mWidgetBounds, &mBlend, mStyle.frameThickness);
1069
1070 DrawWidget(g);
1071}
1072
1074{
1075 DrawTrack(g);
1076
1077 const IRECT trackBounds = mWidgetBounds.GetPadded(mTrackClipsHandle ? 0 : -mHandleRadius);
1078
1079 const float xpos = static_cast<float>(GetValue(0)) * trackBounds.W();
1080 const float ypos = static_cast<float>(GetValue(1)) * trackBounds.H();
1081 const IRECT handleBounds = IRECT(trackBounds.L + xpos-mHandleRadius, trackBounds.B - ypos-mHandleRadius, trackBounds.L + xpos+mHandleRadius, trackBounds.B -ypos+mHandleRadius);
1082
1083 DrawHandle(g, trackBounds, handleBounds);
1084}
1085
1086void IVXYPadControl::DrawHandle(IGraphics& g, const IRECT& trackBounds, const IRECT& handleBounds)
1087{
1088 if (mTrackClipsHandle)
1089 g.PathClipRegion(trackBounds.GetPadded(-0.5f * mStyle.frameThickness));
1090
1091 DrawPressableShape(g, mShape, handleBounds, mMouseDown, mMouseIsOver, IsDisabled());
1092}
1093
1094void IVXYPadControl::DrawTrack(IGraphics& g)
1095{
1096 if (mDrawCross)
1097 {
1098 g.DrawVerticalLine(GetColor(kSH), mWidgetBounds, 0.5);
1099 g.DrawHorizontalLine(GetColor(kSH), mWidgetBounds, 0.5);
1100 }
1101}
1102
1103void IVXYPadControl::OnMouseDown(float x, float y, const IMouseMod& mod)
1104{
1105 mMouseDown = true;
1106 if (mStyle.hideCursor)
1107 GetUI()->HideMouseCursor(true, false);
1108
1109 OnMouseDrag(x, y, 0., 0., mod);
1110}
1111
1112void IVXYPadControl::OnMouseUp(float x, float y, const IMouseMod& mod)
1113{
1114 if (mStyle.hideCursor)
1115 GetUI()->HideMouseCursor(false);
1116
1117 mMouseDown = false;
1118 SetDirty(true);
1119}
1120
1121void IVXYPadControl::OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod& mod)
1122{
1123 mRECT.Constrain(x, y);
1124 float xn = (x - mRECT.L) / mRECT.W();
1125 float yn = 1.f - ((y - mRECT.T) / mRECT.H());
1126 SetValue(xn, 0);
1127 SetValue(yn, 1);
1128 SetDirty(true);
1129}
1130
1132{
1133 SetTargetRECT(MakeRects(mRECT));
1134 SetDirty(false);
1135}
1136
1137IVPlotControl::IVPlotControl(const IRECT& bounds, const std::initializer_list<Plot>& plots, int numPoints, const char* label, const IVStyle& style, float min, float max, bool useLayer)
1138: IControl(bounds)
1139, IVectorBase(style)
1140, mMin(min)
1141, mMax(max)
1142, mUseLayer(useLayer)
1143{
1144 mPoints.resize(numPoints);
1145
1146 AttachIControl(this, label);
1147
1148 for(auto plot : plots)
1149 {
1150 AddPlotFunc(plot.color, plot.func);
1151 }
1152}
1153
1155{
1156 DrawBackground(g, mRECT);
1157 DrawLabel(g);
1158
1159 float hdiv = mWidgetBounds.W() / static_cast<float>(mHorizontalDivisions);
1160 float vdiv = mWidgetBounds.H() / static_cast<float>(mVerticalDivisions + 2);
1161
1162 IRECT plotsRECT = mWidgetBounds.GetVPadded(-vdiv);
1163
1164 auto drawFunc = [&](){
1165 g.DrawGrid(GetColor(kSH), mWidgetBounds, hdiv, vdiv, &mBlend);
1166
1167 for (int p=0; p<mPlots.size(); p++)
1168 {
1169 for (int i=0; i<mPoints.size(); i++)
1170 {
1171 auto v = mPlots[p].func((static_cast<float>(i)/static_cast<float>(mPoints.size() - 1)));
1172 v = (v - mMin) / (mMax-mMin);
1173 mPoints[i] = static_cast<float>(v);
1174 }
1175
1176 g.DrawData(mPlots[p].color, plotsRECT, mPoints.data(), static_cast<int>(mPoints.size()), nullptr, &mBlend, mTrackSize);
1177 }
1178
1179 if (mStyle.drawFrame)
1180 g.DrawRect(GetColor(kFR), mWidgetBounds, &mBlend, mStyle.frameThickness);
1181 };
1182
1183 if(mUseLayer)
1184 {
1185 if (!g.CheckLayer(mLayer))
1186 {
1187 g.StartLayer(this, mRECT);
1188 drawFunc();
1189 mLayer = g.EndLayer();
1190 }
1191
1192 g.DrawLayer(mLayer, &mBlend);
1193 }
1194 else
1195 drawFunc();
1196}
1197
1199{
1200 SetTargetRECT(MakeRects(mRECT));
1201 SetDirty(false);
1202}
1203
1204void IVPlotControl::AddPlotFunc(const IColor& color, const IPlotFunc& func)
1205{
1206 mPlots.push_back({color, func});
1207
1208 if(mLayer)
1209 mLayer->Invalidate();
1210 SetDirty(false);
1211}
1212
1213IVGroupControl::IVGroupControl(const IRECT& bounds, const char* label, float labelOffset, const IVStyle& style, IContainerBase::AttachFunc attachFunc, IContainerBase::ResizeFunc resizeFunc)
1214: IContainerBase(bounds, attachFunc, resizeFunc)
1215, IVectorBase(style)
1216, mLabelOffset(labelOffset)
1217{
1218 AttachIControl(this, label);
1219 mIgnoreMouse = true;
1220}
1221
1222IVGroupControl::IVGroupControl(const char* label, const char* groupName, float padL, float padT, float padR, float padB, const IVStyle& style)
1224, IVectorBase(style)
1225, mGroupName(groupName)
1226, mPadL(padL)
1227, mPadT(padT)
1228, mPadR(padR)
1229, mPadB(padB)
1230{
1231 AttachIControl(this, label);
1232 mIgnoreMouse = true;
1233}
1234
1236{
1237 if(mGroupName.GetLength())
1238 {
1239 SetBoundsBasedOnGroup(mGroupName.Get(), mPadL, mPadT, mPadR, mPadB);
1240 }
1241}
1242
1244{
1245// const float cr = GetRoundedCornerRadius(mWidgetBounds);
1246// g.FillRoundRect(GetColor(kBG), mWidgetBounds, cr);
1247// g.FillRect(GetColor(kBG), mLabelBounds);
1248 DrawLabel(g);
1249 DrawWidget(g);
1250}
1251
1253{
1254 const float cr = GetRoundedCornerRadius(mWidgetBounds);
1255 const float ft = mStyle.frameThickness;
1256 const float hft = ft/2.f;
1257
1258 int nPaths = /*mStyle.drawShadows ? 2 :*/ 1;
1259
1260 auto b = mWidgetBounds.GetPadded(/*mStyle.drawShadows ? -mStyle.shadowOffset :*/ 0.f);
1261
1262 auto labelR = mLabelBounds.Empty() ? mRECT.MW() : mLabelBounds.R;
1263 auto labelL = mLabelBounds.Empty() ? mRECT.MW() : mLabelBounds.L;
1264
1265 for(int i=0; i < nPaths; i++)
1266 {
1267 const float offset = i == 0 ? 0.f : mStyle.shadowOffset;
1268 g.PathClear();
1269 g.PathMoveTo(labelR, b.T + hft - offset);
1270 g.PathArc(b.R - cr - hft - offset, b.T + cr + hft - offset, cr, 0.f, 90.f);
1271 g.PathArc(b.R - cr - hft - offset, b.B - cr - hft - offset, cr, 90.f, 180.f);
1272 g.PathArc(b.L + cr + hft - offset, b.B - cr - hft - offset, cr, 180.f, 270.f);
1273 g.PathArc(b.L + cr + hft - offset, b.T + cr + hft - offset, cr, 270.f, 360.f);
1274 g.PathLineTo(labelL, b.T + hft - offset);
1275 g.PathStroke(mStyle.drawShadows ? GetColor(i == 0 ? kSH : kFR) : GetColor(kFR), ft);
1276 }
1277}
1278
1280{
1281 SetTargetRECT(MakeRects(mRECT));
1282 mLabelBounds.HPad(mLabelPadding);
1283 mWidgetBounds.Offset(0, -(mLabelBounds.H()/2.f) - (mStyle.frameThickness/2.f), 0, 0);
1284 const float cr = GetRoundedCornerRadius(mWidgetBounds);
1285 mLabelBounds.Translate(mRECT.L - mLabelBounds.L + mStyle.frameThickness + mLabelOffset + cr, 0.f);
1286 SetDirty(false);
1287}
1288
1289void IVGroupControl::SetBoundsBasedOnGroup(const char* groupName, float padL, float padT, float padR, float padB)
1290{
1291 mGroupName.Set(groupName);
1292
1293 IRECT unionRect;
1294 GetUI()->ForControlInGroup(mGroupName.Get(), [&unionRect](IControl* pControl) { unionRect = unionRect.Union(pControl->GetRECT()); });
1295 float halfLabelHeight = mLabelBounds.H()/2.f;
1296 unionRect.GetVPadded(halfLabelHeight);
1297 mRECT = unionRect.GetPadded(padL, padT, padR, padB);
1298
1299 OnResize();
1300}
1301
1302IVColorSwatchControl::IVColorSwatchControl(const IRECT& bounds, const char* label, ColorChosenFunc func, const IVStyle& style, ECellLayout layout,
1303 const std::initializer_list<EVColor>& colorIDs, const std::initializer_list<const char*>& labelsForIDs)
1304: IControl(bounds)
1305, IVectorBase(style)
1306, mColorChosenFunc(func)
1307, mLayout(layout)
1308, mColorIdForCells(colorIDs)
1309{
1310 assert(colorIDs.size() == labelsForIDs.size());
1311
1312 AttachIControl(this, label);
1313 mCellRects.Resize(static_cast<int>(mColorIdForCells.size()));
1314 mText.mAlign = mStyle.valueText.mAlign = EAlign::Far;
1315
1316 for (int i=0;i<colorIDs.size();i++)
1317 {
1318 mLabels.Add(new WDL_String(labelsForIDs.begin()[i]));
1319 }
1320}
1321
1323{
1324 DrawWidget(g);
1325 DrawLabel(g);
1326}
1327
1329{
1330 for (int i=0; i< mColorIdForCells.size(); i++)
1331 {
1332 WDL_String* pStr = mLabels.Get(i);
1333 IRECT r = mCellRects.Get()[i];
1334 IRECT buttonBounds = r.FracRectHorizontal(pStr->GetLength() ? 0.25f : 1.f, true);
1335 g.FillRect(GetColor(mColorIdForCells[i]), buttonBounds, &mBlend);
1336 g.DrawRect(i == mCellOver ? COLOR_GRAY : COLOR_DARK_GRAY, buttonBounds.GetPadded(0.5f), &mBlend);
1337
1338 if(pStr->GetLength())
1339 g.DrawText(mStyle.valueText, mLabels.Get(i)->Get(), r.FracRectHorizontal(0.7f, false), &mBlend);
1340 }
1341}
1342
1344{
1345 SetTargetRECT(MakeRects(mRECT, true));
1346
1347 int rows = 3;
1348 int columns = 3;
1349
1350 if(mLayout == ECellLayout::kGrid)
1351 {
1352 rows = 3;
1353 columns = 3;
1354 }
1355 else if (mLayout == ECellLayout::kHorizontal)
1356 {
1357 rows = 1;
1358 columns = static_cast<int>(mColorIdForCells.size());
1359 }
1360 else if (mLayout == ECellLayout::kVertical)
1361 {
1362 rows = static_cast<int>(mColorIdForCells.size());
1363 columns = 1;
1364 }
1365
1366 for (int i=0; i< mColorIdForCells.size(); i++)
1367 {
1368 mCellRects.Get()[i] = mWidgetBounds.GetGridCell(i, rows, columns).GetPadded(-2);
1369 }
1370
1371 SetDirty(false);
1372}
1373
1374void IVColorSwatchControl::OnMouseOver(float x, float y, const IMouseMod& mod)
1375{
1376 for (int i=0; i<mColorIdForCells.size(); i++)
1377 {
1378 if(mCellRects.Get()[i].Contains(x, y))
1379 {
1380 mCellOver = i;
1381 SetDirty();
1382 return;
1383 }
1384 }
1385
1386 mCellOver = -1;
1387 SetDirty();
1388}
1389
1391{
1392 mCellOver = -1;
1393 SetDirty();
1394}
1395
1396void IVColorSwatchControl::OnMouseDown(float x, float y, const IMouseMod& mod)
1397{
1398 int cellClicked=-1;
1399
1400 for (int i=0; i<mColorIdForCells.size(); i++)
1401 {
1402 if(mCellRects.Get()[i].Contains(x, y))
1403 {
1404 cellClicked = i;
1405 break;
1406 }
1407 }
1408
1409 if(cellClicked > -1)
1410 {
1411 EVColor vColorClicked = mColorIdForCells[cellClicked];
1412 IColor color = GetColor(vColorClicked);
1413 GetUI()->PromptForColor(color, "Choose a color", [this, cellClicked, vColorClicked](IColor result) {
1414 SetColor(vColorClicked, result);
1415 if(mColorChosenFunc)
1416 mColorChosenFunc(cellClicked, result);
1417 });
1418 }
1419}
1420
1421#pragma mark - SVG CONTROLS
1422
1423ISVGButtonControl::ISVGButtonControl(const IRECT& bounds, IActionFunction aF, const ISVG& offImage, const ISVG& onImage)
1424: IButtonControlBase(bounds, aF)
1425, mOffSVG(offImage)
1426, mOnSVG(onImage)
1427{
1428}
1429
1430
1431ISVGButtonControl::ISVGButtonControl(const IRECT& bounds, IActionFunction aF, const ISVG& image, const std::array<IColor, 4> colors, EColorReplacement colorReplacement)
1432: IButtonControlBase(bounds, aF)
1433, mOffSVG(image)
1434, mOnSVG(image)
1435, mColors(colors)
1436, mColorReplacement(colorReplacement)
1437{
1438}
1439
1441{
1442 IColor* pOnColorFill = nullptr;
1443 IColor* pOffColorFill = nullptr;
1444 IColor* pOnColorStroke = nullptr;
1445 IColor* pOffColorStroke = nullptr;
1446
1447 switch (mColorReplacement) {
1448
1449 case EColorReplacement::None:
1450 break;
1451 case EColorReplacement::Fill:
1452 pOnColorFill = mMouseIsOver ? &mColors[3] : &mColors[1];
1453 pOffColorFill = mMouseIsOver ? &mColors[2] : &mColors[0];
1454 break;
1455 case EColorReplacement::Stroke:
1456 pOnColorStroke = mMouseIsOver ? &mColors[3] : &mColors[1];
1457 pOffColorStroke = mMouseIsOver ? &mColors[2] : &mColors[0];
1458 break;
1459 }
1460
1461 if (GetValue() > 0.5)
1462 g.DrawSVG(mOnSVG, mRECT, &mBlend, pOnColorStroke, pOnColorFill);
1463 else
1464 g.DrawSVG(mOffSVG, mRECT, &mBlend, pOffColorStroke, pOffColorFill);
1465}
1466
1467ISVGToggleControl::ISVGToggleControl(const IRECT& bounds, IActionFunction aF, const ISVG& offImage, const ISVG& onImage)
1468: ISwitchControlBase(bounds, kNoParameter, aF)
1469, mOffSVG(offImage)
1470, mOnSVG(onImage)
1471{
1472}
1473
1474ISVGToggleControl::ISVGToggleControl(const IRECT& bounds, int paramIdx, const ISVG& offImage, const ISVG& onImage)
1475: ISwitchControlBase(bounds, paramIdx)
1476, mOffSVG(offImage)
1477, mOnSVG(onImage)
1478{
1479}
1480
1481ISVGToggleControl::ISVGToggleControl(const IRECT& bounds, IActionFunction aF, const ISVG& image, const std::array<IColor, 4> colors, EColorReplacement colorReplacement)
1482: ISwitchControlBase(bounds, kNoParameter, aF)
1483, mOffSVG(image)
1484, mOnSVG(image)
1485, mColors(colors)
1486, mColorReplacement(colorReplacement)
1487{
1488}
1489
1490ISVGToggleControl::ISVGToggleControl(const IRECT& bounds, int paramIdx, const ISVG& image, const std::array<IColor, 4> colors, EColorReplacement colorReplacement)
1491: ISwitchControlBase(bounds, paramIdx)
1492, mOffSVG(image)
1493, mOnSVG(image)
1494, mColors(colors)
1495, mColorReplacement(colorReplacement)
1496{
1497}
1498
1500{
1501 IColor* pOnColorFill = nullptr;
1502 IColor* pOffColorFill = nullptr;
1503 IColor* pOnColorStroke = nullptr;
1504 IColor* pOffColorStroke = nullptr;
1505
1506 switch (mColorReplacement) {
1507 case EColorReplacement::None:
1508 break;
1509 case EColorReplacement::Fill:
1510 pOnColorFill = mMouseIsOver ? &mColors[3] : &mColors[1];
1511 pOffColorFill = mMouseIsOver ? &mColors[2] : &mColors[0];
1512 break;
1513 case EColorReplacement::Stroke:
1514 pOnColorStroke = mMouseIsOver ? &mColors[3] : &mColors[1];
1515 pOffColorStroke = mMouseIsOver ? &mColors[2] : &mColors[0];
1516 break;
1517 }
1518
1519 if (GetValue() > 0.5)
1520 g.DrawSVG(mOnSVG, mRECT, &mBlend, pOnColorStroke, pOnColorFill);
1521 else
1522 g.DrawSVG(mOffSVG, mRECT, &mBlend, pOffColorStroke, pOffColorFill);
1523}
1524
1525ISVGKnobControl::ISVGKnobControl(const IRECT& bounds, const ISVG& svg, int paramIdx)
1526: IKnobControlBase(bounds, paramIdx)
1527, mSVG(svg)
1528{
1529}
1530
1532{
1533 g.DrawRotatedSVG(mSVG, mRECT.MW(), mRECT.MH(), mRECT.W(), mRECT.H(), mStartAngle + GetValue() * (mEndAngle - mStartAngle), &mBlend);
1534}
1535
1536void ISVGKnobControl::SetSVG(ISVG& svg)
1537{
1538 mSVG = svg;
1539 SetDirty(false);
1540}
1541
1542ISVGSwitchControl::ISVGSwitchControl(const IRECT& bounds, const std::initializer_list<ISVG>& svgs, int paramIdx, IActionFunction aF)
1543: ISwitchControlBase(bounds, paramIdx, aF, static_cast<int>(svgs.size()))
1544, mSVGs(svgs)
1545{
1546}
1547
1549{
1550 g.DrawSVG(mSVGs[GetSelectedIdx()], mRECT, &mBlend);
1551}
1552
1553ISVGSliderControl::ISVGSliderControl(const IRECT& bounds, const ISVG& handleSVG, const ISVG& trackSVG, int paramIdx, EDirection dir, double gearing)
1554: ISliderControlBase(bounds, paramIdx, dir, gearing)
1555, mHandleSVG(handleSVG)
1556, mTrackSVG(trackSVG)
1557{
1558}
1559
1561{
1562 g.DrawSVG(mTrackSVG, mTrackSVGBounds, &mBlend);
1563 g.DrawSVG(mHandleSVG, GetHandleBounds(GetValue()), &mBlend);
1564}
1565
1567{
1568 auto trackAspectRatio = mTrackSVG.W() / mTrackSVG.H();
1569 auto handleAspectRatio = mHandleSVG.W() / mHandleSVG.H();
1570 auto handleOverTrackHeight = mHandleSVG.H() / mTrackSVG.H();
1571
1572 IRECT handleBoundsAtMidPoint;
1573
1574 if (mDirection == EDirection::Vertical)
1575 {
1576 mTrackSVGBounds = mRECT.GetCentredInside(mRECT.H() * trackAspectRatio, mRECT.H());
1577
1578 handleBoundsAtMidPoint = mRECT.GetCentredInside(mRECT.H() * handleAspectRatio * handleOverTrackHeight, mRECT.H() * handleOverTrackHeight);
1579 mHandleBoundsAtMax = { handleBoundsAtMidPoint.L, mTrackSVGBounds.T, handleBoundsAtMidPoint.R, mTrackSVGBounds.T + handleBoundsAtMidPoint.H() };
1580 mTrackBounds = mTrackSVGBounds.GetPadded(0, -handleBoundsAtMidPoint.H(), 0, 0);
1581 }
1582 else
1583 {
1584 mTrackSVGBounds = mRECT.GetCentredInside(mRECT.W(), mRECT.W() / trackAspectRatio);
1585 auto handleHeight = mTrackSVGBounds.H() * handleOverTrackHeight;
1586 handleBoundsAtMidPoint = mRECT.GetCentredInside(handleHeight * handleAspectRatio, handleHeight);
1587 auto halfHeight = handleBoundsAtMidPoint.H() / 2.f;
1588 mHandleBoundsAtMax = { mTrackSVGBounds.R - handleBoundsAtMidPoint.W(), mTrackSVGBounds.MH() - halfHeight, mTrackSVGBounds.R, mTrackSVGBounds.MH() + halfHeight };
1589 mTrackBounds = mTrackSVGBounds.GetPadded(-handleBoundsAtMidPoint.W(), 0, 0, 0);
1590 }
1591
1592 SetDirty(false);
1593}
1594
1595IRECT ISVGSliderControl::GetHandleBounds(double value) const
1596{
1597 if (value < 0.0)
1598 value = GetValue();
1599
1600 IRECT r = mHandleBoundsAtMax;
1601
1602 if (mDirection == EDirection::Vertical)
1603 {
1604 float offs = (1.f - (float) value) * mTrackBounds.H();
1605 r.T += offs;
1606 r.B += offs;
1607 }
1608 else
1609 {
1610 float offs = (1.f - (float) value) * mTrackBounds.W();
1611 r.L -= offs;
1612 r.R -= offs;
1613 }
1614
1615 return r;
1616}
1617
1618#pragma mark - BITMAP CONTROLS
1619
1620IBButtonControl::IBButtonControl(float x, float y, const IBitmap& bitmap, IActionFunction aF)
1621 : IButtonControlBase(IRECT(x, y, bitmap), aF)
1622 , IBitmapBase(bitmap)
1623{
1624 AttachIControl(this);
1625}
1626
1627IBButtonControl::IBButtonControl(const IRECT& bounds, const IBitmap& bitmap, IActionFunction aF)
1628 : IButtonControlBase(bounds.GetCentredInside(bitmap), aF)
1629 , IBitmapBase(bitmap)
1630{
1631 AttachIControl(this);
1632}
1633
1634IBSwitchControl::IBSwitchControl(float x, float y, const IBitmap& bitmap, int paramIdx)
1635: ISwitchControlBase(IRECT(x, y, bitmap), paramIdx)
1636, IBitmapBase(bitmap)
1637{
1638 AttachIControl(this);
1639}
1640
1641IBSwitchControl::IBSwitchControl(const IRECT& bounds, const IBitmap& bitmap, int paramIdx)
1642: ISwitchControlBase(bounds.GetCentredInside(bitmap), paramIdx)
1643, IBitmapBase(bitmap)
1644{
1645 AttachIControl(this);
1646}
1647
1648void IBSwitchControl::OnMouseDown(float x, float y, const IMouseMod& mod)
1649{
1650 if (mBitmap.N() > 1)
1651 SetValue(GetValue() + 1.0 / static_cast<double>(mBitmap.N() - 1));
1652 else
1653 SetValue(GetValue() + 1.0);
1654
1655 if (GetValue() > 1.001)
1656 SetValue(0.);
1657
1658 SetDirty();
1659}
1660
1661IBSliderControl::IBSliderControl(float x, float y, float trackLength, const IBitmap& handleBitmap, const IBitmap& trackBitmap, int paramIdx, EDirection dir, double gearing)
1662: ISliderControlBase(IRECT::MakeXYWH(x, y,
1663 dir == EDirection::Vertical ? handleBitmap.W() : trackLength,
1664 dir == EDirection::Vertical ? trackLength : handleBitmap.H()),
1665 paramIdx, dir, gearing,
1666 float(dir == EDirection::Vertical ? handleBitmap.H() : handleBitmap.W()))
1667, IBitmapBase(handleBitmap)
1668, mTrackBitmap(trackBitmap)
1669{
1670 AttachIControl(this);
1671}
1672
1673IBSliderControl::IBSliderControl(const IRECT& bounds, const IBitmap& handleBitmap, const IBitmap& trackBitmap, int paramIdx, EDirection dir, double gearing)
1674: ISliderControlBase(bounds, paramIdx, dir, gearing, float(dir == EDirection::Vertical ? handleBitmap.H() : handleBitmap.W()))
1675, IBitmapBase(handleBitmap)
1676, mTrackBitmap(trackBitmap)
1677{
1678 AttachIControl(this);
1679}
1680
1682{
1683 if(mTrackBitmap.IsValid())
1684 g.DrawBitmap(mTrackBitmap, mRECT.GetCentredInside(IRECT(0, 0, mTrackBitmap)), 0, 0, &mBlend);
1685
1686 g.DrawBitmap(mBitmap, GetHandleBounds(), 1, &mBlend);
1687}
1688
1689IRECT IBSliderControl::GetHandleBounds(double value) const
1690{
1691 if (value < 0.0)
1692 value = GetValue();
1693
1694 IRECT r(mTrackBounds.L, mTrackBounds.T, mBitmap);
1695
1696 if (mDirection == EDirection::Vertical)
1697 r.Translate(0.f, (1.f - static_cast<float>(value)) * (mTrackBounds.H() - static_cast<float>(mBitmap.H())));
1698 else
1699 r.Translate(static_cast<float>(value) * (mTrackBounds.W() - static_cast<float>(mBitmap.W())), 0.f);
1700
1701 return r;
1702}
1703
1705{
1706 if (mDirection == EDirection::Vertical)
1707 {
1708 if(mTrackBitmap.IsValid())
1709 mTrackBounds = mRECT.GetCentredInside(IRECT(0, 0, mTrackBitmap));
1710 else
1711 {
1712 const float halfWidth = static_cast<float>(mBitmap.W()) / 2.f;
1713 mTrackBounds = mRECT.GetMidHPadded(halfWidth);
1714 }
1715 }
1716 else
1717 {
1718 if(mTrackBitmap.IsValid())
1719 mTrackBounds = mRECT.GetCentredInside(IRECT(0, 0, mTrackBitmap));
1720 else
1721 {
1722 const float halfHeight = static_cast<float>(mBitmap.H()) / 2.f;
1723 mTrackBounds = mRECT.GetMidVPadded(halfHeight);
1724 }
1725 }
1726
1727 SetDirty(false);
1728}
1729
1731{
1732 const double angle = -130.0 + GetValue() * 260.0;
1733 g.DrawRotatedBitmap(mBitmap, mRECT.MW(), mRECT.MH(), angle, &mBlend);
1734}
1735
1736IBTextControl::IBTextControl(const IRECT& bounds, const IBitmap& bitmap, const IText& text, const char* str, int charWidth, int charHeight, int charOffset, bool multiLine, bool vCenter, EBlend blend)
1737: ITextControl(bounds, str, text)
1738, IBitmapBase(bitmap)
1739, mCharWidth(charWidth)
1740, mCharHeight(charHeight)
1741, mCharOffset(charOffset)
1742, mMultiLine(multiLine)
1743, mVCentre(vCenter)
1744{
1745 mBlend = blend;
1746}
1747
1749{
1750 g.DrawBitmapedText(mBitmap, mRECT, mText, &mBlend, mStr.Get(), mVCentre, mMultiLine, mCharWidth, mCharHeight, mCharOffset);
1751}
1752
1753void IBMeterControl::OnMsgFromDelegate(int msgTag, int dataSize, const void* pData)
1754{
1755 if (!IsDisabled() && msgTag == ISender<>::kUpdateMessage)
1756 {
1757 IByteStream stream(pData, dataSize);
1758
1759 int pos = 0;
1761 pos = stream.Get(&d, pos);
1762
1763 if (mResponse == EResponse::Log)
1764 {
1765 auto lowPointAbs = std::fabs(mLowRangeDB);
1766 auto rangeDB = std::fabs(mHighRangeDB - mLowRangeDB);
1767 for (auto c = d.chanOffset; c < (d.chanOffset + d.nChans); c++)
1768 {
1769 auto avg = d.vals[c].second;
1770 auto ampValue = AmpToDB(avg);
1771 auto linearPos = (ampValue + lowPointAbs)/rangeDB;
1772 SetValue(Clip(linearPos, 0., 1.), c);
1773 }
1774 }
1775 else
1776 {
1777 for (auto c = d.chanOffset; c < (d.chanOffset + d.nChans); c++)
1778 {
1779 auto avg = d.vals[c].second;
1780 SetValue(Clip(avg, 0.f, 1.f), c);
1781 }
1782 }
1783
1784 SetDirty(false);
1785 }
1786}
A collection of IControls for common UI widgets, such as knobs, sliders, switches.
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1730
void OnMsgFromDelegate(int msgTag, int dataSize, const void *pData) override
Implement to receive messages sent to the control, see IEditorDelegate:SendControlMsgFromDelegate()
Definition: IControls.cpp:1753
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:1704
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1681
IBSwitchControl(float x, float y, const IBitmap &bitmap, int paramIdx=kNoParameter)
Constructs a bitmap switch control.
Definition: IControls.cpp:1634
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:1648
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1748
A base interface to be combined with IControl for bitmap-based controls "IBControls",...
Definition: IControl.h:719
void AttachIControl(IControl *pControl)
Call in the constructor of your IBControl to link the IBitmapBase and IControl.
Definition: IControl.h:732
User-facing bitmap abstraction that you use to manage bitmap data, independant of draw class/platform...
int W() const
int N() const
int H() const
bool IsValid() const
A base class for buttons/momentary switches - cannot be linked to parameters.
Definition: IControl.h:1863
Manages a non-owned block of memory, for receiving arbitrary message byte streams.
Definition: IPlugStructs.h:268
int Get(T *pDst, int startPos) const
Get arbitary typed data from the stream.
Definition: IPlugStructs.h:289
IContainerBase allows a control to nest sub controls and it clips the drawing of those subcontrols In...
Definition: IControl.h:606
The lowest level base class of an IGraphics control.
Definition: IControl.h:49
const char * GetGroup() const
Get the group that the control belongs to, if any.
Definition: IControl.h:284
IGraphics * GetUI()
Definition: IControl.h:467
bool mMouseIsOver
if mGraphics::mHandleMouseOver = true, this will be true when the mouse is over control.
Definition: IControl.h:560
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:267
virtual void SetValueFromDelegate(double value, int valIdx=0)
Set the control's value from the delegate This method is called from the class implementing the IEdit...
Definition: IControl.cpp:159
virtual void OnPopupMenuSelection(IPopupMenu *pSelectedMenu, int valIdx)
Implement this method to handle popup menu selection after IGraphics::CreatePopupMenu/IControlPromptU...
Definition: IControl.cpp:283
bool IsDisabled() const
Definition: IControl.h:362
void SetTargetRECT(const IRECT &bounds)
Set the rectangular mouse tracking target area, within the graphics context for this control.
Definition: IControl.h:323
double GetAnimationProgress() const
Get the progress in a control's animation, in the range 0-1.
Definition: IControl.cpp:431
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:334
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:397
IControl * SetAnimationEndActionFunction(IActionFunction actionFunc)
Set an Action Function to be called at the end of an animation.
Definition: IControl.h:211
virtual void SetValueToDefault(int valIdx=kNoValIdx)
Set one or all of the control's values to the default value of the associated parameter.
Definition: IControl.cpp:183
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:122
virtual void SetValue(double value, int valIdx=0)
Set one of the control's values.
Definition: IControl.cpp:147
double GetValue(int valIdx=0) const
Get the control's value.
Definition: IControl.cpp:153
void SetTargetAndDrawRECTs(const IRECT &bounds)
Set BOTH the draw rect and the target area, within the graphics context for this control.
Definition: IControl.h:327
virtual int GetValIdxForPos(float x, float y) const
Check to see which of the control's values relates to this x and y coordinate.
Definition: IControl.h:245
int NVals() const
Definition: IControl.h:239
IAnimationFunction GetAnimationFunction()
Get the control's animation function, if it exists.
Definition: IControl.h:500
virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)
Mark the control as dirty, i.e.
Definition: IControl.cpp:198
void DisablePrompt(bool disable)
Disable/enable default prompt for user input.
Definition: IControl.h:415
IControl * SetActionFunction(IActionFunction actionFunc)
Set an Action Function for this control.
Definition: IControl.h:206
void SetAnimation(IAnimationFunction func)
Set the animation function.
Definition: IControl.h:492
The lowest level base class of an IGraphics context.
Definition: IGraphics.h:86
virtual void DrawRotatedSVG(const ISVG &svg, float destCentreX, float destCentreY, float width, float height, double angle, const IBlend *pBlend=0)
Draw an SVG image to the graphics context with rotation.
Definition: IGraphics.cpp:2797
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:2497
void DrawBitmapedText(const IBitmap &bitmap, const IRECT &bounds, IText &text, IBlend *pBlend, const char *str, bool vCenter=true, bool multiline=false, int charWidth=6, int charHeight=12, int charOffset=0)
Draws mono spaced bitmap text.
Definition: IGraphics.cpp:714
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:670
virtual void PathClear()=0
Clear the stack of path drawing commands.
void DrawRadialLine(const IColor &color, float cx, float cy, float angle, float rMin, float rMax, const IBlend *pBlend=0, float thickness=1.f)
Draw a radial line to the graphics context, useful for pointers on dials.
Definition: IGraphics.cpp:811
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:2504
virtual void DrawRotatedBitmap(const IBitmap &bitmap, float destCentreX, float destCentreY, double angle, const IBlend *pBlend=0)
Draw a bitmap (raster) image to the graphics context with rotation.
Definition: IGraphics.cpp:2399
virtual void PathStroke(const IPattern &pattern, float thickness, const IStrokeOptions &options=IStrokeOptions(), const IBlend *pBlend=0)=0
Stroke the current current path.
bool CheckLayer(const ILayerPtr &layer)
Test to see if a layer needs drawing, for instance if the control's bounds were changed.
Definition: IGraphics.cpp:2032
void DrawLayer(const ILayerPtr &layer, const IBlend *pBlend=nullptr)
Draw a layer to the main IGraphics context.
Definition: IGraphics.cpp:2045
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:2569
virtual bool PromptForColor(IColor &color, const char *str="", IColorPickerHandlerFunc func=nullptr)=0
Create a platform color chooser dialog.
virtual void DrawArc(const IColor &color, float cx, float cy, float r, float a1, float a2, const IBlend *pBlend=0, float thickness=1.f)
Draw an arc to the graphics context.
Definition: IGraphics.cpp:2525
void PathClipRegion(const IRECT r=IRECT())
Clip the current path to a particular region.
Definition: IGraphics.cpp:2765
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:2576
virtual void DrawData(const IColor &color, const IRECT &bounds, float *normYPoints, int nPoints, float *normXPoints=nullptr, const IBlend *pBlend=0, float thickness=1.f, const IColor *pFillColor=nullptr)
Draw a line between a collection of normalized points.
Definition: IGraphics.cpp:2450
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:2424
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:787
virtual void PathMoveTo(float x, float y)=0
Move the current point in the current path.
virtual void PathArc(float cx, float cy, float r, float a1, float a2, EWinding winding=EWinding::CW)=0
Add an arc to the current path.
virtual void HideMouseCursor(bool hide=true, bool lock=true)=0
Call to hide/show the mouse cursor.
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:794
void ForControlInGroup(const char *group, IControlFunction func)
For all standard controls in the main control stack that are linked to a group, execute a function.
Definition: IGraphics.cpp:519
virtual void PathLineTo(float x, float y)=0
Add a line to the current path from the current point to the specified location.
void StartLayer(IControl *pOwner, const IRECT &r, bool cacheable=false)
Create an IGraphics layer.
Definition: IGraphics.cpp:1977
virtual void DrawSVG(const ISVG &svg, const IRECT &bounds, const IBlend *pBlend=0, const IColor *pStrokeColor=nullptr, const IColor *pFillColor=nullptr)
Draw an SVG image to the graphics context.
Definition: IGraphics.cpp:2784
ILayerPtr EndLayer()
End an IGraphics layer.
Definition: IGraphics.cpp:2000
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.
A base class for knob/dial controls, to handle mouse action and Sender.
Definition: IControl.h:1368
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.cpp:799
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.cpp:810
IPlug's parameter class.
void GetDisplay(WDL_String &display, bool withDisplayText=true) const
Get the current textual display for the current parameter value.
const char * GetName() const
Returns the parameter's name.
void GetDisplayWithLabel(WDL_String &display, bool withDisplayText=true) const
Fills the WDL_String the value of the parameter along with the label, e.g.
A class for setting the contents of a pop up menu.
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1440
ISVGButtonControl(const IRECT &bounds, IActionFunction aF, const ISVG &offImage, const ISVG &onImage)
Constructs an SVG button control, with an action function.
Definition: IControls.cpp:1423
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1531
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1560
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:1566
ISVGSliderControl(const IRECT &bounds, const ISVG &handleSvg, const ISVG &trackSVG, int paramIdx=kNoParameter, EDirection dir=EDirection::Vertical, double gearing=DEFAULT_GEARING)
Constructs an ISVGSliderControl.
Definition: IControls.cpp:1553
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1548
ISVGSwitchControl(const IRECT &bounds, const std::initializer_list< ISVG > &svgs, int paramIdx=kNoParameter, IActionFunction aF=nullptr)
Constructs a SVG switch control.
Definition: IControls.cpp:1542
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1499
ISVGToggleControl(const IRECT &bounds, IActionFunction aF, const ISVG &offImage, const ISVG &onImage)
Constructs an SVG button control, with an action function.
Definition: IControls.cpp:1467
ISender is a utility class which can be used to defer data from the realtime audio processing and sen...
Definition: ISender.h:65
A base class for slider/fader controls, to handle mouse action and Sender.
Definition: IControl.h:1398
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.cpp:895
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.cpp:915
A base class for switch controls.
Definition: IControl.h:1874
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControl.cpp:754
A basic control to display some text.
Definition: IControl.h:2152
A vector button/momentary switch control.
Definition: IControls.h:53
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:63
bool IsHit(float x, float y) const override
Hit test the control.
Definition: IControls.cpp:83
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:71
IVButtonControl(const IRECT &bounds, IActionFunction aF=SplashClickActionFunc, const char *label="", const IVStyle &style=DEFAULT_STYLE, bool labelInButton=true, bool valueInButton=true, EVShape shape=EVShape::Rectangle)
Constructs a vector button control, with an action function.
Definition: IControls.cpp:54
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:77
void OnMouseOut() override
Implement this method to respond to a mouseout event on this control.
Definition: IControls.cpp:1390
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:1343
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1322
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:1396
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:1328
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControls.cpp:1374
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1243
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:1252
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControls.cpp:1235
IVGroupControl(const IRECT &bounds, const char *label="", float labelOffset=10.f, const IVStyle &style=DEFAULT_STYLE, IContainerBase::AttachFunc attachFunc=nullptr, IContainerBase::ResizeFunc resizeFunc=nullptr)
Construct the group control.
Definition: IControls.cpp:1213
void SetBoundsBasedOnGroup(const char *groupName, float padL, float padT, float padR, float padB)
Set the bounds of the group control based on the area occupied by the controls in a particular group.
Definition: IControls.cpp:1289
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:1279
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControls.cpp:742
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:613
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControls.cpp:705
bool IsHit(float x, float y) const override
Hit test the control.
Definition: IControls.cpp:721
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:715
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:652
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: IControls.cpp:690
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
Definition: IControls.cpp:699
virtual IRECT GetKnobDragBounds() override
Get the area for which mouse deltas will be used to calculate the amount dragging changes the control...
Definition: IControls.cpp:621
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:676
void SetDirty(bool push, int valIdx=kNoValIdx) override
Mark the control as dirty, i.e.
Definition: IControls.cpp:732
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:38
void SetValueFromDelegate(double value, int valIdx=0) override
Set the control's value from the delegate This method is called from the class implementing the IEdit...
Definition: IControls.cpp:552
void SetValueFromUserInput(double value, int valIdx) override
Set the control's value after user input.
Definition: IControls.cpp:569
IVMenuButtonControl(const IRECT &bounds, int paramIdx, const char *label="", const IVStyle &style=DEFAULT_STYLE, EVShape shape=EVShape::Rectangle)
Constructs a vector button control, with an action function.
Definition: IControls.cpp:520
void SetStyle(const IVStyle &style) override
Set the Style of this IVControl.
Definition: IControls.cpp:546
void OnPopupMenuSelection(IPopupMenu *pSelectedMenu, int valIdx) override
Implement this method to handle popup menu selection after IGraphics::CreatePopupMenu/IControlPromptU...
Definition: IControls.cpp:560
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1154
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:1198
void AddPlotFunc(const IColor &color, const IPlotFunc &func)
add a new function to the plot
Definition: IControls.cpp:1204
IVPlotControl(const IRECT &bounds, const std::initializer_list< Plot > &funcs, int numPoints, const char *label="", const IVStyle &style=DEFAULT_STYLE, float min=-1., float max=1., bool useLayer=false)
Constructs an IVPlotControl.
Definition: IControls.cpp:1137
std::function< double(double)> IPlotFunc
IVPlotControl passes values between 0 and 1 to this object, that are the plot normalized x values.
Definition: IControls.h:388
int GetButtonForPoint(float x, float y) const override
Definition: IControls.cpp:504
IVRadioButtonControl(const IRECT &bounds, int paramIdx=kNoParameter, const std::initializer_list< const char * > &options={}, const char *label="", const IVStyle &style=DEFAULT_STYLE, EVShape shape=EVShape::Ellipse, EDirection direction=EDirection::Vertical, float buttonSize=10.f)
Constructs a vector radio button control, linked to a parameter.
Definition: IControls.cpp:468
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:486
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControls.cpp:1013
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: IControls.cpp:1040
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:1034
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:931
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:990
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:273
void SetDirty(bool push, int valIdx=kNoValIdx) override
Mark the control as dirty, i.e.
Definition: IControls.cpp:290
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:263
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:250
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:876
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControls.cpp:867
void SetDirty(bool push, int valIdx=kNoValIdx) override
Mark the control as dirty, i.e.
Definition: IControls.cpp:901
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
Definition: IControls.cpp:861
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:840
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: IControls.cpp:852
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:807
bool IsHit(float x, float y) const override
Hit test the control.
Definition: IControls.cpp:888
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControls.cpp:911
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:785
A vector switch control.
Definition: IControls.h:74
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControls.cpp:144
bool IsHit(float x, float y) const override
Hit test the control.
Definition: IControls.cpp:139
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:118
void SetDirty(bool push, int valIdx=kNoValIdx) override
Mark the control as dirty, i.e.
Definition: IControls.cpp:123
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:133
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:110
A vector "tab" multi switch control.
Definition: IControls.h:131
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:449
virtual bool IsHit(float x, float y) const override
Hit test the control.
Definition: IControls.cpp:426
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:431
virtual void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:387
IVTabSwitchControl(const IRECT &bounds, int paramIdx=kNoParameter, const std::vector< const char * > &options={}, const char *label="", const IVStyle &style=DEFAULT_STYLE, EVShape shape=EVShape::Rectangle, EDirection direction=EDirection::Horizontal)
Constructs a vector tab switch control, linked to a parameter.
Definition: IControls.cpp:298
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:350
void OnMouseOver(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouseover event on this control.
Definition: IControls.cpp:440
virtual int GetButtonForPoint(float x, float y) const
Definition: IControls.cpp:415
void OnInit() override
Called just prior to when the control is attached, after its delegate and graphics member variable se...
Definition: IControls.cpp:332
const char * GetSelectedLabelStr() const
returns the label string on the selected tab
Definition: IControls.cpp:463
void DrawValue(IGraphics &g, bool mouseOver) override
Draw the IVControl value text.
Definition: IControls.cpp:180
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:175
A base class for mult-strip/track controls, such as multi-sliders, meters Track refers to the channel...
Definition: IControl.h:1426
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:1516
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControl.h:1551
virtual void DrawBackground(IGraphics &g, const IRECT &r) override
Draw the IVControl background (usually transparent)
Definition: IControl.h:1663
void OnMouseDown(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse down event on this control.
Definition: IControls.cpp:1103
void DrawWidget(IGraphics &g) override
Draw the IVControl main widget (override)
Definition: IControls.cpp:1073
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: IControls.cpp:1121
void OnResize() override
Called when IControl is constructed or resized using SetRect().
Definition: IControls.cpp:1131
void Draw(IGraphics &g) override
Draw the control to the graphics context.
Definition: IControls.cpp:1062
void OnMouseUp(float x, float y, const IMouseMod &mod) override
Implement this method to respond to a mouse up event on this control.
Definition: IControls.cpp:1112
A base interface to be combined with IControl for vectorial controls "IVControls",...
Definition: IControl.h:757
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:918
void SetColor(EVColor colorIdx, const IColor &color)
Set one of the IVColors that style the IVControl.
Definition: IControl.h:787
IRECT MakeRects(const IRECT &parent, bool hasHandle=false)
Calculate the rectangles for the various areas, depending on the style.
Definition: IControl.h:1158
virtual void DrawBackground(IGraphics &g, const IRECT &rect)
Draw the IVControl background (usually transparent)
Definition: IControl.h:876
virtual void SetStyle(const IVStyle &style)
Set the Style of this IVControl.
Definition: IControl.h:825
IRECT DrawPressableTriangle(IGraphics &g, const IRECT &bounds, bool pressed, bool mouseOver, float angle, bool disabled)
Draw a triangle-shaped vector button.
Definition: IControl.h:1103
float GetRoundedCornerRadius(const IRECT &bounds) const
Get the radius of rounded corners for a rectangle, based on the style roundness factor.
Definition: IControl.h:853
virtual void DrawValue(IGraphics &g, bool mouseOver)
Draw the IVControl value text.
Definition: IControl.h:899
void AttachIControl(IControl *pControl, const char *label)
Call in the constructor of your IVControl to link the IVectorBase and IControl.
Definition: IControl.h:775
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:1020
virtual void DrawLabel(IGraphics &g)
Draw the IVControl label text.
Definition: IControl.h:889
const IColor & GetColor(EVColor color) const
Get value of a specific EVColor in the IVControl.
Definition: IControl.h:801
void SplashClickActionFunc(IControl *pCaller)
The splash click action function is used by IVControls to start SplashAnimationFunc.
Definition: IControl.cpp:47
BEGIN_IPLUG_NAMESPACE T Clip(T x, T lo, T hi)
Clips the value x between lo and hi.
static double AmpToDB(double amp)
Used to manage color data, independent of draw class/platform.
Used to manage mouse modifiers i.e.
Used to manage a rectangular area, independent of draw class/platform.
IRECT GetFromRight(float amount) const
Get a subrect of this IRECT bounded in X by 'amount' and the right edge.
IRECT GetCentredInside(const IRECT &sr) const
Get a rectangle the size of sr but with the same center point as this rectangle.
IRECT GetTranslated(float x, float y) const
Get a translated copy of this rectangle.
float MH() const
void Offset(float l, float t, float r, float b)
Offset each field of the rectangle.
IRECT SubRect(EDirection layoutDir, int numSlices, int sliceIdx) const
Get a new rectangle which is a "slice" of this rectangle.
bool Empty() const
IRECT GetGridCell(int row, int col, int nRows, int nColumns) const
Get a subrect (by row, column) of this IRECT which is a cell in a grid of size (nRows * nColumns)
IRECT GetVPadded(float padding) const
Get a copy of this IRECT padded in the Y-axis N.B.
IRECT FracRect(EDirection layoutDir, float frac, bool fromTopOrRight=false) const
Get a new rectangle which is a fraction of this rectangle.
float W() const
static IRECT LinearInterpolateBetween(const IRECT &start, const IRECT &dest, float progress)
Get a rectangle that is a linear interpolation between start and dest
IRECT FracRectHorizontal(float frac, bool rhs=false) const
Returns a new IRECT with a width that is multiplied by frac.
void HPad(float padding)
Pad this IRECT in the X-axis N.B.
void Constrain(float &x, float &y) const
Ensure the point (x,y) is inside this IRECT.
IRECT GetFromLeft(float amount) const
Get a subrect of this IRECT bounded in X by the left edge and 'amount'.
float H() const
void Translate(float x, float y)
Translate this rectangle.
IRECT GetMidHPadded(float padding) const
Get a copy of this IRECT where its width = 2 * padding but the center point on the X-axis has not cha...
float MW() const
bool Contains(const IRECT &rhs) const
Returns true if this IRECT completely contains rhs.
IRECT GetPadded(float padding) const
Get a copy of this IRECT with each value padded by padding N.B.
IRECT GetHPadded(float padding) const
Get a copy of this IRECT padded in the X-axis N.B.
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...
User-facing SVG abstraction that you use to manage SVG data ISVG doesn't actually own the image data.
float H() const
float W() const
ISenderData is used to represent a typed data packet, that may contain values for multiple channels.
Definition: ISender.h:34
IText is used to manage font and text/text entry style for a piece of text on the UI,...
A struct encapsulating a set of properties used to configure IVControls.