iPlug 2: IControls.cpp Source File

1

2

3

4

5

6

7

8

9

10

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)

33{

34 mText = style.valueText;

35 AttachIControl(this, label);

36}

37

39{

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

56, IVectorBase(style, labelInButton, valueInButton)

57{

58 mText = style.valueText;

59 mShape = shape;

61}

62

64{

69}

70

72{

73 bool pressed = (bool)GetValue();

75}

76

78{

81}

82

84{

85 return mWidgetBounds.Contains(x, y);

86}

87

88IVSwitchControl::IVSwitchControl(const IRECT& bounds, int paramIdx, const char* label, const IVStyle& style, bool valueInButton)

91{

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)

101, IVectorBase(style, false, valueInButton)

102{

104 mText = style.valueText;

105

106 if(valueInButton)

107 mText.mVAlign = mStyle.valueText.mVAlign = EVAlign::Middle;

108}

109

111{

116}

117

119{

121}

122

124{

126

128

129 if(pParam)

131}

132

134{

137}

138

140{

141 return mWidgetBounds.Contains(x, y);

142}

143

145{

147

149

150 if(pParam)

151 {

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)

161, mOffText(offText)

162, mOnText(onText)

163{

164

165}

166

167IVToggleControl::IVToggleControl(const IRECT& bounds, IActionFunction aF, const char* label, const IVStyle& style, const char* offText, const char* onText, bool initialState)

169, mOffText(offText)

170, mOnText(onText)

171{

172 SetValue((double) initialState);

173}

174

176{

178}

179

181{

182 if(mouseOver)

184

186 g.DrawText(mStyle.valueText, mOnText.Get(), mValueBounds, &mBlend);

187 else

188 g.DrawText(mStyle.valueText, mOffText.Get(), mValueBounds, &mBlend);

189}

190

191

193: IVSwitchControl(bounds, paramIdx, label, style, valueInButton)

194, mDirection(direction)

195{

199

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

215: IVSwitchControl(bounds, nullptr, label, style, numStates, valueInButton)

216, mDirection(direction)

217{

218 SetValue((double) initialState);

219

223

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{

268

271}

272

274{

275 DrawTrack(g, mWidgetBounds);

276 DrawHandle(g, mHandleBounds);

277}

278

279void IVSlideSwitchControl::DrawTrack(IGraphics& g, const IRECT& filledArea)

280{

283}

284

285void IVSlideSwitchControl::DrawHandle(IGraphics& g, const IRECT& filledArea)

286{

288}

289

291{

293

295 UpdateRects();

296}

297

301, mDirection(direction)

302{

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

316: ISwitchControlBase(bounds, kNoParameter, aF, static_cast<int>(options.size()))

318, mDirection(direction)

319{

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

337

338 if(pParam && mTabLabels.GetSize() == 0)

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{

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:

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

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

427{

429}

430

432{

434 if (index > -1)

435 SetValue(((double) index * (1./(double) (mNumStates-1))));

436

438}

439

441{

443

445

447}

448

450{

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

461}

462

464{

465 return mTabLabels.Get(GetSelectedIdx())->Get();

466}

467

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 {

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

523{

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

538 });

539 });

540

543 });

544}

545

547{

549 mButtonControl->SetStyle(style.WithValueText(style.valueText.WithVAlign(EVAlign::Middle)));

550}

551

553{

555 WDL_String str;

557 mButtonControl->SetValueStr(str.Get());

558}

559

561{

562 if (pSelectedMenu)

563 {

564 mButtonControl->SetValueStr(pSelectedMenu->GetChosenItem()->GetText());

565 }

567}

568

570{

571 if (GetValue(valIdx) != value)

572 {

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)

584, IVectorBase(style, false, valueInWidget)

585, mAngle1(a1)

586, mAngle2(a2)

587, mAnchorAngle(aAnchor)

588{

590 mText = style.valueText;

591 mHideCursorOnDrag = mStyle.hideCursor;

592 mShape = EVShape::Ellipse;

593 mTrackSize = trackSize;

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)

599, IVectorBase(style, false, valueInWidget)

600, mAngle1(a1)

601, mAngle2(a2)

602, mAnchorAngle(aAnchor)

603{

605 mText = style.valueText;

606 mHideCursorOnDrag = mStyle.hideCursor;

607 mShape = EVShape::Ellipse;

608 mTrackSize = trackSize;

611}

612

614{

619}

620

622{

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();

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 DrawHandle(g, knobHandleBounds);

660 DrawPointer(g, angle, cx, cy, knobHandleBounds.W() / 2.f);

661}

662

663void IVKnobControl::DrawHandle(IGraphics& g, const IRECT& bounds)

664{

666}

667

668void IVKnobControl::DrawIndicatorTrack(IGraphics& g, float angle, float cx, float cy, float radius)

669{

670 if (mTrackSize > 0.f)

671 {

672 g.DrawArc(GetColor(kX1), cx, cy, radius, angle >= mAnchorAngle ? mAnchorAngle : mAnchorAngle - (mAnchorAngle - angle), angle >= mAnchorAngle ? angle : mAnchorAngle, &mBlend, mTrackSize);

673 }

674}

675

676void IVKnobControl::DrawPointer(IGraphics& g, float angle, float cx, float cy, float radius)

677{

678 g.DrawRadialLine(GetColor(kFR), cx, cy, angle, mInnerPointerFrac * radius, mOuterPointerFrac * radius, &mBlend, mPointerThickness);

679}

680

682{

683 if(mStyle.showValue && mValueBounds.Contains(x, y))

684 {

686 }

687 else

688 {

690 }

691

693}

694

696{

697 #ifdef AAX_API

699 #else

701 #endif

702}

703

705{

708}

709

711{

712 if(mStyle.showValue && !mDisablePrompt)

713 mValueMouseOver = mValueBounds.Contains(x,y);

714

716

718}

719

721{

724}

725

727{

728 if(!mDisablePrompt)

729 {

730 if(mValueBounds.Contains(x,y))

731 return true;

732 }

733

734 return mWidgetBounds.Contains(x, y);

735}

736

738{

740

742

743 if(pParam)

745}

746

748{

750

751 if(pParam)

752 {

754

755 if(!mLabelStr.GetLength())

756 mLabelStr.Set(pParam->GetName());

757 }

758}

759

760IVSliderControl::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)

763, mHandleInsideTrack(handleInsideTrack)

764, mHandleXOffset(handleXOffset)

765, mHandleYOffset(handleYOffset)

766{

768 mText = style.valueText;

769 mHideCursorOnDrag = style.hideCursor;

770 mShape = EVShape::Ellipse;

771 mTrackSize = trackSize;

773}

774

775IVSliderControl::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)

778, mHandleInsideTrack(handleInsideTrack)

779, mHandleXOffset(handleXOffset)

780, mHandleYOffset(handleYOffset)

781{

783 mText = style.valueText;

784 mHideCursorOnDrag = style.hideCursor;

785 mShape = EVShape::Ellipse;

786 mTrackSize = trackSize;

788}

789

791{

796}

797

798void IVSliderControl::DrawTrack(IGraphics& g, const IRECT& filledArea)

799{

800 const float extra = mHandleInsideTrack ? mHandleSize : 0.f;

801 const IRECT adjustedTrackBounds = mDirection == EDirection::Vertical ? mTrackBounds.GetVPadded(extra) : mTrackBounds.GetHPadded(extra);

802 const IRECT adjustedFillBounds = mDirection == EDirection::Vertical ? filledArea.GetVPadded(extra) : filledArea.GetHPadded(extra);

804

807

808 if(mStyle.drawFrame)

809 g.DrawRoundRect(GetColor(kFR), adjustedTrackBounds, cr, &mBlend, mStyle.frameThickness);

810}

811

813{

815

816 if(mTrackSize > 0.f)

817 DrawTrack(g, filledTrack);

818

819 float cx, cy;

820

821 const float offset = (mStyle.drawShadows && mShape != EVShape::Ellipse ) ? mStyle.shadowOffset * 0.5f : 0.f;

822

823 if(mDirection == EDirection::Vertical)

824 {

825 cx = filledTrack.MW() + offset;

826 cy = filledTrack.T;

827 }

828 else

829 {

830 cx = filledTrack.R;

831 cy = filledTrack.MH() + offset;

832 }

833

834 if(mHandleSize > 0.f)

835 {

836 DrawHandle(g, {cx+mHandleXOffset-mHandleSize, cy+mHandleYOffset-mHandleSize, cx+mHandleXOffset+mHandleSize, cy+mHandleYOffset+mHandleSize});

837 }

838}

839

840void IVSliderControl::DrawHandle(IGraphics& g, const IRECT& bounds)

841{

843}

844

846{

847 if(mStyle.showValue && mValueBounds.Contains(x, y))

848 {

850 }

851 else

852 {

854 }

855}

856

858{

859 #ifdef AAX_API

861 #else

863 #endif

864}

865

867{

870}

871

873{

874 if(mStyle.showValue && !mDisablePrompt)

875 mValueMouseOver = mValueBounds.Contains(x,y);

876

879}

880

882{

884

885 if(mDirection == EDirection::Vertical)

887 else

889

891}

892

894{

895 if(!mDisablePrompt)

896 {

897 if(mValueBounds.Contains(x,y))

898 {

899 return true;

900 }

901 }

902

903 return mWidgetBounds.Contains(x, y);

904}

905

907{

909

911

912 if(pParam)

914}

915

917{

919

920 if(pParam)

921 {

922 if(!mLabelStr.GetLength())

923 mLabelStr.Set(pParam->GetName());

924

926 }

927}

928

929IVRangeSliderControl::IVRangeSliderControl(const IRECT& bounds, const std::initializer_list<int>& params, const char* label, const IVStyle& style, EDirection dir, bool onlyHandle, float handleSize, float trackSize)

931, mHandleSize(handleSize)

932{

933 mTrackSize = trackSize;

934}

935

937{

941

942}

943

944void IVRangeSliderControl::MakeTrackRects(const IRECT& bounds)

945{

946 for (int ch = 0; ch < NVals(); ch++)

947 {

948 if(mDirection == EDirection::Vertical)

950 else

952 }

953}

954

955void IVRangeSliderControl::DrawTrack(IGraphics& g, const IRECT& r, int chIdx)

956{

957 bool thisTrack = mMouseOverHandle == chIdx;

958 float angle = 0.f;

959

960 if(mDirection == EDirection::Horizontal)

961 angle = chIdx % 2 ? 180.f : 0.f;

962 else

963 angle = chIdx % 2 ? 270.f : 90.f;

964

966}

967

968IRECT IVRangeSliderControl::GetHandleBounds(int trackIdx)

969{

970 IRECT filledTrack = mTrackBounds.Get()[trackIdx].FracRect(mDirection, (float) GetValue(trackIdx));

971 float cx, cy;

972 const float offset = (mStyle.drawShadows && mShape != EVShape::Ellipse ) ? mStyle.shadowOffset * 0.5f : 0.f;

973 if(mDirection == EDirection::Vertical)

974 {

975 cx = filledTrack.MW() + offset;

976 cy = filledTrack.T;

977

978 if(trackIdx % 2)

979 return IRECT(cx+mTrackSize, cy-mHandleSize, cx+(2.f*mHandleSize)+mTrackSize, cy+mHandleSize);

980 else

981 return IRECT(cx-(2.f*mHandleSize), cy-mHandleSize, cx, cy+mHandleSize);

982 }

983 else

984 {

985 cx = filledTrack.R;

986 cy = filledTrack.MH() + offset;

987

988 if(trackIdx % 2)

989 return IRECT(cx-mHandleSize, cy-(2.f*mHandleSize), cx+mHandleSize, cy);

990 else

991 return IRECT(cx-mHandleSize, cy+mTrackSize, cx+mHandleSize, cy+(2.f*mHandleSize)+mTrackSize);

992 }

993}

994

996{

997 IRECT r = mTrackBounds.Get()[0];

998

999 DrawTrackBackground(g, r, 0);

1000

1001 for(int i=0;i<NVals()-1;i++)

1002 {

1003 IRECT filled1 = mTrackBounds.Get()[i].FracRect(mDirection, (float) GetValue(i));

1004 IRECT filled2 = mTrackBounds.Get()[i+1].FracRect(mDirection, (float) GetValue(i+1));

1005

1006 if(mDirection == EDirection::Vertical)

1007 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);

1008 else

1009 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);

1010 }

1011

1012 if(mStyle.drawFrame && mDrawTrackFrame)

1013 g.DrawRect(GetColor(kFR), r, &mBlend, mStyle.frameThickness);

1014

1016}

1017

1019{

1021 int hitHandle = -1;

1022

1023 for(int i=0;i<NVals();i++)

1024 {

1025 bounds = GetHandleBounds(i);

1027 {

1028 hitHandle = i;

1029 break;

1030 }

1031 }

1032

1033 mMouseOverHandle = hitHandle;

1034

1037}

1038

1040{

1041 mMouseIsDown = true;

1043}

1044

1046{

1047 if(mMouseOverHandle == -1)

1048 return;

1049

1050 auto minClip = mMouseOverHandle == 0 ? 0. : GetValue(mMouseOverHandle-1);

1051 auto maxClip = mMouseOverHandle == NVals()-1 ? 1. : GetValue(mMouseOverHandle+1);

1052 SnapToMouse(x, y, mDirection, mWidgetBounds, mMouseOverHandle, minClip, maxClip);

1053}

1054

1055

1056IVXYPadControl::IVXYPadControl(const IRECT& bounds, const std::initializer_list<int>& params, const char* label, const IVStyle& style, float handleRadius, bool trackClipsHandle, bool drawCross)

1059, mHandleRadius(handleRadius)

1060, mTrackClipsHandle(trackClipsHandle)

1061, mDrawCross(drawCross)

1062{

1063 mShape = EVShape::Ellipse;

1065}

1066

1068{

1071

1072 if(mStyle.drawFrame)

1073 g.DrawRect(GetColor(kFR), mWidgetBounds, &mBlend, mStyle.frameThickness);

1074

1076}

1077

1079{

1080 DrawTrack(g);

1081

1082 const IRECT trackBounds = mWidgetBounds.GetPadded(mTrackClipsHandle ? 0 : -mHandleRadius);

1083

1084 const float xpos = static_cast<float>(GetValue(0)) * trackBounds.W();

1085 const float ypos = static_cast<float>(GetValue(1)) * trackBounds.H();

1086 const IRECT handleBounds = IRECT(trackBounds.L + xpos-mHandleRadius, trackBounds.B - ypos-mHandleRadius, trackBounds.L + xpos+mHandleRadius, trackBounds.B -ypos+mHandleRadius);

1087

1088 DrawHandle(g, trackBounds, handleBounds);

1089}

1090

1091void IVXYPadControl::DrawHandle(IGraphics& g, const IRECT& trackBounds, const IRECT& handleBounds)

1092{

1093 if (mTrackClipsHandle)

1095

1097}

1098

1099void IVXYPadControl::DrawTrack(IGraphics& g)

1100{

1101 if (mDrawCross)

1102 {

1105 }

1106}

1107

1109{

1110 mMouseDown = true;

1111 if (mStyle.hideCursor)

1113

1115}

1116

1118{

1119 if (mStyle.hideCursor)

1121

1122 mMouseDown = false;

1124}

1125

1127{

1129 float xn = (x - mRECT.L) / mRECT.W();

1130 float yn = 1.f - ((y - mRECT.T) / mRECT.H());

1134}

1135

1137{

1140}

1141

1142IVPlotControl::IVPlotControl(const IRECT& bounds, const std::initializer_list<Plot>& plots, int numPoints, const char* label, const IVStyle& style, float min, float max, bool useLayer)

1145, mMin(min)

1146, mMax(max)

1147, mUseLayer(useLayer)

1148{

1149 mPoints.resize(numPoints);

1150

1152

1153 for(auto plot : plots)

1154 {

1156 }

1157}

1158

1160{

1163

1164 float hdiv = mWidgetBounds.W() / static_cast<float>(mHorizontalDivisions);

1165 float vdiv = mWidgetBounds.H() / static_cast<float>(mVerticalDivisions + 2);

1166

1168

1169 auto drawFunc = [&](){

1170 g.DrawGrid(GetColor(kSH), mWidgetBounds, hdiv, vdiv, &mBlend);

1171

1172 for (int p=0; p<mPlots.size(); p++)

1173 {

1174 for (int i=0; i<mPoints.size(); i++)

1175 {

1176 auto v = mPlots[p].func((static_cast<float>(i)/static_cast<float>(mPoints.size() - 1)));

1177 v = (v - mMin) / (mMax-mMin);

1178 mPoints[i] = static_cast<float>(v);

1179 }

1180

1181 g.DrawData(mPlots[p].color, plotsRECT, mPoints.data(), static_cast<int>(mPoints.size()), nullptr, &mBlend, mTrackSize);

1182 }

1183

1184 if (mStyle.drawFrame)

1185 g.DrawRect(GetColor(kFR), mWidgetBounds, &mBlend, mStyle.frameThickness);

1186 };

1187

1188 if(mUseLayer)

1189 {

1191 {

1193 drawFunc();

1195 }

1196

1198 }

1199 else

1200 drawFunc();

1201}

1202

1204{

1207}

1208

1210{

1211 mPlots.push_back({color, func});

1212

1213 if(mLayer)

1214 mLayer->Invalidate();

1216}

1217

1218IVGroupControl::IVGroupControl(const IRECT& bounds, const char* label, float labelOffset, const IVStyle& style, IContainerBase::AttachFunc attachFunc, IContainerBase::ResizeFunc resizeFunc)

1221, mLabelOffset(labelOffset)

1222{

1224 mIgnoreMouse = true;

1225}

1226

1230, mGroupName(groupName)

1231, mPadL(padL)

1232, mPadT(padT)

1233, mPadR(padR)

1234, mPadB(padB)

1235{

1237 mIgnoreMouse = true;

1238}

1239

1241{

1242 if(mGroupName.GetLength())

1243 {

1245 }

1246}

1247

1249{

1250

1251

1252

1255}

1256

1258{

1260 const float ft = mStyle.frameThickness;

1261 const float hft = ft/2.f;

1262

1263 int nPaths = 1;

1264

1265 auto b = mWidgetBounds.GetPadded( 0.f);

1266

1267 auto labelR = mLabelBounds.Empty() ? mRECT.MW() : mLabelBounds.R;

1268 auto labelL = mLabelBounds.Empty() ? mRECT.MW() : mLabelBounds.L;

1269

1270 for(int i=0; i < nPaths; i++)

1271 {

1272 const float offset = i == 0 ? 0.f : mStyle.shadowOffset;

1274 g.PathMoveTo(labelR, b.T + hft - offset);

1275 g.PathArc(b.R - cr - hft - offset, b.T + cr + hft - offset, cr, 0.f, 90.f);

1276 g.PathArc(b.R - cr - hft - offset, b.B - cr - hft - offset, cr, 90.f, 180.f);

1277 g.PathArc(b.L + cr + hft - offset, b.B - cr - hft - offset, cr, 180.f, 270.f);

1278 g.PathArc(b.L + cr + hft - offset, b.T + cr + hft - offset, cr, 270.f, 360.f);

1279 g.PathLineTo(labelL, b.T + hft - offset);

1281 }

1282}

1283

1285{

1287 mLabelBounds.HPad(mLabelPadding);

1288 mWidgetBounds.Offset(0, -(mLabelBounds.H()/2.f) - (mStyle.frameThickness/2.f), 0, 0);

1290 mLabelBounds.Translate(mRECT.L - mLabelBounds.L + mStyle.frameThickness + mLabelOffset + cr, 0.f);

1292}

1293

1295{

1296 mGroupName.Set(groupName);

1297

1298 IRECT unionRect;

1299 GetUI()->ForControlInGroup(mGroupName.Get(), [&unionRect](IControl* pControl) { unionRect = unionRect.Union(pControl->GetRECT()); });

1300 float halfLabelHeight = mLabelBounds.H()/2.f;

1301 unionRect.GetVPadded(halfLabelHeight);

1302 mRECT = unionRect.GetPadded(padL, padT, padR, padB);

1303

1305}

1306

1307IVColorSwatchControl::IVColorSwatchControl(const IRECT& bounds, const char* label, ColorChosenFunc func, const IVStyle& style, ECellLayout layout,

1308 const std::initializer_list<EVColor>& colorIDs, const std::initializer_list<const char*>& labelsForIDs)

1311, mColorChosenFunc(func)

1312, mLayout(layout)

1313, mColorIdForCells(colorIDs)

1314{

1315 assert(colorIDs.size() == labelsForIDs.size());

1316

1318 mCellRects.Resize(static_cast<int>(mColorIdForCells.size()));

1319 mText.mAlign = mStyle.valueText.mAlign = EAlign::Far;

1320

1321 for (int i=0;i<colorIDs.size();i++)

1322 {

1323 mLabels.Add(new WDL_String(labelsForIDs.begin()[i]));

1324 }

1325}

1326

1328{

1331}

1332

1334{

1335 for (int i=0; i< mColorIdForCells.size(); i++)

1336 {

1337 WDL_String* pStr = mLabels.Get(i);

1338 IRECT r = mCellRects.Get()[i];

1340 g.FillRect(GetColor(mColorIdForCells[i]), buttonBounds, &mBlend);

1341 g.DrawRect(i == mCellOver ? COLOR_GRAY : COLOR_DARK_GRAY, buttonBounds.GetPadded(0.5f), &mBlend);

1342

1343 if(pStr->GetLength())

1345 }

1346}

1347

1349{

1351

1352 int rows = 3;

1353 int columns = 3;

1354

1355 if(mLayout == ECellLayout::kGrid)

1356 {

1357 rows = 3;

1358 columns = 3;

1359 }

1360 else if (mLayout == ECellLayout::kHorizontal)

1361 {

1362 rows = 1;

1363 columns = static_cast<int>(mColorIdForCells.size());

1364 }

1365 else if (mLayout == ECellLayout::kVertical)

1366 {

1367 rows = static_cast<int>(mColorIdForCells.size());

1368 columns = 1;

1369 }

1370

1371 for (int i=0; i< mColorIdForCells.size(); i++)

1372 {

1373 mCellRects.Get()[i] = mWidgetBounds.GetGridCell(i, rows, columns).GetPadded(-2);

1374 }

1375

1377}

1378

1380{

1381 for (int i=0; i<mColorIdForCells.size(); i++)

1382 {

1383 if(mCellRects.Get()[i].Contains(x, y))

1384 {

1385 mCellOver = i;

1387 return;

1388 }

1389 }

1390

1391 mCellOver = -1;

1393}

1394

1396{

1397 mCellOver = -1;

1399}

1400

1402{

1403 int cellClicked=-1;

1404

1405 for (int i=0; i<mColorIdForCells.size(); i++)

1406 {

1407 if(mCellRects.Get()[i].Contains(x, y))

1408 {

1409 cellClicked = i;

1410 break;

1411 }

1412 }

1413

1414 if(cellClicked > -1)

1415 {

1416 EVColor vColorClicked = mColorIdForCells[cellClicked];

1418 GetUI()->PromptForColor(color, "Choose a color", [this, cellClicked, vColorClicked](IColor result) {

1419 SetColor(vColorClicked, result);

1420 if(mColorChosenFunc)

1421 mColorChosenFunc(cellClicked, result);

1422 });

1423 }

1424}

1425

1426#pragma mark - SVG CONTROLS

1427

1430, mOffSVG(offImage)

1431, mOnSVG(onImage)

1432{

1433}

1434

1435

1438, mOffSVG(image)

1439, mOnSVG(image)

1440, mColors(colors)

1441, mColorReplacement(colorReplacement)

1442{

1443}

1444

1446{

1447 IColor* pOnColorFill = nullptr;

1448 IColor* pOffColorFill = nullptr;

1449 IColor* pOnColorStroke = nullptr;

1450 IColor* pOffColorStroke = nullptr;

1451

1452 switch (mColorReplacement) {

1453

1454 case EColorReplacement::None:

1455 break;

1456 case EColorReplacement::Fill:

1457 pOnColorFill = mMouseIsOver ? &mColors[3] : &mColors[1];

1458 pOffColorFill = mMouseIsOver ? &mColors[2] : &mColors[0];

1459 break;

1460 case EColorReplacement::Stroke:

1461 pOnColorStroke = mMouseIsOver ? &mColors[3] : &mColors[1];

1462 pOffColorStroke = mMouseIsOver ? &mColors[2] : &mColors[0];

1463 break;

1464 }

1465

1467 g.DrawSVG(mOnSVG, mRECT, &mBlend, pOnColorStroke, pOnColorFill);

1468 else

1469 g.DrawSVG(mOffSVG, mRECT, &mBlend, pOffColorStroke, pOffColorFill);

1470}

1471

1474, mOffSVG(offImage)

1475, mOnSVG(onImage)

1476{

1477}

1478

1481, mOffSVG(offImage)

1482, mOnSVG(onImage)

1483{

1484}

1485

1488, mOffSVG(image)

1489, mOnSVG(image)

1490, mColors(colors)

1491, mColorReplacement(colorReplacement)

1492{

1493}

1494

1497, mOffSVG(image)

1498, mOnSVG(image)

1499, mColors(colors)

1500, mColorReplacement(colorReplacement)

1501{

1502}

1503

1505{

1506 IColor* pOnColorFill = nullptr;

1507 IColor* pOffColorFill = nullptr;

1508 IColor* pOnColorStroke = nullptr;

1509 IColor* pOffColorStroke = nullptr;

1510

1511 switch (mColorReplacement) {

1512 case EColorReplacement::None:

1513 break;

1514 case EColorReplacement::Fill:

1515 pOnColorFill = mMouseIsOver ? &mColors[3] : &mColors[1];

1516 pOffColorFill = mMouseIsOver ? &mColors[2] : &mColors[0];

1517 break;

1518 case EColorReplacement::Stroke:

1519 pOnColorStroke = mMouseIsOver ? &mColors[3] : &mColors[1];

1520 pOffColorStroke = mMouseIsOver ? &mColors[2] : &mColors[0];

1521 break;

1522 }

1523

1525 g.DrawSVG(mOnSVG, mRECT, &mBlend, pOnColorStroke, pOnColorFill);

1526 else

1527 g.DrawSVG(mOffSVG, mRECT, &mBlend, pOffColorStroke, pOffColorFill);

1528}

1529

1530ISVGKnobControl::ISVGKnobControl(const IRECT& bounds, const ISVG& svg, int paramIdx)

1532, mSVG(svg)

1533{

1534}

1535

1537{

1538 g.DrawRotatedSVG(mSVG, mRECT.MW(), mRECT.MH(), mRECT.W(), mRECT.H(), mStartAngle + GetValue() * (mEndAngle - mStartAngle), &mBlend);

1539}

1540

1541void ISVGKnobControl::SetSVG(ISVG& svg)

1542{

1543 mSVG = svg;

1545}

1546

1548: ISwitchControlBase(bounds, paramIdx, aF, static_cast<int>(svgs.size()))

1549, mSVGs(svgs)

1550{

1551}

1552

1554{

1555 g.DrawSVG(mSVGs[GetSelectedIdx()], mRECT, &mBlend);

1556}

1557

1560, mHandleSVG(handleSVG)

1561, mTrackSVG(trackSVG)

1562{

1563}

1564

1566{

1567 g.DrawSVG(mTrackSVG, mTrackSVGBounds, &mBlend);

1568 g.DrawSVG(mHandleSVG, GetHandleBounds(GetValue()), &mBlend);

1569}

1570

1572{

1573 auto trackAspectRatio = mTrackSVG.W() / mTrackSVG.H();

1574 auto handleAspectRatio = mHandleSVG.W() / mHandleSVG.H();

1575 auto handleOverTrackHeight = mHandleSVG.H() / mTrackSVG.H();

1576

1577 IRECT handleBoundsAtMidPoint;

1578

1579 if (mDirection == EDirection::Vertical)

1580 {

1581 mTrackSVGBounds = mRECT.GetCentredInside(mRECT.H() * trackAspectRatio, mRECT.H());

1582

1583 handleBoundsAtMidPoint = mRECT.GetCentredInside(mRECT.H() * handleAspectRatio * handleOverTrackHeight, mRECT.H() * handleOverTrackHeight);

1584 mHandleBoundsAtMax = { handleBoundsAtMidPoint.L, mTrackSVGBounds.T, handleBoundsAtMidPoint.R, mTrackSVGBounds.T + handleBoundsAtMidPoint.H() };

1585 mTrackBounds = mTrackSVGBounds.GetPadded(0, -handleBoundsAtMidPoint.H(), 0, 0);

1586 }

1587 else

1588 {

1589 mTrackSVGBounds = mRECT.GetCentredInside(mRECT.W(), mRECT.W() / trackAspectRatio);

1590 auto handleHeight = mTrackSVGBounds.H() * handleOverTrackHeight;

1591 handleBoundsAtMidPoint = mRECT.GetCentredInside(handleHeight * handleAspectRatio, handleHeight);

1592 auto halfHeight = handleBoundsAtMidPoint.H() / 2.f;

1593 mHandleBoundsAtMax = { mTrackSVGBounds.R - handleBoundsAtMidPoint.W(), mTrackSVGBounds.MH() - halfHeight, mTrackSVGBounds.R, mTrackSVGBounds.MH() + halfHeight };

1594 mTrackBounds = mTrackSVGBounds.GetPadded(-handleBoundsAtMidPoint.W(), 0, 0, 0);

1595 }

1596

1598}

1599

1600IRECT ISVGSliderControl::GetHandleBounds(double value) const

1601{

1602 if (value < 0.0)

1604

1605 IRECT r = mHandleBoundsAtMax;

1606

1607 if (mDirection == EDirection::Vertical)

1608 {

1609 float offs = (1.f - (float) value) * mTrackBounds.H();

1610 r.T += offs;

1611 r.B += offs;

1612 }

1613 else

1614 {

1615 float offs = (1.f - (float) value) * mTrackBounds.W();

1616 r.L -= offs;

1617 r.R -= offs;

1618 }

1619

1620 return r;

1621}

1622

1623#pragma mark - BITMAP CONTROLS

1624

1625IBButtonControl::IBButtonControl(float x, float y, const IBitmap& bitmap, IActionFunction aF)

1628{

1629 AttachIControl(this);

1630}

1631

1632IBButtonControl::IBButtonControl(const IRECT& bounds, const IBitmap& bitmap, IActionFunction aF)

1635{

1636 AttachIControl(this);

1637}

1638

1642{

1644}

1645

1649{

1651}

1652

1654{

1655 if (mBitmap.N() > 1)

1656 SetValue(GetValue() + 1.0 / static_cast<double>(mBitmap.N() - 1));

1657 else

1659

1662

1664}

1665

1666IBSliderControl::IBSliderControl(float x, float y, float trackLength, const IBitmap& handleBitmap, const IBitmap& trackBitmap, int paramIdx, EDirection dir, double gearing)

1668 dir == EDirection::Vertical ? handleBitmap.W() : trackLength,

1669 dir == EDirection::Vertical ? trackLength : handleBitmap.H()),

1670 paramIdx, dir, gearing,

1671 float(dir == EDirection::Vertical ? handleBitmap.H() : handleBitmap.W()))

1673, mTrackBitmap(trackBitmap)

1674{

1676}

1677

1678IBSliderControl::IBSliderControl(const IRECT& bounds, const IBitmap& handleBitmap, const IBitmap& trackBitmap, int paramIdx, EDirection dir, double gearing)

1679: ISliderControlBase(bounds, paramIdx, dir, gearing, float(dir == EDirection::Vertical ? handleBitmap.H() : handleBitmap.W()))

1681, mTrackBitmap(trackBitmap)

1682{

1684}

1685

1687{

1688 if(mTrackBitmap.IsValid())

1690

1691 g.DrawBitmap(mBitmap, GetHandleBounds(), 1, &mBlend);

1692}

1693

1694IRECT IBSliderControl::GetHandleBounds(double value) const

1695{

1696 if (value < 0.0)

1698

1699 IRECT r(mTrackBounds.L, mTrackBounds.T, mBitmap);

1700

1701 if (mDirection == EDirection::Vertical)

1702 r.Translate(0.f, (1.f - static_cast<float>(value)) * (mTrackBounds.H() - static_cast<float>(mBitmap.H())));

1703 else

1704 r.Translate(static_cast<float>(value) * (mTrackBounds.W() - static_cast<float>(mBitmap.W())), 0.f);

1705

1706 return r;

1707}

1708

1710{

1711 if (mDirection == EDirection::Vertical)

1712 {

1713 if(mTrackBitmap.IsValid())

1715 else

1716 {

1717 const float halfWidth = static_cast<float>(mBitmap.W()) / 2.f;

1719 }

1720 }

1721 else

1722 {

1723 if(mTrackBitmap.IsValid())

1725 else

1726 {

1727 const float halfHeight = static_cast<float>(mBitmap.H()) / 2.f;

1729 }

1730 }

1731

1733}

1734

1736{

1737 const double angle = -130.0 + GetValue() * 260.0;

1739}

1740

1741IBTextControl::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)

1744, mCharWidth(charWidth)

1745, mCharHeight(charHeight)

1746, mCharOffset(charOffset)

1747, mMultiLine(multiLine)

1748, mVCentre(vCenter)

1749{

1750 mBlend = blend;

1751}

1752

1754{

1755 g.DrawBitmapedText(mBitmap, mRECT, mText, &mBlend, mStr.Get(), mVCentre, mMultiLine, mCharWidth, mCharHeight, mCharOffset);

1756}

1757

1759{

1761 {

1763

1764 int pos = 0;

1766 pos = stream.Get(&d, pos);

1767

1768 if (mResponse == EResponse::Log)

1769 {

1770 auto lowPointAbs = std::fabs(mLowRangeDB);

1771 auto rangeDB = std::fabs(mHighRangeDB - mLowRangeDB);

1772 for (auto c = d.chanOffset; c < (d.chanOffset + d.nChans); c++)

1773 {

1774 auto avg = d.vals[c].second;

1775 auto ampValue = AmpToDB(avg);

1776 auto linearPos = (ampValue + lowPointAbs)/rangeDB;

1778 }

1779 }

1780 else

1781 {

1782 for (auto c = d.chanOffset; c < (d.chanOffset + d.nChans); c++)

1783 {

1784 auto avg = d.vals[c].second;

1786 }

1787 }

1788

1790 }

1791}

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.

void OnMsgFromDelegate(int msgTag, int dataSize, const void *pData) override

Implement to receive messages sent to the control, see IEditorDelegate:SendControlMsgFromDelegate()

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void Draw(IGraphics &g) override

Draw the control to the graphics context.

IBSwitchControl(float x, float y, const IBitmap &bitmap, int paramIdx=kNoParameter)

Constructs a bitmap switch control.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

A base interface to be combined with IControl for bitmap-based controls "IBControls",...

void AttachIControl(IControl *pControl)

Call in the constructor of your IBControl to link the IBitmapBase and IControl.

User-facing bitmap abstraction that you use to manage bitmap data, independant of draw class/platform...

A base class for buttons/momentary switches - cannot be linked to parameters.

Manages a non-owned block of memory, for receiving arbitrary message byte streams.

int Get(T *pDst, int startPos) const

Get arbitary typed data from the stream.

IContainerBase allows a control to nest sub controls and it clips the drawing of those subcontrols In...

The lowest level base class of an IGraphics control.

const char * GetGroup() const

Get the group that the control belongs to, if any.

bool mMouseIsOver

if mGraphics::mHandleMouseOver = true, this will be true when the mouse is over control.

virtual void OnMouseOver(float x, float y, const IMouseMod &mod)

Implement this method to respond to a mouseover event on this control.

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...

virtual void OnPopupMenuSelection(IPopupMenu *pSelectedMenu, int valIdx)

Implement this method to handle popup menu selection after IGraphics::CreatePopupMenu/IControlPromptU...

void SetTargetRECT(const IRECT &bounds)

Set the rectangular mouse tracking target area, within the graphics context for this control.

double GetAnimationProgress() const

Get the progress in a control's animation, in the range 0-1.

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,...

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.

IControl * SetAnimationEndActionFunction(IActionFunction actionFunc)

Set an Action Function to be called at the end of an animation.

virtual void SetValueToDefault(int valIdx=kNoValIdx)

Set one or all of the control's values to the default value of the associated parameter.

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...

virtual void SetValue(double value, int valIdx=0)

Set one of the control's values.

double GetValue(int valIdx=0) const

Get the control's value.

void SetTargetAndDrawRECTs(const IRECT &bounds)

Set BOTH the draw rect and the target area, within the graphics context for this control.

virtual int GetValIdxForPos(float x, float y) const

Check to see which of the control's values relates to this x and y coordinate.

IAnimationFunction GetAnimationFunction()

Get the control's animation function, if it exists.

virtual void SetDirty(bool triggerAction=true, int valIdx=kNoValIdx)

Mark the control as dirty, i.e.

void DisablePrompt(bool disable)

Disable/enable default prompt for user input.

IControl * SetActionFunction(IActionFunction actionFunc)

Set an Action Function for this control.

void SetAnimation(IAnimationFunction func)

Set the animation function.

The lowest level base class of an IGraphics context.

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.

virtual void DrawRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0, float thickness=1.f)

Draw a rectangle to the graphics context.

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.

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.

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.

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.

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.

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.

void DrawLayer(const ILayerPtr &layer, const IBlend *pBlend=nullptr)

Draw a layer to the main IGraphics context.

virtual void FillRect(const IColor &color, const IRECT &bounds, const IBlend *pBlend=0)

Fill a rectangular region of the graphics context with a color.

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.

void PathClipRegion(const IRECT r=IRECT())

Clip the current path to a particular region.

virtual void FillRoundRect(const IColor &color, const IRECT &bounds, float cornerRadius=5.f, const IBlend *pBlend=0)

Fill a rounded rectangle with a color.

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.

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.

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.

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.

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.

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.

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.

ILayerPtr EndLayer()

End an IGraphics layer.

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.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void OnMouseUp(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse up event on this control.

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.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

ISVGButtonControl(const IRECT &bounds, IActionFunction aF, const ISVG &offImage, const ISVG &onImage)

Constructs an SVG button control, with an action function.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

ISVGSliderControl(const IRECT &bounds, const ISVG &handleSvg, const ISVG &trackSVG, int paramIdx=kNoParameter, EDirection dir=EDirection::Vertical, double gearing=DEFAULT_GEARING)

Constructs an ISVGSliderControl.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

ISVGSwitchControl(const IRECT &bounds, const std::initializer_list< ISVG > &svgs, int paramIdx=kNoParameter, IActionFunction aF=nullptr)

Constructs a SVG switch control.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

ISVGToggleControl(const IRECT &bounds, IActionFunction aF, const ISVG &offImage, const ISVG &onImage)

Constructs an SVG button control, with an action function.

ISender is a utility class which can be used to defer data from the realtime audio processing and sen...

A base class for slider/fader controls, to handle mouse action and Sender.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void OnMouseUp(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse up event on this control.

A base class for switch controls.

void OnInit() override

Called just prior to when the control is attached, after its delegate and graphics member variable se...

A basic control to display some text.

A vector button/momentary switch control.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

bool IsHit(float x, float y) const override

Hit test the control.

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

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.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void OnMouseOut() override

Implement this method to respond to a mouseout event on this control.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void OnMouseOver(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouseover event on this control.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void OnInit() override

Called just prior to when the control is attached, after its delegate and graphics member variable se...

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.

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.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void OnInit() override

Called just prior to when the control is attached, after its delegate and graphics member variable se...

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnMouseOver(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouseover event on this control.

bool IsHit(float x, float y) const override

Hit test the control.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void OnMouseDblClick(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse double click event on this control.

void OnMouseUp(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse up event on this control.

virtual IRECT GetKnobDragBounds() override

Get the area for which mouse deltas will be used to calculate the amount dragging changes the control...

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void SetDirty(bool push, int valIdx=kNoValIdx) override

Mark the control as dirty, i.e.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void AddPlotFunc(const IColor &color, const IPlotFunc &func)

add a new function to the plot

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.

std::function< double(double)> IPlotFunc

IVPlotControl passes values between 0 and 1 to this object, that are the plot normalized x values.

int GetButtonForPoint(float x, float y) const override

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.

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void OnMouseOver(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouseover event on this control.

void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod) override

Implement this method to respond to a mouse drag event on this control.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

IVSlideSwitchControl(const IRECT &bounds, int paramIdx=kNoParameter, const char *label="", const IVStyle &style=DEFAULT_STYLE, bool valueInButton=false, EDirection direction=EDirection::Horizontal)

Construct a new IVSlideSwitchControl, with a parameter.

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void SetDirty(bool push, int valIdx=kNoValIdx) override

Mark the control as dirty, i.e.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void OnMouseOver(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouseover event on this control.

void SetDirty(bool push, int valIdx=kNoValIdx) override

Mark the control as dirty, i.e.

void OnMouseUp(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse up event on this control.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void OnMouseDblClick(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse double click event on this control.

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

bool IsHit(float x, float y) const override

Hit test the control.

void OnInit() override

Called just prior to when the control is attached, after its delegate and graphics member variable se...

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnInit() override

Called just prior to when the control is attached, after its delegate and graphics member variable se...

bool IsHit(float x, float y) const override

Hit test the control.

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void SetDirty(bool push, int valIdx=kNoValIdx) override

Mark the control as dirty, i.e.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void Draw(IGraphics &g) override

Draw the control to the graphics context.

A vector "tab" multi switch control.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

virtual bool IsHit(float x, float y) const override

Hit test the control.

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

virtual void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

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.

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnMouseOver(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouseover event on this control.

virtual int GetButtonForPoint(float x, float y) const

void OnInit() override

Called just prior to when the control is attached, after its delegate and graphics member variable se...

const char * GetSelectedLabelStr() const

returns the label string on the selected tab

void DrawValue(IGraphics &g, bool mouseOver) override

Draw the IVControl value text.

void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

A base class for mult-strip/track controls, such as multi-sliders, meters Track refers to the channel...

void OnMouseOver(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouseover event on this control.

void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

virtual void DrawBackground(IGraphics &g, const IRECT &r) override

Draw the IVControl background (usually transparent)

void OnMouseDown(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse down event on this control.

void DrawWidget(IGraphics &g) override

Draw the IVControl main widget (override)

void OnMouseDrag(float x, float y, float dX, float dY, const IMouseMod &mod) override

Implement this method to respond to a mouse drag event on this control.

void OnResize() override

Called when IControl is constructed or resized using SetRect().

void Draw(IGraphics &g) override

Draw the control to the graphics context.

void OnMouseUp(float x, float y, const IMouseMod &mod) override

Implement this method to respond to a mouse up event on this control.

A base interface to be combined with IControl for vectorial controls "IVControls",...

virtual void DrawPressableShape(IGraphics &g, EVShape shape, const IRECT &bounds, bool pressed, bool mouseOver, bool disabled)

Call one of the DrawPressableShape methods.

void SetColor(EVColor colorIdx, const IColor &color)

Set one of the IVColors that style the IVControl.

IRECT MakeRects(const IRECT &parent, bool hasHandle=false)

Calculate the rectangles for the various areas, depending on the style.

virtual void DrawBackground(IGraphics &g, const IRECT &rect)

Draw the IVControl background (usually transparent)

virtual void SetStyle(const IVStyle &style)

Set the Style of this IVControl.

IRECT DrawPressableTriangle(IGraphics &g, const IRECT &bounds, bool pressed, bool mouseOver, float angle, bool disabled)

Draw a triangle-shaped vector button.

float GetRoundedCornerRadius(const IRECT &bounds) const

Get the radius of rounded corners for a rectangle, based on the style roundness factor.

virtual void DrawValue(IGraphics &g, bool mouseOver)

Draw the IVControl value text.

void AttachIControl(IControl *pControl, const char *label)

Call in the constructor of your IVControl to link the IVectorBase and IControl.

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.

virtual void DrawLabel(IGraphics &g)

Draw the IVControl label text.

const IColor & GetColor(EVColor color) const

Get value of a specific EVColor in the IVControl.

void SplashClickActionFunc(IControl *pCaller)

The splash click action function is used by IVControls to start SplashAnimationFunc.

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.

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.

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.

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'.

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...

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.

ISenderData is used to represent a typed data packet, that may contain values for multiple channels.

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.