Krotos Modules 3
Loading...
Searching...
No Matches
KwidgetGUI_XyPad.cpp
Go to the documentation of this file.
1namespace krotos
2{
3 const String KwidgetGUI_XyPad::ComponentIds::ButtonNoteTriggerId("noteTriggerToggleButton");
4
6 : KwidgetGUI(owner), m_grainVisualiser(std::make_unique<GrainVisualiser>())
7 {
8 setLookAndFeel(&m_lookAndFeelv4);
10
11 addAndMakeVisible(m_grainVisualiser.get());
12 addMouseListener(this, true);
13 auto currentMode = dynamic_cast<Kwidget_XyPad*>(&getOwner())->getCurrentMode();
14
15 m_editableLabelX = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
16 m_editableLabelX->getAttachment() =
18 m_editableLabelX->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
19 m_editableLabelX->getLabel().setJustificationType(Justification::centredRight);
20 addAndMakeVisible(m_editableLabelX.get());
21
22 m_editableLabelY = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
23 m_editableLabelY->getAttachment() =
25 m_editableLabelY->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
26 m_editableLabelY->getLabel().setJustificationType(Justification::centredLeft);
27 addAndMakeVisible(m_editableLabelY.get());
28
29 switch (currentMode)
30 {
32 m_xyButton.createMask(KrotosBinaryData::XYPad_2Zone_svg, KrotosBinaryData::XYPad_2Zone_svgSize);
33 break;
34 }
37 m_xyButton.createMask(KrotosBinaryData::XYPad_Distance_svg, KrotosBinaryData::XYPad_Distance_svgSize);
38 // Change centering of x,y labels
39 m_editableLabelX->getLabel().setJustificationType(Justification::centredLeft);
40 m_editableLabelY->getLabel().setJustificationType(Justification::centred);
41 // FOR NOW COPY WHAT WE HAVE IN 4 ZONE - Reposition after Nikolas Designs
42 // Create two additional labels
43 m_editableLabelW = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
44 m_editableLabelW->getAttachment() =
46 m_editableLabelW->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
47 m_editableLabelW->getLabel().setJustificationType(Justification::centred);
48 addAndMakeVisible(m_editableLabelW.get());
49
50 m_editableLabelZ = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
51 m_editableLabelZ->getAttachment() =
53 m_editableLabelZ->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
54 m_editableLabelZ->getLabel().setJustificationType(Justification::centredLeft);
55 addAndMakeVisible(m_editableLabelZ.get());
56 break;
57 }
59 m_xyButton.createMask(KrotosBinaryData::XYPad_Peak_svg, KrotosBinaryData::XYPad_Peak_svgSize);
60
61 // Change centering of x,y labels
62 m_editableLabelX->getLabel().setJustificationType(Justification::centredLeft);
63 m_editableLabelY->getLabel().setJustificationType(Justification::centredRight);
64 // FOR NOW COPY WHAT WE HAVE IN 4 ZONE - Reposition after Nikolas Designs
65 // Create two additional labels
66 m_editableLabelW = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
67 m_editableLabelW->getAttachment() =
69 m_editableLabelW->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
70 m_editableLabelW->getLabel().setJustificationType(Justification::centredRight);
71 addAndMakeVisible(m_editableLabelW.get());
72
73 m_editableLabelZ = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
74 m_editableLabelZ->getAttachment() =
76 m_editableLabelZ->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
77 m_editableLabelZ->getLabel().setJustificationType(Justification::centredLeft);
78 addAndMakeVisible(m_editableLabelZ.get());
79 break;
80 }
82 m_xyButton.createMask(KrotosBinaryData::XYPad_4Zone_svg, KrotosBinaryData::XYPad_4Zone_svgSize);
83 // Change centering of x,y labels
84 m_editableLabelX->getLabel().setJustificationType(Justification::centredLeft);
85 m_editableLabelY->getLabel().setJustificationType(Justification::centredRight);
86 // FOR NOW COPY WHAT WE HAVE IN 4 ZONE - Reposition after Nikolas Designs
87 // Create two additional labels
88 m_editableLabelW = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
89 m_editableLabelW->getAttachment() =
91 m_editableLabelW->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
92 m_editableLabelW->getLabel().setJustificationType(Justification::centredRight);
93 addAndMakeVisible(m_editableLabelW.get());
94
95 m_editableLabelZ = std::make_unique<AttachedLabel>(owner.getKwidgetLabel());
96 m_editableLabelZ->getAttachment() =
98 m_editableLabelZ->getLabel().setColour(juce::Label::textColourId, juce::Colours::lightgrey);
99 m_editableLabelZ->getLabel().setJustificationType(Justification::centredLeft);
100 addAndMakeVisible(m_editableLabelZ.get());
101 break;
102 }
103 case Kwidget_XyPad::Polar: { // TODO: If we decide we want this XYPad we need a mask from Nikolas (best
104 // concentric circles with fading alpha)
105 m_xyButton.createMask(KrotosBinaryData::XYPad_2Zone_svg, KrotosBinaryData::XYPad_2Zone_svgSize);
106 break;
107 }
108 }
109
110 addAndMakeVisible(m_xyButton);
111
112 // Set up toggle label
113 addChildComponent(m_toggleLabel);
114 m_toggleLabel.setVisible(owner.getParameter(Parameters::toggleOn)->getValue() > 0.0f);
115 m_toggleLabel.setJustificationType(Justification::centredBottom);
116 m_toggleLabel.setBorderSize(BorderSize<int>(8));
117 m_toggleLabel.setColour(Label::textColourId, Colours::white.withAlpha(0.3f));
118 m_toggleLabel.setText("Click or drag\nto trigger a performance", dontSendNotification);
119 m_toggleLabel.setInterceptsMouseClicks(false, false);
121 Parameters::toggleOn, [=](float value) { m_toggleLabel.setVisible(value > 0.0f); });
122
123 auto& xParam = *owner.getParameter(Parameters::posX)->getAttachedParameter();
124 auto& yParam = *owner.getParameter(Parameters::posY)->getAttachedParameter();
125 auto& clickParam = *owner.getParameter(Parameters::onClick)->getAttachedParameter();
126 auto& toggleParam = *owner.getParameter(Parameters::toggleOn)->getAttachedParameter();
127
129 new XYButtonParameterAttachment(xParam, yParam, clickParam, toggleParam, m_xyButton));
131
132 addAndMakeVisible(m_contextMenu);
133 m_contextMenu.onClick = [&] { showContextMenu(); };
134
135#if ENABLE_REFORMER
136 // Starts slow because we are only polling for the existence of a suitable
137 // kwidget to display
138 startTimerSlow(true);
139#endif
140 }
141
142 KwidgetGUI_XyPad::~KwidgetGUI_XyPad() { setLookAndFeel(nullptr); }
143
144#if ENABLE_REFORMER
145 void KwidgetGUI_XyPad::startTimerSlow(bool goSlow)
146 {
147 if (goSlow && !m_goSlow)
148 {
149 m_goSlow = true;
150 startTimerHz(PAINT_REFRESH_TIMER_HZ_SLOW);
151 }
152 else if (!goSlow && m_goSlow)
153 {
154 m_goSlow = false;
155 startTimerHz(PAINT_REFRESH_TIMER_HZ_NORMAL);
156 }
157 }
158
159 void KwidgetGUI_XyPad::timerCallback()
160 {
161 if (auto toggleParameter = getOwner().getParameter(Parameters::toggleOn); !toggleParameter->isOn())
162 {
163 // If "Note Trigger" is not on then
164 // we are not going to paint in the grain visualiser
165 // Switch on the default XY button background
167 m_grainVisualiser->setVisible(false);
168 // Do slow polling to save CPU
169 startTimerSlow(true);
170 return; // Then go home
171 }
172
173 m_grainVisualiser->setPuckPosition(m_xyButton.getPuckPosition());
174
175 // GEt a pointer to the kwidget audio processor
176 auto kProcessor = static_cast<Kwidget_XyPad&>(getOwner()).getKwidgetAudioProcessorReference();
177 if (kProcessor == nullptr)
178 {
179 return; // Return if no access to kwidget audio processor
180 }
181
182 auto& thisXyPadId = getKwidgetID();
183
184 // Get a list of all the KwidgetFactory::KwidgetType::Reformer type kwidgets in the system
185 auto reformerKwidgets =
186 kProcessor->getKwidgetsOfTypeWithAccessPermission(KwidgetFactory::KwidgetType::Reformer, thisXyPadId);
187
188 if (m_activeReformerKwidgets != reformerKwidgets.size())
189 {
190 m_grainVisualiser->requestBackgroundCacheRegeneration();
191 m_activeReformerKwidgets = reformerKwidgets.size();
192 }
193
194 // Are there any Reformer kwidgets to display ?
195 if (reformerKwidgets.size() == 0)
196 {
197 // No reformer kwidget was found - so we are not going to paint in the grain visualiser
198 // Instead, we switch on the default XY button background
200 m_grainVisualiser->setVisible(false);
201 startTimerSlow(true);
202 if (m_frameCooldownCounter < FRAME_COOLDOWN)
203 {
204 // Draw a few frames after grains stop playing
205 m_frameCooldownCounter++;
206 m_grainVisualiser->repaint();
207 }
208 }
209 else // At least one reformer kwidget was found
210 {
211 // move the x and y labels for XYButton when using reformer kwidget
212 m_editableLabelX->getLabel().setJustificationType(Justification::centred);
213 m_editableLabelY->getLabel().setJustificationType(Justification::centred);
214 resized();
215
216 m_grainVisualiser->prepareToAddSampleEngines();
217 for (int i = 0; i < jmin<int>(GrainVisualiser::ReformerMaxDisplayedInstances, reformerKwidgets.size()); i++)
218 {
219 // Cast Kwidget pointer into a reformer kwidget
220 auto reformerKwidget = dynamic_cast<Kwidget_Reformer*>(reformerKwidgets[i]);
221 if (reformerKwidget != nullptr)
222 {
223 // Copy the sound data which we want to display
224 m_grainVisualiser->shallowCopy(reformerKwidget->getSound());
225 }
226 // We no longer need a lock on the kwidget since we have copied the data we need
227 reformerKwidgets[i]->finishedAccessing(thisXyPadId);
228 }
229 // This call allows us to count the active engines, and detect any change
230 // in that count. If the number of active engines changes, a re-draw of the
231 // background cache is triggered
232 m_grainVisualiser->finishedAddingSampleEngines();
233
234 // At this point, all the data which the grain visualiser requires to do its job
235 // has been copied into the grain visualiser, and we have handed back the locks
236 // on the kwidgets which supplied the data using finishedAccessing()
237
238 // No further resource locking is required. Grain visualiser paint() has its own copy
239 // of the data now and can use it freely. This timer callback is the only place
240 // where that data can be modified, added or removed, and this is on the message thread
241 // Since paint() calls are also on the message thread, there is no danger that data
242 // will change during a paint call
243
244 // Switch to full speed display rate
245 startTimerSlow(false);
246 m_frameCooldownCounter = 0;
248 m_grainVisualiser->setVisible(true);
249 m_grainVisualiser->setPerformMode(m_performMode);
250 m_grainVisualiser->repaint();
251 }
252 }
253
254#endif
255
257
259 {
260 auto xyButtonBounds = m_xyButton.getBounds();
261
262 int maxDimension = jmax(xyButtonBounds.getWidth(), xyButtonBounds.getHeight());
263 float radius = 0.7f * maxDimension;
264 auto currentMode = dynamic_cast<Kwidget_XyPad*>(&getOwner())->getCurrentMode();
265 switch (currentMode)
266 {
268 // g.setColour(Colours::aqua);
269 // g.drawRect(xyButtonBounds);
270
271 // Top left corner Arc
272 juce::Path path;
273 path.addCentredArc(
274 /*centreX*/ static_cast<float>(xyButtonBounds.getTopLeft().getX()),
275 /*centreY*/ static_cast<float>(xyButtonBounds.getTopLeft().getY()),
276 /*radiusX*/ radius,
277 /*radiusY*/ radius,
278 /*rotationOfEllipse*/ MathConstants<float>::halfPi,
279 /*fromRadians*/ 0.0f,
280 /*toRadians*/ MathConstants<float>::halfPi,
281 /*startAsNewSubPath*/ true);
282 g.setColour(Colours::lightgrey);
283 g.strokePath(path, PathStrokeType(static_cast<float>(3.0f)));
284 // Top right corner Arc
285 juce::Path path1;
286 path1.addCentredArc(
287 /*centreX*/ static_cast<float>(xyButtonBounds.getTopRight().getX()),
288 /*centreY*/ static_cast<float>(xyButtonBounds.getTopRight().getY()),
289 /*radiusX*/ radius,
290 /*radiusY*/ radius,
291 /*rotationOfEllipse*/ MathConstants<float>::twoPi,
292 /*fromRadians*/ 0.0f,
293 /*toRadians*/ MathConstants<float>::halfPi * 3.0f,
294 /*startAsNewSubPath*/ true);
295 g.setColour(Colours::darkgrey);
296 g.strokePath(path1, PathStrokeType(static_cast<float>(3.0f)));
297 // Bottom left corner Arc
298 juce::Path path2;
299 path2.addCentredArc(
300 /*centreX*/ static_cast<float>(xyButtonBounds.getBottomLeft().getX()),
301 /*centreY*/ static_cast<float>(xyButtonBounds.getBottomLeft().getY()),
302 /*radiusX*/ radius,
303 /*radiusY*/ radius,
304 /*rotationOfEllipse*/ MathConstants<float>::twoPi,
305 /*fromRadians*/ 0.0f,
306 /*toRadians*/ MathConstants<float>::halfPi,
307 /*startAsNewSubPath*/ true);
308 g.setColour(Colours::blanchedalmond);
309 g.strokePath(path2, PathStrokeType(static_cast<float>(3.0f)));
310 // Bottom right corner Arc
311 juce::Path path3;
312 path3.addCentredArc(
313 /*centreX*/ static_cast<float>(xyButtonBounds.getBottomRight().getX()),
314 /*centreY*/ static_cast<float>(xyButtonBounds.getBottomRight().getY()),
315 /*radiusX*/ radius,
316 /*radiusY*/ radius,
317 /*rotationOfEllipse*/ MathConstants<float>::twoPi,
318 /*fromRadians*/ MathConstants<float>::halfPi * 3.0f,
319 /*toRadians*/ MathConstants<float>::twoPi,
320 /*startAsNewSubPath*/ true);
321 g.setColour(Colours::darkcyan);
322 g.strokePath(path3, PathStrokeType(static_cast<float>(3.0f)));
323 break;
324 }
326 // g.setColour(Colours::aqua);
327 // g.drawRect(xyButtonBounds);
328
329 g.setColour(Colours::lightgrey);
330 auto lineHeight = static_cast<float>(xyButtonBounds.getHeight() + xyButtonBounds.getHeight() / 8.0f);
331 auto linePoint = xyButtonBounds.getWidth() / 2;
332 auto start = static_cast<float>(xyButtonBounds.getTopLeft().getY());
333 g.drawVerticalLine(linePoint, start, lineHeight);
334 }
335 }
336 }
337
339 {
340 auto currentMode = dynamic_cast<Kwidget_XyPad*>(&getOwner())->getCurrentMode();
341
342 m_ignorePadding = true;
344 Rectangle<int> mainRect = m_currentBounds;
345
346 float masterWidth = (float)mainRect.getWidth();
347 float masterHeight = (float)mainRect.getHeight();
348
349 if (m_contextMenu.isVisible())
350 {
351 auto contextMenuRect = mainRect.removeFromRight(constants.contextMenuSize);
352 mainRect.removeFromBottom(constants.contextMenuSize);
353
354 masterWidth = (float)mainRect.getWidth();
355 masterHeight = (float)mainRect.getHeight();
356
357 contextMenuRect.removeFromTop(constants.contextMenuMargin);
358 m_contextMenu.setBounds(contextMenuRect.removeFromTop(constants.contextMenuSize));
359 }
360
361 // calculate xyButton dimensions to resize
362 auto xyButtonCenter = mainRect.getCentre().toFloat(); // Point<float>(masterWidth * 0.5f, masterHeight * 0.5f);
363 auto xyButtonBounds = Rectangle<float>()
364 .withCentre(xyButtonCenter)
365 .withSizeKeepingCentre(masterWidth, masterHeight - constants.LabelPadding);
366 m_xyButton.setBounds(xyButtonBounds.toNearestInt());
367 m_grainVisualiser->setBounds(xyButtonBounds.toNearestInt());
368
369 // generic label dimensions
370 // TODO These values should come from LaF
371 auto labelFont = Font().withPointHeight(static_cast<float>(constants.FontSize));
372 labelFont.setExtraKerningFactor(constants.KerningFactor);
373 int labelHeight = constants.LabelPadding / 2;
374 int labelWidth = mainRect.getWidth() / 2;
375
376 // hide toggle label if xy pad is smaller than small width
377 auto toggleLabelBounds =
378 masterWidth > constants.mediumXYWidth ? xyButtonBounds.toNearestInt() : Rectangle<int>(0, 0);
379 m_toggleLabel.setBounds(
380 toggleLabelBounds.removeFromBottom(static_cast<int>(toggleLabelBounds.getHeight() * 0.3f)));
381 m_toggleLabel.setFont(labelFont);
382
383 // toggle button bounds
384 Rectangle<int> toggleButtonBounds;
385
386 switch (currentMode)
387 {
389 Rectangle<int> labelBoundsX;
390 Rectangle<int> labelBoundsY;
391
393 {
394 // label X
395 labelBoundsX = Rectangle<int>(mainRect.getWidth() - labelWidth, mainRect.getHeight() - labelHeight,
396 labelWidth, labelHeight);
397
398 // label Y
399 labelBoundsY = Rectangle<int>(mainRect.getX(), mainRect.getY(), labelWidth, labelHeight);
400 }
401 else // if we're dealing with a reformer attachment
402 {
403 // Calculate the center position for the labels
404 int labelCenterX = mainRect.getX() + mainRect.getWidth() / 2;
405
406 // Calculate half width of the label
407 int halfLabelWidth = labelWidth / 2;
408
409 // Calculate the Y position for the labels, adjusting for labelHeight
410 int labelYPosition = mainRect.getY();
411
412 // label X (centered underneath the xy button)
413 labelBoundsX = Rectangle<int>(labelCenterX - halfLabelWidth, mainRect.getHeight() - labelHeight,
414 labelWidth, labelHeight);
415
416 // label Y (centered above the xy button)
417 labelBoundsY = Rectangle<int>(labelCenterX - halfLabelWidth, labelYPosition, labelWidth, labelHeight);
418 }
419
420 m_editableLabelX->setBounds(labelBoundsX);
421 m_editableLabelX->getLabel().setFont(labelFont);
422
423 m_editableLabelY->setBounds(labelBoundsY);
424 m_editableLabelY->getLabel().setFont(labelFont);
425
426 // toggle button bounds
427 toggleButtonBounds =
428 Rectangle<int>(mainRect.getX(), mainRect.getHeight() - labelHeight, labelWidth / 3, labelHeight);
429 break;
430 }
432 // label X
433 Rectangle<int> labelBoundsX = Rectangle<int>(mainRect.getX(), mainRect.getY(), labelWidth, labelHeight);
434 m_editableLabelX->setBounds(labelBoundsX);
435 m_editableLabelX->getLabel().setFont(labelFont);
436
437 // label Y
438 Rectangle<int> labelBoundsY =
439 Rectangle<int>((mainRect.getWidth() / 2.0f) - 50, mainRect.getY(), labelWidth, labelHeight);
440 m_editableLabelY->setBounds(labelBoundsY);
441 m_editableLabelY->getLabel().setFont(labelFont);
442
443 // label W
444 Rectangle<int> labelBoundsW = Rectangle<int>((mainRect.getWidth() / 2.0f) - 50,
445 mainRect.getHeight() - labelHeight, labelWidth, labelHeight);
446 m_editableLabelW->setBounds(labelBoundsW);
447 m_editableLabelW->getLabel().setFont(labelFont);
448
449 // label Z
450 Rectangle<int> labelBoundsZ = Rectangle<int>(mainRect.getX(), mainRect.getHeight() - labelHeight,
451 labelWidth - constants.toggleOffset, labelHeight);
452 m_editableLabelZ->setBounds(labelBoundsZ);
453 m_editableLabelZ->getLabel().setFont(labelFont);
454
455 // put toggle in the middle so it's visible for now
456 toggleButtonBounds = Rectangle<int>(0, mainRect.getHeight() - labelHeight, labelWidth / 3, labelHeight);
457 break;
458 }
459 case Kwidget_XyPad::Peak: {
460 // FOR NOW COPY WHAT WE HAVE IN 4 ZONE - Reposition after Nikolas Designs
461 // label X
462 Rectangle<int> labelBoundsX = Rectangle<int>(mainRect.getX(), mainRect.getY(), labelWidth, labelHeight);
463 m_editableLabelX->setBounds(labelBoundsX);
464 m_editableLabelX->getLabel().setFont(labelFont);
465
466 // label Y
467 Rectangle<int> labelBoundsY =
468 Rectangle<int>(mainRect.getWidth() - labelWidth, mainRect.getY(), labelWidth, labelHeight);
469 m_editableLabelY->setBounds(labelBoundsY);
470 m_editableLabelY->getLabel().setFont(labelFont);
471
472 // label W
473 Rectangle<int> labelBoundsW = Rectangle<int>(mainRect.getWidth() - labelWidth,
474 mainRect.getHeight() - labelHeight, labelWidth, labelHeight);
475 m_editableLabelW->setBounds(labelBoundsW);
476 m_editableLabelW->getLabel().setFont(labelFont);
477
478 // label Z
479 Rectangle<int> labelBoundsZ = Rectangle<int>(mainRect.getX(), mainRect.getHeight() - labelHeight,
480 labelWidth - constants.toggleOffset, labelHeight);
481 m_editableLabelZ->setBounds(labelBoundsZ);
482 m_editableLabelZ->getLabel().setFont(labelFont);
483
484 // put toggle in the middle so it's visible for now
485 toggleButtonBounds = Rectangle<int>((mainRect.getWidth() / 2.0f) - constants.toggleOffset,
486 mainRect.getHeight() - labelHeight, labelWidth / 3, labelHeight);
487 break;
488 }
490 // label X
491 Rectangle<int> labelBoundsX = Rectangle<int>(mainRect.getX(), mainRect.getY(), labelWidth, labelHeight);
492 m_editableLabelX->setBounds(labelBoundsX);
493 m_editableLabelX->getLabel().setFont(labelFont);
494
495 // label Y
496 Rectangle<int> labelBoundsY =
497 Rectangle<int>(mainRect.getWidth() - labelWidth, mainRect.getY(), labelWidth, labelHeight);
498 m_editableLabelY->setBounds(labelBoundsY);
499 m_editableLabelY->getLabel().setFont(labelFont);
500
501 // label W
502 Rectangle<int> labelBoundsW = Rectangle<int>(mainRect.getWidth() - labelWidth,
503 mainRect.getHeight() - labelHeight, labelWidth, labelHeight);
504 m_editableLabelW->setBounds(labelBoundsW);
505 m_editableLabelW->getLabel().setFont(labelFont);
506
507 // label Z
508 Rectangle<int> labelBoundsZ = Rectangle<int>(mainRect.getX(), mainRect.getHeight() - labelHeight,
509 labelWidth - constants.toggleOffset, labelHeight);
510 m_editableLabelZ->setBounds(labelBoundsZ);
511 m_editableLabelZ->getLabel().setFont(labelFont);
512
513 // put toggle in the middle so it's visible for now
514 toggleButtonBounds = Rectangle<int>((mainRect.getWidth() / 2.0f) - constants.toggleOffset,
515 mainRect.getHeight() - labelHeight, labelWidth / 3, labelHeight);
516 break;
517 }
519 Rectangle<int> labelBoundsX;
520 Rectangle<int> labelBoundsY;
522 {
523 // label X
524 labelBoundsX = Rectangle<int>(mainRect.getWidth() - labelWidth, mainRect.getHeight() - labelHeight,
525 labelWidth, labelHeight);
526 // label Y
527 labelBoundsY = Rectangle<int>(mainRect.getX(), mainRect.getY(), labelWidth, labelHeight);
528 }
529 else // if we're dealing with a reformer attachment
530 {
531 // Calculate the center position for the labels
532 int labelCenterX = mainRect.getX() + mainRect.getWidth() / 2;
533 // Calculate half width of the label
534 int halfLabelWidth = labelWidth / 2;
535 // Calculate the Y position for the labels, adjusting for labelHeight
536 int labelYPosition = mainRect.getY();
537 // label X (centered underneath the xy button)
538 labelBoundsX = Rectangle<int>(labelCenterX - halfLabelWidth, mainRect.getHeight() - labelHeight,
539 labelWidth, labelHeight);
540 // label Y (centered above the xy button)
541 labelBoundsY = Rectangle<int>(labelCenterX - halfLabelWidth, labelYPosition, labelWidth, labelHeight);
542 }
543 m_editableLabelX->setBounds(labelBoundsX);
544 m_editableLabelX->getLabel().setFont(labelFont);
545 m_editableLabelY->setBounds(labelBoundsY);
546 m_editableLabelY->getLabel().setFont(labelFont);
547 // toggle button bounds
548 toggleButtonBounds =
549 Rectangle<int>(mainRect.getX(), mainRect.getHeight() - labelHeight, labelWidth / 3, labelHeight);
550 break;
551 }
552 }
553
554 if (m_toggleVisibility == false && m_performMode == true)
555 {
556 m_editableLabelX->getLabel().setEditable(false);
557 m_editableLabelY->getLabel().setEditable(false);
558 if (currentMode == Kwidget_XyPad::FourZone || currentMode == Kwidget_XyPad::Peak ||
559 currentMode == Kwidget_XyPad::Distance)
560 {
561 m_editableLabelW->getLabel().setEditable(false);
562 m_editableLabelZ->getLabel().setEditable(false);
563 }
564 m_contextMenu.setVisible(false);
565 }
566 else
567 {
568 m_editableLabelX->getLabel().setEditable(false, false, true, true);
569 m_editableLabelY->getLabel().setEditable(false, false, true, true);
570 if (currentMode == Kwidget_XyPad::FourZone || currentMode == Kwidget_XyPad::Peak ||
571 currentMode == Kwidget_XyPad::Distance)
572 {
573 m_editableLabelW->getLabel().setEditable(false, false, true, true);
574 m_editableLabelZ->getLabel().setEditable(false, false, true, true);
575 }
576 m_contextMenu.setVisible(true);
577 }
578 }
579
581 {
582 // set a boolean for visibility for the note toggle control
583 // but only hide when m_toggleVisibility is false and we're
584 // displaying in the perform mode.
585 m_toggleVisibility = visible;
586 }
587
589 {
590 PopupMenu menu;
591 enum menuOptions
592 {
593 NoteTrigger = 1
594 };
595 menu.addItem(menuOptions::NoteTrigger, "Note Trigger", true,
596 getOwner().getParameter(Parameters::toggleOn)->isOn());
597
598 std::function<void(int)> menuCallback = [&](int itemResultID) {
599 switch (static_cast<menuOptions>(itemResultID))
600 {
601 case menuOptions::NoteTrigger:
602 // Get the parameter again since menu callback may be separated in scope
603 auto noteTriggerParameter = getOwner().getParameter(Parameters::toggleOn);
604 noteTriggerParameter->set(!noteTriggerParameter->isOn());
605 break;
606 }
607 };
608
609 menu.showMenuAsync(PopupMenu::Options{}
610 .withTargetComponent(m_contextMenu)
611 .withMinimumNumColumns(1)
612 .withMinimumWidth(114)
613 .withStandardItemHeight(20),
614 menuCallback);
615 }
616} // namespace krotos
A component to display the grains of the reformer engine.
Definition GrainVisualiser.h:66
static constexpr int ReformerMaxDisplayedInstances
Definition GrainVisualiser.h:70
GenericParameter * getAttachedParameter()
Definition KParameter.cpp:170
float getValue() const override
Definition KParameter.cpp:181
void set(float newValue)
Definition KParameter.cpp:128
Definition Kwidget_XyPad.h:4
@ Peak
Definition Kwidget_XyPad.h:23
@ Polar
Definition Kwidget_XyPad.h:26
@ FourZone
Definition Kwidget_XyPad.h:24
@ Simple
Definition Kwidget_XyPad.h:22
@ Distance
Definition Kwidget_XyPad.h:25
ContextMenuButton m_contextMenu
Definition KwidgetGUI_XyPad.h:88
~KwidgetGUI_XyPad()
Definition KwidgetGUI_XyPad.cpp:142
void setToggleVisibility(bool visible)
Definition KwidgetGUI_XyPad.cpp:580
KwidgetGUI_XyPad(Kwidget &owner)
Definition KwidgetGUI_XyPad.cpp:5
std::unique_ptr< krotos::GrainVisualiser > m_grainVisualiser
Definition KwidgetGUI_XyPad.h:85
void paint(Graphics &g) override
Definition KwidgetGUI_XyPad.cpp:256
bool m_toggleVisibility
Definition KwidgetGUI_XyPad.h:82
std::unique_ptr< AttachedLabel > m_editableLabelZ
Definition KwidgetGUI_XyPad.h:76
void resized() override
Definition KwidgetGUI_XyPad.cpp:338
std::unique_ptr< XYButtonParameterAttachment > m_xyButtonAttachment
Definition KwidgetGUI_XyPad.h:68
XYButton m_xyButton
Definition KwidgetGUI_XyPad.h:66
std::unique_ptr< AttachedLabel > m_editableLabelX
Definition KwidgetGUI_XyPad.h:71
struct krotos::KwidgetGUI_XyPad::Constants constants
bool m_goSlow
Definition KwidgetGUI_XyPad.h:50
bool m_performMode
Definition KwidgetGUI_XyPad.h:83
void drawDebugGraphics(Graphics &g)
Definition KwidgetGUI_XyPad.cpp:258
juce::Label m_toggleLabel
Definition KwidgetGUI_XyPad.h:67
std::unique_ptr< ParameterAttachment > m_toggleLabelAttachment
Definition KwidgetGUI_XyPad.h:69
void showContextMenu()
Definition KwidgetGUI_XyPad.cpp:588
LookAndFeel_V4 m_lookAndFeelv4
Definition KwidgetGUI_XyPad.h:92
std::unique_ptr< AttachedLabel > m_editableLabelW
Definition KwidgetGUI_XyPad.h:75
std::unique_ptr< AttachedLabel > m_editableLabelY
Definition KwidgetGUI_XyPad.h:72
Interface for a UI Component that controls a KwidgetProcessor.
Definition KwidgetGUI.h:24
std::unique_ptr< LabelCustomParameterAttachment > createCustomParameterAttachment(const String &paramID, Label &label)
Definition KwidgetGUI.cpp:100
std::unique_ptr< SliderParameterAttachment > createParameterAttachment(const String &paramID, Slider &slider)
Definition KwidgetGUI.cpp:72
void paint(Graphics &g) override
Definition KwidgetGUI.cpp:26
Kwidget & getOwner()
Definition KwidgetGUI.cpp:106
Rectangle< int > m_currentBounds
Definition KwidgetGUI.h:146
void resized() override
Definition KwidgetGUI.cpp:45
const String & getKwidgetID() const
Definition KwidgetGUI.cpp:70
void setRenderStyle(RenderStyle newStyle)
Definition KwidgetGUI.cpp:114
bool m_ignorePadding
Definition KwidgetGUI.h:145
Definition Kwidget.h:8
KParameter * getParameter(const String &parameterID) const noexcept
Get a raw pointer to a KParameter belonging to this Kwidget's KwidgetProcessor. Useful for low overhe...
Definition Kwidget.cpp:168
virtual const String & getKwidgetLabel()
Definition Kwidget.cpp:378
bool getPaintBackground()
Definition XYButton.h:67
void setMaskNotStreched()
Definition XYButton.h:69
void setPaintBackground(bool val)
Definition XYButton.h:64
void createMask(const void *data, const size_t numBytes)
Definition XYButton.cpp:274
Point< float > getPuckPosition()
Definition XYButton.h:42
A class that creates a custom ParameterAttachment between the x and y axis positions of the puck with...
Definition XYButton.h:131
Definition AirAbsorptionFilter.cpp:2
static const String editableLabelY
Definition Kwidget_XyPad.h:38
static const String editableLabelZ
Definition Kwidget_XyPad.h:39
static const String posX
Definition Kwidget_XyPad.h:33
static const String onClick
Definition Kwidget_XyPad.h:35
static const String toggleOn
Definition Kwidget_XyPad.h:36
static const String posY
Definition Kwidget_XyPad.h:34
static const String editableLabelX
Definition Kwidget_XyPad.h:37
static const String editableLabelW
Definition Kwidget_XyPad.h:40
static const String Reformer
Definition KwidgetFactory.h:14
static const String ButtonNoteTriggerId
Definition KwidgetGUI_XyPad.h:44
const int FontSize
Definition KwidgetGUI_XyPad.h:56
const int LabelPadding
Definition KwidgetGUI_XyPad.h:54
const int contextMenuMargin
Definition KwidgetGUI_XyPad.h:63
const int mediumXYWidth
Definition KwidgetGUI_XyPad.h:58
const int contextMenuSize
Definition KwidgetGUI_XyPad.h:62
const float KerningFactor
Definition KwidgetGUI_XyPad.h:57
const int toggleOffset
Definition KwidgetGUI_XyPad.h:60